Interface patterns

From Koha Wiki
Jump to navigation Jump to search

The staff interface to Koha is complex, with over five hundred templates which are used to display an even greater number of distinct pages. With so many different kinds of interfaces it can be hard to stay consistent. There are, however, some established patterns which template creators and editors try to follow. This document elaborates on these.

The header

Almost every page in the staff client includes the same elements at the top of the page, all contained within a region we can call the header, highlighted in this screenshot:

The header menu

At the top of the header is the header menu, a fixed set of menu items on the left and user/login information on the right:

Interface-patterns-staff-client-header-menu.png

While it is possible to customize this menu by adding additional links, the contents of the menu are not context-sensitive, staying the same no matter what page you're on.

The header search

Below the header menu is a region common to almost all staff client pages which contains the Koha logo and the header search form:

Interface-patterns-staff-client-header-search.png

The header search form contains two or more different search options depending on where you are in the staff client. On pages for which there is no relevant search, a default set of options should be used: Check out, Check in, and Search the catalog (currently in an include called circ-search.inc). Other sections of the staff client show a different set of search options based on search tools available for that section. On patron related pages a different patron search option is included:

On cataloging pages the assumption is made that circulation functions are less important than a search specific to the cataloging module:

On the system preferences page a search of system preferences is offered:

Note that one of the goals in selecting which searches are offered is to avoid ambiguity. The cataloging search form omits the standard catalog search because the focus is the cataloging search.

"Check out" and "Catalog search" are often the fallback options for pages which include another module-specific search as the primary search option, but they are not required. Other sections omit those options in favor of a set of completely module-specific options. For instance in Acquisitions where "Vendor Search" and "Orders Search" are the only options.

In practice the primary module-specific search is usually placed first and highlighted. In some cases you might find the same set of search options (e.g. Check out, Check in, and Search the catalog) but find that different options are highlighted by default on different pages: Check out is highlighted on circulation-related pages, but Search the catalog is highlighted on some pages, like Tools, where the search form is in not in a "module-specific" state.

Another factor to consider when designing a header search form is simplicity. In the past we have tried to limit the number of search options to three options which seem most relevant to module the user is in. This has expanded to four in some cases (like the patron module). Current practice in Koha's template design is to make the choice to eliminate the least relevant default search option in order to make room for a module-specific search option: "Check in" is omitted in favor of "Search system preferences" in the system preferences interface.

Breadcrumbs

Below the header region is the breadcrumbs menu. The breadcrumbs menu provides two functions: First, it orients the user to their "location" in the staff client. It should show where they are (with a repetition of the page title) and what module they're in. In some cases it is possible to offer breadcrumb links to intermediate steps in the user's process. In these cases the menu fulfills the second function, offering users direct links to other pages which may be previous pages in a linear workflow or other relevant pages in the module.

Interface-patterns-staff-client-breadcrumbs-example-patrons.png

The breadcrumbs does not (and cannot) show the user exactly the links they have taken to arrive at any particular page. Since breadcrumbs are hard-coded for each template, an assumption must be made about a logical hierarchy of links to offer. In acquisitions, the user may have used an order search to find a particular basket, but the breadcrumbs can't know to show a link back to the order search when viewing the basket. Instead it shows links to a hierarchy of pages related to the basket:


When designing breadcrumbs keep in mind paths the user might want to take which are not offered by any other navigation in the interface. Improvements to breadcrumbs menus are often made based on specific usage patterns which are not accommodated.

Breadcrumb navigation uses Bootstrap markup. In order to abstract the specific elements of the markup and ease the process of upgrading Bootstrap versions, a system of Template::Toolkit WRAPPER directives are used. A typical example might look like this:

    [% WRAPPER breadcrumbs %]
        [% Home breadcrumb automatically included %]
        [% WRAPPER breadcrumb_item %]
            <a href="/cgi-bin/koha/module/module-home.pl"> Module </a>
        [% END %]

        [% IF ( op == 'add_form' || op == 'delete_confirm' ) %]
            [% WRAPPER breadcrumb_item %]
                <a href="/cgi-bin/koha/module/page.pl"> Module page </a>
            [% END %]
        [% END %]

        [% IF op == 'add_form' %]
            [% WRAPPER breadcrumb_item bc_active = 1 %]
                <span>Add form</span>
            [% END %]

        [% ELSIF op == 'delete_confirm' %]
            [% WRAPPER breadcrumb_item bc_active = 1 %]
                <span>Confirm deletion</span>
            [% END %]

        [% ELSE %]
            [% WRAPPER breadcrumb_item bc_active = 1 %]
                <span>Module page</span>
            [% END %]
        [% END #/IF op = add_form %]

    [% END #/ WRAPPER breadcrumbs %]

When the template is rendered in the browser the breadcrumb elements are wrapped in the correct Bootstrap breadcrumb menu markup:

<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
    <ol>
        <li>
            <a href="/cgi-bin/koha/mainpage.pl">Home</a>
        </li>
        <li>
            <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
        </li>
        <li>
            <a href="/cgi-bin/koha/admin/cities.pl">Cities</a>
        </li>
        <li>
            <a href="#" aria-current="page">
                <span>New city</span>
            </a>
        </li>
    </ol>
</nav>

Note that some elements of the template show text wrapped in tags. This is done to ease template translation.

Errors and messages

When Koha needs to communicate something directly to the user it usually takes one of two forms: an informational message or an error message. Each type is used for specific categories of communications, and each has its own global style.

Informational messages

When Koha needs to communicate information to the user about a transaction, status, or some other non-critical event the information should be displayed using the message style. The markup looks like this:

<div class="dialog message">
  Informational message here
</div>

The "dialog" class gives the message its basic orientation and size. The "message" class adds the color which distinguishes it from an error message. Informational messages convey information to the user which does not require action. An informational message doesn't ask the user a question.

Examples

Error messages

When Koha needs to ask the user a question or block an action an error message should be used. Error messages should be used when Koha requires that the user stop and make a decision or when Koha must stop an operation that the user has initiated. Error message markup looks like this:

<div class="dialog alert">
   Error message here
</div>

Again, the "dialog" class gives the message box the same basic style as the information message, but the "alert" class adds a style specific to this type of message.

Examples:

Circulation-error-confirm-checkout.png

Confirm-deletion-error-message.png

Usage

As defined above an information message conveys "non-blocking" information to the user while error messages display information which blocks an operation or requires the user's input. Not all instances of each type of message are currently consistent with these guidelines, so the templates have room for improvement.

The screenshot snippet below is a good example of the two types of messages displayed in combination:

Screenshot showing example of error and informational messages together

These messages appeared in a situation where a number of things were happening at once. The "Cannot place hold" error message conveys the blocking information: that the hold cannot be placed.  The other, informational messages convey information which may be relevant to the user but which does not interfere with the user being able to complete the task at hand.

Views and Actions

Many of the interactions in the Koha staff client can be divided up into two very general categories: Views and actions. The categories determine how the action is displayed in the interface: in a sidebar tab or in a toolbar.

  • Views are ways of looking at information about a record.
  • Actions are things you can do to a record.

These distinctions are the best defined when looking at patrons or bibliographic records.

Patrons
Bibliographic Records
View
Actions
View
Actions
Details
Edit
Normal
New
Fines
Change password
MARC
Edit
Circ history
Duplicate
Items
Save
Messages
Print
Holds
Print

Here's a highlighted screenshot as an example:

Views-versus-actions.png

The distinction between views and actions is a good one to keep in mind when deciding whether to use a link or a button for certain types of interaction. If the interaction can fit into one of those two categories you can group them with existing options.

Page layouts

The Koha staff client uses Bootstrap grids, "a responsive, mobile first fluid grid system that appropriately scales up to 12 columns as the device or viewport size increases."

Common page layouts

Whereas our previous grid system (YUI) had a number of predefined layouts, Bootstrap is much more flexible. Still, there are a number of common layouts currently in use in the staff client templates.

Fluid-width page with adaptive left-hand sidebar

Examples: Circulation, Patrons, Search results

            <div class="main container-fluid">
                <div class="row">
                    <div class="col-sm-10 col-sm-push-2">
                        <main>
                            <!-- Main body of the page -->
                        </main>
                    </div> <!-- /.col-sm-10.col-sm-push-2 -->

                    <div class="col-sm-2 col-sm-pull-10">
                        <aside>
                            <!-- Left-hand sidebar -->
                        </aside>
                    </div> <!-- .col-sm-2.col-sm-pull-10 -->
                 </div> <!-- /.row -->
            </div> <!-- /.main.container-fluid -->


Fluid centered page with no sidebars

Examples: Patron entry, Advanced search, the basic MARC editor

            <div class="main container-fluid">
                <div class="row">
                    <div class="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
                        <main>
                            <!-- Main body of the page -->
                        </main>
                    </div> <!-- /.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 -->
                 </div> <!-- /.row -->
            </div> <!-- /.main.container-fluid -->

The matching "-offset-2" class suffixes allow us to keep the source order of page elements: Main body first, sidebar second.

Fluid-width page with no sidebar

Examples: About page, Holds awaiting pickup

            <div class="main container-fluid">
                <div class="row">
                    <div class="col-md-12">
                        <main>
                            <!-- Main body of the page -->
                        </main>
                    </div> <!-- /.col-md-12 -->
                 </div> <!-- /.row -->
            </div> <!-- /.main.container-fluid -->

Grids within pages

Bootstrap grids can be nested within each other. For example, to add a nested 3-column grid in the body of a page with a left-hand sidebar, add a div with a "row" class:

            <div class="main container-fluid">
                <div class="row">
                    <div class="col-sm-10 col-sm-push-2">
                        <main>
                            <!-- Main body of the page -->
                            <div class="row">
                                <div class="col-sm-4">
                                    <!-- Nested column 1 -->
                                </div>
                                <div class="col-sm-4">
                                    <!-- Nested column 2 -->
                                </div>
                                <div class="col-sm-4">
                                    <!-- Nested column 3 -->
                                </div>
                            </div>
                        </main>
                    </div> <!-- /.col-sm-10.col-sm-push-2 -->

                    <div class="col-sm-2 col-sm-pull-10">
                        <aside>
                            <!-- Left-hand sidebar -->
                        </aside>
                    </div> <!-- .col-sm-2.col-sm-pull-10 -->
                 </div> <!-- /.row -->
            </div> <!-- /.main.container-fluid -->

Common interface patterns

Many interfaces in Koha follow a similar pattern where data is shown initially in a table. Links are provided for edit and delete views. A toolbar provides additional actions like "New."

The data list view

Using Administration -> Cities and towns as an example, the initial view shows all existing cities in a table:

Screenshot showing the Cities and Towns data list view

Note the order of the elements:

  1. Toolbar
  2. Heading
  3. Table

If there are more than two "actions" available in the data list view those actions might be combined in a menu. For example, in Administration -> Funds:

Screenshot showing a pop-up menu of actions in an item list view.

If there is no data to list, a message will be shown:

Screenshot of the message which is shown if there are no cities defined.

In cases like this where the user has the ability to create a new instance of whatever kind of record is to be displayed, a link to the "New" entry form can be displayed in the message.

The 'New' entry form

The data list view will typically include a toolbar with a 'New' button to link to an entry form for creating a new instance of whatever kind of record is being managed. In the Cities and Towns example, this is a new city:

Screenshot showing the Cities and Towns new city entry form.

In this view the toolbar is not displayed, because the user is expected to either submit a completed form or choose the 'Cancel' link to abort the process of creating a new entry.

Form markup

<form class="validated" method="post" action="/cgi-bin/koha/admin/cities.pl">
    <input type="hidden" value="add_validate" name="op">
    <input type="hidden" value="" name="cityid">
    <fieldset class="rows">
        <ol>
            <li>
                <label class="required" for="city_name">City: </label>
                <input type="text" class="required" required="required" value="" maxlength="100" size="80" id="city_name" name="city_name">
                <span class="required">Required</span>
            </li>
            <li>
                <label for="city_state">State: </label>
                <input type="text" value="" maxlength="100" size="80" id="city_state" name="city_state">
            </li>
            <li>
                <label class="required" for="city_zipcode">ZIP/Postal code: </label>
                <input type="text" class="required" required="required" value="" maxlength="20" size="20" id="city_zipcode" name="city_zipcode"> <span class="required">Required</span>
            </li>
            <li>
                <label for="city_country">Country: </label>
                <input type="text" value="" maxlength="100" size="80" id="city_country" name="city_country">
            </li>
        </ol>
    </fieldset>
    <fieldset class="action">
        <input type="submit" class="btn btn-primary" value="Submit">
        <a href="/cgi-bin/koha/admin/cities.pl" class="cancel">Cancel</a>
    </fieldset>
</form>

The style of this form is created by using a "rows" class on the fieldset element and putting form fields inside an ordered list.

The maxlength attribute should be used when the corresponding table column has a character limit.

Form fields which are required are styled as such:

  • <label> tags have a "required" class: <label class="required" for="city_name">City: </label>
  • <input> and <select> tags have a "required" class and a "required" attribute: <input type="text" class="required" required="required" id="city_name" name="city_name">
  • Required fields are followed by a "Required" hint: <span class="required">Required</span>. Users should not be expected to rely on the color of the label to tell them which fields are required. We do not use an asterisk to denote required fields.

The form is followed by a submit button and a cancel link. Currently most forms in Koha use "Submit" as the label for all submit buttons rather than a label which is tied to specific action, for example "Save city" or "Update city."

Submit buttons are typically standard inputs with type "submit" and no associated icon. Submit buttons should usually have the "btn btn-primary" Bootstrap classes. The cancel link has a "cancel" class which currently adds no style except some extra padding.

The 'Edit' entry form

The edit view displays a form for editing one of the items shown in the data list view. The edit view is typically a separate page showing only the edit form:

Screenshot showing the Cities and Towns edit view.

This view is identical to the 'New' view except that existing data is shown in the form. Note that the first line in the edit form shows data which cannot be edited. Instead of the typical pair of <label> and <input> there is a <span> styled like a label: <span class="label"> followed by the existing data.

Radio buttons and checkboxes

There are two different options for displaying form rows with radio buttons or checkboxes. In the first, the form controls are displayed without a label in the left-hand column:

Screenshot showing the gender selection radio buttons on the patron edit page.

<fieldset class="rows">
    <ol>
        <li class="radio">
            <label><input type="radio" /> Choice 1</label>
            <label><input type="radio" /> Choice 2</label>
            <label><input type="radio" /> Choice 3</label>
        </li>
    </ol>
</fieldset>

In the second version, there is a general label which identifies the choices in the radio buttons or checkboxes:

This screenshot snippet shows the vendor edit form's active and inactive choices.

<fieldset class="rows">
    <ol>
        <li>
            <label>General label:</label>
            <label class="radio">
                Specific label 1 <input type="radio" />
            </label>
            <label class="radio">
                Specific label 2 <input type="radio" />
            </label>
        </li>
    </ol>
</fieldset>

Deletion confirmation

In some interfaces clicking the "Delete" link or button from the data list view will take you to a deletion confirmation page. On this page an "alert" style dialog asks the user to confirm the deletion:

Screenshot of the confirmation dialog shown when deleting a city.

In other interfaces clicking the "Delete" link will trigger a JavaScript confirmation:

JavaScript confirmation shown when deleting a list.

If the user confirms, the entry will be deleted without being taken to a deletion confirmation page.

Buttons

There are several general categories of buttons in the Koha staff client (including link, input and button elements):

Toolbar buttons

Toolbar buttons are styled using Bootstrap classes, often with the inclusion of a Font Awesome icon. The buttons inherit a unique style from the toolbar container.

The toolbar on the staff client bibliographic detail page.

Buttons in a toolbar might be any combination of inputs, buttons, or links.

A simple example from this toolbar is the "Print" buton:

  <a class="btn btn-default" id="printbiblio">
    <i class="fa fa-print"></i> Print
  </a>

The "btn btn-default" class allows the link or button element inherit the correct style. The <i> element creates the icon.

See Bootstrap documentation for more.

As covered in #Views_and_Actions, Toolbar buttons should be used for "actions," rather than "views."

Dialog buttons

When the staff client interface displays a (non-JavaScript) dialog, as shown in #Deletion_confirmation, buttons have a distinct style which stems from the container they are in. Dialog buttons do not have Bootstrap classes applied to them. Font Awesome icons should be used to give an indication of the kind of action being performed:

A selection of a confirmation dialog showing example buttons.

    <button type="submit" class="approve">
        <i class="fa fa-fw fa-check"></i> Yes, delete
    </button>
    <button type="submit" class="deny">
        <i class="fa fa-times"></i> No, do not delete
    </button>

Submit buttons

The least "specialized" button in the staff client interface is the generic submit button. This is commonly found at the end of data entry forms, for example in the form for adding a library in Administration -> Libraries and Groups:

The default submit button style in a typical form.

 <input type="submit" class="btn btn-primary" value="Submit" />

Action buttons in tables

When displaying tabular data, there are often actions associated with each line of data: Edit and delete for instance. As of this writing we are in the process of applying a consistent style to these actions using the Bootstrap button "btn-xs" class:

Action buttons repeated for each table row.

  <td class="actions">
    <a class="btn btn-default btn-xs" href="#"><i class="fa fa-pencil"></i> Edit</a>
    <a class="btn btn-default btn-xs" href="#"><i class="fa fa-trash"></i> Delete</a>
  </td>

Modals

Sometimes is useful to display some information in modal dialog, for example short forms or record previews.

We are using modals from Bootstrap 5, see full documentation here.

KohaModal.png

Basic HTML markup for modals, please note we are class closebtn for close button:

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

Printable Modals

A modal can be made printable by adding the `printable` class the modal container div and including the modal_printer.js asset.

<div class="modal printable" tabindex="-1" role="dialog" id="myModal">
   . . .
</div>

. . .

<script>
   [% Asset.js("js/modal_printer.js") | $raw %]
   . . .
</script>

Tabs

Koha uses Bootstrap tab markup to create tabbed interfaces.

Tabbed-interface.PNG

The markup for a set of tabs includes two main parts: A list of links which will form the tabs and a corresponding set of "panels" which will form the tab contents. As with breadcrumb navigation, we use a series of Template::Toolkit WRAPPER directives to construct tabbed interfaces. A simplified example:

    [% WRAPPER tabs id= "tabs container id" %]
        [% WRAPPER tabs_nav %]
            [% WRAPPER tab_item tabname= "tab name 1" bt_active= 1 %] <span>Tab text 1</span> [% END %]
            [% WRAPPER tab_item tabname= "tab name 2" %] <span>Tab text 2</span> [% END %]
        [% END %]
        [% WRAPPER tab_panels %]
            [% WRAPPER tab_panel tabname="tab name 1" bt_active= 1 %] [% content %] [% END %]
            [% WRAPPER tab_panel tabname="tab name 2" %] [% content %] [% END %]
        [% END %]
    [% END %]

The "bt_active" attribute on both tab link and tab panel results in that tab being the active or open tab when the page renders. Note that the text of the tab labels must be wrapped in span tags to ensure the strings can be translated. The template markup example would render this HTML:

<div id="tabs_container_id" class="toptabs">
    <ul class="nav nav-tabs" role="tablist">
        <li role="presentation" class="active">
            <a href="#tab_name_1_panel" aria-controls="tab_name_1_panel" role="tab" data-toggle="tab">
                <span>Tab text 1</span>
            </a>
        </li>
        <li role="presentation">
            <a href="#tab_name_2_panel" aria-controls="tab_name_2_panel" role="tab" data-toggle="tab">
                <span>Tab text 2</span>
            </a>
        </li>
    </ul>
    <div class="tab-content">
        <div role="tabpanel" class="tab-pane active" id="tab_name_1_panel">
            Tab panel 1
        </div>
        <div role="tabpanel" class="tab-pane" id="tab_name_2_panel">
            Tab panel 2
        </div>
    </div>
</div>

Keyboard shortcuts

The staff client includes a JavaScript library for defining keyboard shortcuts. Find it here: koha-tmpl/intranet-tmpl/lib/shortcut/shortcut.js. It is used for a few primary action shortcuts: Check in (Alt-r), Check out (Alt-u), Search (Alt-q) and Renew (Alt-w). These shortcuts are defined in staff-global.js. For example:

    shortcut.add('Alt+r',function (){
                location.href="/cgi-bin/koha/circ/returns.pl";
            });

The plugin is also used to define keyboard shortcuts in the advanced MARC editor.


Developer handbook