Output element planning

Jump to: navigation, search
Renderer consistency
Project state Specification
Tracker issue https://tracker.moodle.org/browse/MDL-45829
Discussion https://moodle.org/mod/forum/discuss.php?d=261202
Assignee Damyon, Sam

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.

This page documents the proposed core elements, variations of them, what we expect they will contain, and the core_renderer block.

This page will be a good base to start planning the conversion from renderers to templates for Moodle 3.0 (but needs a lot of updates first).

The user action

An action in this sense is a collection of data that all pertains to one action that can be taken by the user. The action, once populated with data can be rendered as is required for the job it is going to fulfil, usually with some relation to the frontend framework in use. In this way the action could be a link, or a button; it could even be interpreted into a more complex structure.

An action has the following properties:

content [string]
text content for the link or button.
url [moodle_url] 
the url for the action to take when the user interacts with this action.
description 
a description of the action. Typically used within a title or alt attribute.
active 
True if this is the action the user is current performing.
enabled 
True if the action is possible, false if it is not possible and should be shown as disabled.
dimmed 
True if the action should be shown as dimmed, usually used to the action is hidden to other users.
method 
The preferred method of submitting this action, typically GET but can be set to POST.

It is also possible to add JavaScript actions (component_action objects) to an action. These attach a JS listener to the action that gets executed when the user interacts with the action. Attached JavaScript actions get initialised when the properties for the action are retrieved so any events must be attached BEFORE the action is rendered, and all renderers must ensure they use the get_attributes() call.

Grids

We need to come up with some way to include grids in core, it is desirable to keep it framework agnostic so perhaps a grid object that allows for items to be added and a "width" specified when that occurs. The width would be either a fixed number or a percentage. Steps of 12 seems pretty common.

Design requirements

The following concepts need to be accounted for in core, or decisions made on how we choose to support these and where.

Clearfix

We have this in core already, bootstrap has it, pretty much every front end framework has it. Clearfix is more of a design decision, should only be used when require, and only ever applied by a renderer. This gets special mention as being important, support is already 100%.

Floats

Pull left, pull right etc. These are a design decisions and should be implemented by the renderer. Bootstrap caters for these and as such they will be easily catered for in bootstrapbase, however work may be required to get them operational in base.

Discarded ideas

The following things are ideas that came up during discussions on what elements are, and what elements we want in core that have being discarded.

Core atoms, molecules, and organisms

The following is the atoms, molecules and organisms we believe should be created initially. Of course there will be many more that are required - however this should give us a good grounding of elements to work with for the first conversions.

Action {atom}

See the section above about #The user action

Actions are special atoms the represent an action the user can make. They can be rendered by a theme as a link, a button or I suppose anything else. There should be a default for when it is not specified and the renderer in change of producing the current thing can decide whether to use the default and just call render or if it requires something specific render_link or render_button as required.

Action group {molecule}

A group of actions, to be rendered to reflect a relation. I suppose the easiest way to think about this is how buttons in the atto editor are grouped together. It is a requirement that may seem a tad absrtracted and irrelevant at first but I think will pop up in several places throughout Moodle when we start converting.

It is basically a collection of actions.

Markup in various frontend frameworks

Block {atom}

Unique to Moodle. This represents a block on the page, and is displayed within a #Block region. It accepts two arguments, the first is a block_contents object instance, and the second is the region name the block instance is being shown within.

At present a block is rendered using the core_render::block method. Internally this calls several renderer methods to produce the different parts of a block.

  • core_renderer::block_header - Produces a header
    • core_renderer::block_controls - Produces controls to display within the header.
  • core_renderer::block_content - Produces the actual content of the block.
    • core_renderer::block_controls - Used to check if block controls were rendered. PUKE!!!
    • core_renderer::block_footer - Produces a footer that actually resides within the content.
  • core_renderer::block_annotation - Produces an annotation, used VERY rarely.

Current structure

The following is the output when called for a navigation block with a bit of extra added to show how a footer is displayed and an annotation.

<a href="#sb-1" class="skip-block">Skip Navigation</a>
<div id="inst4" class="block_navigation  block" role="navigation" data-block="navigation" data-instanceid="4" aria-labelledby="instance-4-header" data-dockable="1">
    <div class="header">
        <div class="title">
            <div class="block_action">
                <!-- Block actions go here, they are images with JS or anchors-->
            </div>
            <h2 id="instance-4-header">Navigation</h2>
        </div>
    </div>
    <div class="content">
       <!-- Block content goes here -->
       <div class="footer">
           <!-- Block footer content goes here -->
       </div>
    </div>
    <div class="blockannotation">
        <!-- Block annotation content goes here -->
    </div>
</div>
<span id="sb-1" class="skip-block-to"></span>

Block region {molecule}

Unique to Moodle, the block region is a contain for all of the blocks in one location. We currently have two methods that produce a block region within Moodle, the first is core_renderer::blocks_for_region which adds no surrounding content. The preferred method core_renderer::blocks adds some embedded information to a common structure.

Current structure

The following is the structure of the core_renderer::blocks() method.

public function blocks($region, $classes = array(), $tag = 'aside');

The following is the html output is $region was pre and the default tag and classes were used.

<aside id="block-region-pre" class="block-region" data-blockregion="pre" data-droptarget="1">
    <!-- blocks go here -->
</aside>

Thoughts on this

The blocks method is a convenience method and serves an important purpose. However it should not take classes and tag as arguments.
These should certainly only settable within the renderer itself, and if themes wish to change this without wrapping the call they should override the renderer.

Both the data attributes relate to servicing JavaScript functionality. Perhaps they should be moved to a component_action or somehow else integrated with JS rather than with the renderer directly.

Internally it is calling blocks for region, however this should change it should request a array of blocks, convert the array to #Block elements and call render on each.

Proposed HTML structure

Much like the current structure but with the data attributes coming through a JS mechanism.

<aside id="block-region-pre" class="block-region">
    <!-- blocks go here -->
</aside>

Breadcrumb {molecule}

Currently called the navbar within Moodle, controlled by the navbar class located in lib/navigationlib.php and rendered by core_renderer::navbar().
Internally it calls moodle_page->navbar->get_items() to get an array containing navigation node items to display in the navigation bar.
It produces a bit of surrounding structure before calling render on each item.

Current structure

The following shows the structure for two items in the navigation bar presently within Moodle.

<span class="accesshide">Page path</span>
<nav class="breadcrumb-nav">
    <ul class="breadcrumb">
        <li>
            <a href="#">Home</a>
            <span class="divider">
                <span class="accesshide">
                    <span class="arrow_text">/</span>
                    &nbsp;
                </span>
                <span class="arrow sep"></span>
            </span>
        </li>
        <li>
            <a href="#">Here</a>
            <span class="divider">
                <span class="accesshide">
                    <span class="arrow_text">/</span>
                    &nbsp;
                </span>
                <span class="arrow sep"></span>
            </span>
        </li>
    </ul>
</nav>

Notice the excessive amount of markup to make the separator accessible.

Markup in various frontend frameworks

Bootstrap 2.3.2

<ul class="breadcrumb">
    <li>
        <a href="#">Home</a>
        <span class="divider">/</span>
    </li>
    <li>
        <a href="#">Here</a>
        <span class="divider">/</span>
    </li>
</ul>

Bootstrap 3

<ul class="breadcrumb">
    <li>
        <a href="#">Home</a>
    </li>
    <li>
        <a href="#">Here</a>
    </li>
</ul>

Zurb foundation

<ul class="breadcrumb">
    <li>
        <a href="#">Home</a>
    </li>
    <li>
        <a href="#">Here</a>
    </li>
</ul>

Design considerations

  • The currently active page should be marked with a class.
  • The current item should probably not be a link MDL-46037
  • wia-aria breadcrumb role
  • The divider perhaps could come through CSS with these changes to avoid markup necessary to make it accessible (in combination with the above).

Implementation thoughts

  • Owns an array of [#Action {atoms}]

Buttons {atom}

This will be both an element and a representation of a [#Action {atom}].
Obviously buttons can serve different purposes and roles so have several easily reachable customisations is probably a wise idea.

Current structure None, presently you produce a button when you need it so there are several throughout Moodle.

Markup in various frontend frameworks

Bootstrap 2.3.2 and Bootstrap 3

<button type="button" class="btn btn-default">Default</button>
<!-- OR -->
<a href="#" class="btn btn-default btn-lg active" role="button">Link</a>
<!-- OR -->
<input class="btn btn-default" type="button" value="Input">

Customisations available through Bootstrap:

  • Purposes: default, primary, success, info, warning, danger, link
  • Sizes: large, default, small, extra-small
  • Block level (wider)
  • States: Active, disabled.

Zurb foundation

<a href="#" class="button">Default Button</a>

Customisations available through Zurb Foundation:

  • Purposes: default, secondary, success, alert
  • Sizes: large, default, small, tiny
  • Corner style: radius, round
  • Expanded (wider)
  • States: disabled

Calendar {organism}

A simple idea really, apparently not already covered by the frontend frameworks being referenced during the creation of the doc. The display of the calendar is fixed, but it can contain content for each day shown.

The calendar should have several views, perhaps these are separate organisms, perhaps not.

  • Compact month
  • Month
  • Week
  • Day

Each day could:

  • Contain an action with an icon for events, and link to the fullday display.
  • Have an associated action to load and display the events in a tooltip.

Collapsible region {molecule}

We use these in several places within Moodle. I could not find a reference to this concept in any of the frontend frameworks I looked at. The concept is simple - you have a heading and an icon with content. By default the content is hidden, when the user clicks the heading and/or the icon the content is revealed.

As noted we do this in several places within Moodle, it would be good to have a single way of displaying this idea of a collapsible region.

Design thoughts

  • It should support an optional collapse/expand all trigger action.
  • We want to be able to use it both inside and outside of forms.
  • It should be usable in situations like the combo list frontpage component as well.
  • Will obviously have a JS component as without JS it would not work.

Confirmation {molecule}

A simple concept used regularly in Moodle to confirm a users intention to perform an actions. Most commonly seeing when deleting content. The structure is relatively basic in Moodle at present.

  • A message
  • A forwards button
  • A back button

Current structure

The method core_renderer::confirm does the rendering at present. Its signature is as follows:

public function confirm($message, $continue, $cancel);

The output it produces is like:

<div class="generalbox" id="notice">
    <p>The message goes here</p>
    <div class="buttons">
        <!-- Two buttons produced by core_renderer::render_single_button() -->
    </div>
</div>

Design throughts

This component does not have a title. I believe at present some pages use core_renderer::heading to produce a title if they wish. Obviously we want consistency of style so I believe it would be wise to add a title property that can be optionally set and then in our documentation for this element recommend that a title is always provided.
It will mean re-factoring our uses to set a title and if a heading is being manually added remove it.

Continue {molecule}

This is much like the confirmation molecule but with a single button.
At present we have core_renderer::continue_button that produces a single button. However this design is very poor as more often than not a message is included in the page to describe the purpose of the continue button. This is really an integral part of the continue button.

Current structure

Currently we have core_renderer::continue_button to render a single continue button.

public function continue_button($url);

Internally it creates a single_button component and then calls render on that.

Design thoughts Our element should have a message and a button. To make it easy to migrate the constructor should accept a URL instead of a button and do the same conversion as the current method is doing.

Choice {molecule}

Not sure about this one quite yet. A description with 2 or more actions allowing the user to select the next step. Think of it like when editing a module you get: Cancel, Save and return to course, Save and display

Perhaps both [#Confirmation {molecule}] and [#Continue {molecule}] should be just instances of this.

Hmm perhaps that would not be as clear as this and we should have this separate choice molecule.

Divider {atom}

Think horizontal rule.

Dropdowns {molecule}

So this is a pretty simple concept, but you've got to think of it as a separate entity. A dropdown is a menu that appears when the user interacts with an action.

The action could take one of three forms:

  • From button
  • From link
  • From icon

Of course that is handled by the [#Action {atom}] noted above. Worth noting is that we will need some way to toggle these actions as dropdowns. Perhaps it is worth making that a property of the action atom.

The dropdown itself will likely contain more actions, and I suppose additional dropdowns to form sub menus. Sub-menus in my mind are required. We don't use them in core, but they are functionally possible through things like the custom menu and I know for a fact that many sites have sub menus.

Markup in various frontend frameworks

Bootstrap 2.3.2

<div class="dropdown">
    <!-- Link or button to toggle dropdown -->
    <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
        <li><a tabindex="-1" href="#">Action</a></li>
        <li><a tabindex="-1" href="#">Another action</a></li>
        <li><a tabindex="-1" href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Separated link</a></li>
    </ul>
</div>

Bootstrap 3

<div class="dropdown">
    <button class="btn dropdown-toggle sr-only" type="button" id="dropdownMenu1" data-toggle="dropdown">
        Dropdown
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
        <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
        <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
        <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
        <li role="presentation" class="divider"></li>
        <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
    </ul>
</div>

Zurb foundation

<a href="#" data-dropdown="drop1">Has Dropdown</a>
<ul id="drop1" class="f-dropdown" data-dropdown-content>
    <li><a href="#">This is a link</a></li>
    <li><a href="#">This is another</a></li>
    <li><a href="#">Yet another</a></li>
</ul>

Forms {organism}

This is an advanced organism and would be quite a bit of work to create in Moodle as we'd need to translate from QuickForms to elements for rendering. It would be worthwhile doing this however, and would be a good way of quickly showing our new work.

Frontend framework structures

All of those are quite in-depth and offer a range of configurations. We should carefully consider these when analysing our work here.

Headings {atom}

Currently handled by core_renderer::heading.

  • h1 - h6
  • Optional icon
  • Optional help icon

Current structure

The render method is currently:

public function heading($text, $level = 2, $classes = null, $id = null);

The output generated by this is, assuming we use the default level, classes, and id.

<h2>I am a heading</h2>

Whats worth noting is that the render method should not accept level and classes as arguments. These should only be set by the render method and should not be directly influenced.

Image {atom}

There are really two types of images to focus on here, or really two ways to display an image to focus on here.

  1. Standard images
  2. Thumbnail images

Each of these would share some common properties:

  • Image
  • Description (alt/title)
  • Size
  • Action (making it a link) - This would actually make it a molecule, we would have to consider this and either have a new element, drop the ability to wrap in an action, or simply ignore this inconsistency.

Image - Icon {atom}

This covers the display of an icon. Should be a separate element from image as really they should be treated individually. Within Moodle there are a few classifications of icons to consider:

  • Standard icons
  • Help icon (popup, tooltip)
  • Loading icon (really regular icon but worth showing separately as its only seen when required)

Image - Logo {molecule}

We don't have this within core Moodle at present, however just about every theme I have seen uses a logo. I think it is about time we considered having a logo element. I imagine it would become a sort of hero element, likely with an associated action (back home by default).

Image - Profile picture {molecule}

We already have a user_picture component within Moodle. It can be found in lib/outputcomponents.php.
It has two render methods, core_renderer::user_picture and core_renderer::render_user_picture.

Current structure

The following is the output structure for the user picture:

<a href="#" id="userpicture_randomid">
    <img src="#" alt="Picture of Joe" title="Picture of Joe" class="userpicture" width="[35, 100, XX]" height="[35, 100, XX]" />
</a>

What you'll notice about this is that the link has no attributes marking it as a user picture link.

The PHP code for the user_picture object itself is really quite in depth and complex. The component serves the user profile fields required to render a user picture. This is good in the scope of the component but would be bad within the scope of an element.
Don't you wish we had a proper user object!

Link {atom}

This will be both an element and a representation of a [#Action {atom}].

Theres not too much more to explain about links, they don't tend to take states other than the default active, enabled and dimmed.
It is worth mentioning that devs will be encouraged to use actions and not links unless absolutely necessary.
The render method for this atom must typehint an action rather than a link.

Prototype example

List {molecule}

This is a pretty simple example and something I am sure you are all familiar with. A list is simply a collection of items. Usually represented using a UL or OL tag in markup although worth noting can be styled completely differently to the default. There are three main types of lists used within Moodle:

  • Ordered list
  • Unordered list
  • Presentation list (currently our unlist)

The list is a molecule because it should be able to accept other elements as items. E.g. it should be content independent.

Menu {molecule}

A menu is a familiar concept for any site. Probably the first thing that pops to mind for many is the navbar, but I want to consider that a separate component as a navbar can consist of more than just menu items. I think a menu should be a collection of actions the user can perform. Perhaps with some form of hierarchy.

We have different types of menus within Moodle:

  • The custom menu is one users can directly create, with dropdown downs and sub dropdowns.
  • The action_menu component we have in core uses icons as actions and can have a dropdown.

These should be combined into a single menu element that takes items as an argument, likely actions + dropdowns + dividers to start with would be perfect.

We would likely need to deal with the display of the menu with properties to allow constructing code to request a particular style of menu. The renderer should be what actually gets to decide, but for the purposes of re-use having properties and a single render_method is better than having multiple render methods.
The following is my initial thoughts on menu structure:

  • Direction: Horizontal, Vertical
  • Design: Default, Tabs,
  • Style: Default, Links, Buttons, Icons

Notification {atom}

  • Info
  • Success
  • Warning
  • Danger

Navigation bar {organism}

Formerly navbar, can't be called that because the render method would conflict.

The navigation bar is just that, it is becoming increasingly common on the web and usually contains a title or logo, a menu, and information pertaining to the user state (login, language etc).

Page header {molecule}

Currently being produced by core_renderer::page_heading this is simply a header for the page, by default the only h1 element on the page.

Current structure

The render method has the following signature:

public function page_heading($tag = 'h1');

The output from the above method is:

<h1>The page heading (from moodle_page::heading)</h1>

The core_renderer method should not allow the tag to be set. The page heading should always be H1. If its not an H1 then page header should not be used.

Frontend framework examples

Bootstrap 2.3.2

<div class="hero-unit">
  <h1>Heading</h1>
  <p>Tagline</p>
  <p>
    <a class="btn btn-primary btn-large">
      Learn more
    </a>
  </p>
</div>

Bootstrap 3

<div class="page-header">
  <h1>Example page header <small>Subtext for header</small></h1>
</div>

Foundation doesn't appear to have a page header component.

Design thoughts

  • In Moodle all page headings are set as a single string, we won't be changing this.
  • Usually just a plain string sometimes an icon is used, and sometimes a help icon is used.

Pagination {molecule}

I like the idea of this being separate to a menu, and to other navigation oriented elements because it should be something that can easily be constructed with a few basic parameters and allow us to achieve consistent pagination throughout Moodle.
It also appeals because this is something that people may want to style differently to their navigation.

Markup in various frontend frameworks

Progress bars {molecule}

A pretty simple concept, we already have a couple of ways of producing progress bars within Moodle.

Markup in various frontend frameworks

Bootstrap 2.3.2

<div class="progress">
    <div class="bar" style="width: 60%;"></div>
</div>

The following options are offered by Bootstrap 2.3.2:

  • Striped
  • Striped + Animated
  • Stacked (multiple bars forming a single)
  • Colours: default (blue), info (light blue), success (green), warning (orange), danger (red)

Bootstrap 3

<!-- With label -->
<div class="progress">
    <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;">
        60% Complete
    </div>
</div>
 
<!-- Label is hidden but accessible -->
<div class="progress">
    <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;">
        60%
    </div>
</div>

The following options are offered by Bootstrap 3:

  • Striped
  • Striped + Animated
  • Stacked (multiple bars forming a single)
  • Colours: default (blue), info (light blue), success (green), warning (orange), danger (red)

Zurb foundation

<div class="progress">
    <span class="meter"></span>
</div>

The following options are offered by Zurb foundation:

  • Width
  • Colours: default (blue), secondary (grey), success (green), alert (red)
  • Corner style: default (square), radius (slight rounding), round

Search {molecule}

A pretty common interface molecule, and in fact used as an example in the atomic design blog post we keep referencing.
We don't have a component for searching yet, however we've several search boxes throughout Moodle. The admin setting search box is the first to come to mind for me, followed by the forum search box and course search box.

Design considerations

Constructed of the following items:

  • Text input
  • Action (must be a button for submit I imagine)
  • Label or short description (optional)
  • Collapsible region containing settings etc (optional)

Table {organism}

We've two primary table components within Moodle presently html_table and flexible_table both of which offer different advantages and disadvantages. This will be a challenge and will really require some proper research and community interaction.

Timer {atom|molecule}

... not sure about this one, but we do use it in a couple of places, and we use it on all core sites that have hourly resets so in a way it makes sense to support it and allow it to be styled nicely and easily.

Tree {organism}

User content {organism}

Think of this like the forum post. We need a common structure in which to display content entered by the user along with information on the user. The users name, picture, date perhaps, title, content, footer (attachments, badges, what ever). It could be applied to things like forum posts, calendar events etc.

At present we have no abstraction for this.

Existing renderables and what they will become

Existing renderable Description Future renderable Convenience method (if different)
action_menu UI component for a drop down edit menu menu
action_menu_link UI component for a menu item in an action menu action
action_menu_filler UI component for a filler menu item in an action menu action
action_menu_link_primary UI component for a primary menu item in an action menu action
action_menu_link_secondary UI component for a secondary menu item in an action menu action
action_link Link with alt text, and an icon action
single_button A form with a single button button (action with post method)
confirm A form with a message and cancel/confirm buttons confirmation
single_select A form with a single drop down list that submits on change
url_select A navigation element consisting of a single drop down list of urls that navigates on change
doc_link A link to the Moodle docs
pix_icon A small icon icon
emoticon_icon A small emoticon
heading_with_help A page heading with a link to help docs heading
help_icon A help icon that opens a help popup when clicked icon_help
help_icon_scale A help icon that opens a help popup when clicked
user_picture A user profile picture which links to their profile
container A block level element used to surround something. Can have a class to allow specific targeting with CSS.
error_text An error to show to the user.
notification A message for the user
continue_button A message and a button to continue to the next page
paging_bar A list of next previous and specific page links
skip_link_to A link to a section on the page
skip_link_target A target for a matching skip_link_to call
heading A page heading heading
box A page section with a border
rarrow A right arrow
larrow A left arrow
tabtree A list of tabs menu
tabobject A single tab panel action

See also