Simple navigation renderer

‹ Back

You can use the ornament_menu simple-navigation renderer to automatically add arrows, toggle and accessibility features.

In order to use this renderer in your app, you will need to register the renderer in your navigation.rb file.

# config/navigation.rb
SimpleNavigation.register_renderer :ornament_menu => OrnamentNavRenderer
<div class="navigation">
  <nav aria-label="Global Navigation">
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      id_namespace: "example1",
      icons: true,
      toggles: true,
      temporary_toggles: true,
    }) %>
  </nav>
</div>

Accessability features

When used in conjuction with the simple-navigation.js, your navigation menus will gain several accessibility features:

When focused on a first-level parent item, you can press down or space to open the menu and focus on the first link.

When focused on second-level or third-level items, you can press up or down to cycle focus through the list links.

When focused on a second-level parent item, you can press right or space to open the child menu.

When focused on a third-level item, you can press left to close the menu and focus on the parent button.

Any second or third-level menus can be closed with esc, one level at a time. Closing will focus on the opener.


A note about IDs

One of the benefits of this renderer is that also comes with the ability to customise the key ids to a namespace with id_namespace.

This is required if you have multiple menus using any of the same navitems, eg in the case of seperate desktop and mobile navigation. If you have multiple menus using either no namespace or the same namespace, you will notice duplicate id errors in the console and any toggles may start triggering multiple times. Best practice is to always define a namespace.


Customising renderer

Like all of Ornament, the renderer is generated in to your project so you can customise to suit your needs. The renderer is generated in to /app/renderers/ornament_nav_renderer.rb.


Split parent icons

To split the toggle button and still have the parent link as an actual link, you can change toggle: true to toggle: "split".

Keyboard shortcuts will work on both the parent link and the toggle button.

<div class="navigation">
  <nav aria-label="Global Navigation">
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      id_namespace: "example-split",
      toggles: "split",
      temporary_toggles: true,
      icons: true,
    }) %>
  </nav>
</div>

Icons

icons: true will render the chevron icons by default. You can omit this option to render without icons:

<div class="navigation">
  <nav>
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      id_namespace: "nav-no-icons",
      toggles: true,
      temporary_toggles: true,
    }) %>
  </nav>
</div>

Alternatively you can pass a hash to define the expand and collapse icons, icons: { expand: icon("expand"), collapse: icon("collapse") }:

If you only pass in expand you will simply override the default icon.

If you pass in both expand and collapse you will then be able to swap the icon based on active state.

This can be handy if you have entirely different icons for collapse and expand states, however it is recommended to use a single icon and animate it when you can.

<div class="navigation">
  <nav>
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      id_namespace: "nav-icons-custom",
      toggles: true,
      temporary_toggles: true,
      icons: {
        expand: icon("star_empty"),
        collapse: icon("star"),
      }
    }) %>
  </nav>
</div>

Hover instead of toggle

Omit the toggle option and you will get hover menus instead.

Keyboard shortcuts will no longer work as they are tied to the toggle actions.

When focusing on parent links as a keyboard user the child menu will appear, note this can be quite jarring for screen reader users. This approach is provided but advised against.

<div class="navigation">
  <nav>
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      icons: true,
      id_namespace: "nav-hover",
    }) %>
  </nav>
</div>

Descriptions

Descriptions can be included in the html hash in your SimpleNavigation item configuration.

Adding descriptions: true to your navigation will show descriptions at all levels, where descriptions are present.

You can render descriptions per level by using eg. descriptions (2..3) to only render the descriptions at levels 2 to 3.

When not using toggles, the description is pushed to the data-description attribute on the link so it can seamlessly integrate with the drilldown component, which you can see below.

# SimpleNavigation Config
primary.item :Foo, "Foo", "#Foo", html: { description: "This is a sample description" }

# View
<div class="navigation">
  <nav aria-label="Global Navigation">
    <%= koi_render_navigation({
      cache_key: "header_nav",
      nav_items_fetch_key: "header_navigation",
      renderer: :ornament_menu,
      level: 1..3,
      expand_all: true,
      id_namespace: "nav-descriptions",
      toggles: true,
      temporary_toggles: true,
      descriptions: (2..3),
      icons: true,
    }) %>
  </nav>
</div>

Open active toggle by default

Not very useful in the context of a horizontal, dropdown navigation like this, but you can default the active tree open with open_active_toggle: true.

In the context of a sidebar navigation this would be used to pop the current tree open, which is a common pattern.

See the Page Navigation page for examples of this feature.


Basic

When you omit the icons and toggle options you end up with a pretty basic unordered list, which can be useful if you're pushing the list to another widget, such as the dropdown component.

<div data-drilldown>
  <%= koi_render_navigation({
    cache_key: "header_nav",
    nav_items_fetch_key: "header_navigation",
    renderer: :ornament_menu,
    level: 1..3,
    expand_all: true,
    descriptions: true,
    id_namespace: "basic",
  }) %>
</div>

Classes

If you want to customise the classes, you can pass in class_prefix.


No renderer

If you aren't using simple-navigation, you can leverage the navigation classes in your HTML to produce basic hover navigation variation:

<div class="navigation">
  <nav aria-label="Global Navigation" class="navigation__simple">
    <ul class="level-1">
      <li>
        <a href="#">Home</a>
      </li>
      <li>
        <a href="#">About</a>
        <ul>
          <li>
            <a href="#">History</a>
          </li>
          <li>
            <a href="#">Board Members</a>
          </li>
        </ul>
      </li>
      <li class="navigation--active-item">
        <a href="#">Products</a>
        <ul>
          <li class="navigation--active-item">
            <a href="#">On Sale</a>
          </li>
          <li>
            <a href="#">Other</a>
          </li>
        </ul>
      </li>
    </ul>
  </nav>
</div>