Navigation

Navigation

The application’s primary navigation is a fixed-position column at the left of every screen for the main app pages and sections. Along with the header navigation, the left navigation should provide a consistent look and feel cross-product.

Navigation basics

Basic left navigation requires a parent nav element with the class .hc-app-nav and at least one section containing content.

The primary menus should sit inside of a wrapping section with class .hc-app-nav-primary. The expand/collapse toggle is recommended and should be contained in a section with class .hc-app-nav-toggle. These will automatically position themselves as justified-between.


<nav id="hc-app-nav" class="hc-app-nav" role="navigation">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--calendar"></i>
        <span class="hc-label">Activities</span>
        <span class="hc-indicator-count hc-indicator--danger">3</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--clipboard"></i>
        <span class="hc-label">Forms &amp; Flows</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--book-open"></i>
        <span class="hc-label">Library</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--newspaper"></i>
        <span class="hc-label">Newsletters</span>
      </a>
    </menu>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

The above boilerplate markup shows a basic representation of an application menu with active state and indicator count.

Each menu group should be wrapped in a menu element with class .hc-app-nav-menu. These menus take menu items using any element with class .hc-app-nav-menu-item. Menu items require an Icon, an .hc-label with the manu item’s label, and optionally an .hc-indicator-count if you’d like to include an indicator.

Applying the class .hc-active to .hc-app-nav-menu-item will automatically handle the active state changes.

Accessibility note

  • Make sure the navigation panels use <nav> as an element, and you can add role="navigation" to further specifiy the correct role (even though this is a bit redundant).

  • The bottom collapse/expand toggle must have tabindex="0" set on the label itself. This ensures that this clickable element is focusable. It should also have a label like aria-label="Toggle navigation width" for screen readers.

Expand/collapse handling

The Navigation component has a default 16rem width for desktop screens. Users should be able to collapse the Navigation with a familiar icon button fixed to the bottom of the component, reducing it to 4rem with the menu items in icon-only mode.

The CSS-only logic is handled by Honeycomb and just requires some specific markup before the </nav> end tag:


<nav id="hc-app-nav2" class="hc-app-nav" role="navigation">
  <!-- menu items here ... -->
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-2" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-2" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

Important: please note that the markup above appends -2 to the input ID. This is only necessary for the examples on this page and should be removed in production; you can see the official markup in the first example at the top.

How the expand/collapse works

The expand/collapse functionality takes advantage of the checkbox label hack and the :has pseudo-class. No JavaScript is required!

The button itself is actually a <label> that controls a hidden <checkbox> element. When the checkbox has a :checked state, the parent <nav> element sees this and adjusts its width and some other child element properties. The CSS for this looks like:


nav#hc-app-nav:has(.hc-app-nav-toggle-check:checked) {
  // styles
}

Because it looks at a checkbox’s :checked state, the Navigation component will stay collapsed or expanded regardless of other user interactions.

Class-based handling

Alternatively, you can apply the class .hc-app-nav--collapsed to the <nav> element to force the collapsed state. This is useful if you’d like to handle collapsing based on other conditions, to save the state with a cookie, or otherwise programmatically via JavaScript.

Note that you must manually remove this class when you want the Navigation component expanded again. The checkbox will not work with this manual class added.

Considerations

This checkbox-based approach will allow the collapsed state to “stick” during page refreshes. It will not, however, stick when the user navigates to another page. In this case, you could save the collapsed state to a cookie and add or remove the checked attribute to the checkbox by default depending on state.

Tooltips

You can add Tooltips on menu item hover when the Navigation component is collapsed with the same class hierarchy as a regular Tooltip.

Add the wrapper class, .hc-tooltip-group, to the .hc-app-nav-menu-item link itself and place the .hc-tooltip as a <span> as the last element within the link. Read more about this alternative HTML on the Tooltip component page.

No tooltip should show up here in expanded mode:

It should, however, appear by default when collapsed:


<!-- full width example -->
<p>No tooltip should show up here in expanded mode:</p>
<nav id="hc-app-nav-3" class="hc-app-nav" role="navigation">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Home
        </span>
      </a>
    </menu>
  </section>
</nav>
<!-- collapsed nav example -->
<p>It should, however, appear by default when collapsed:</p>
<nav id="hc-app-nav-4" class="hc-app-nav hc-app-nav--collapsed">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Home
        </span>
      </a>
    </menu>
  </section>
</nav>

Showing Tooltips all the time

The default behavior is to hide the Tooltip when the Navigation is in full/expanded mode, and to only show them when it’s collapsed.

To override this, add the class .hc-app-nav-menu--tooltips-always to the <menu> element.


<nav id="hc-app-nav-5" class="hc-app-nav" role="navigation">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu hc-app-nav-menu--tooltips-always">
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Home
        </span>
      </a>
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--calendar"></i>
        <span class="hc-label">Calendar</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Calendar
        </span>
      </a>
    </menu>
  </section>
</nav>

Menu groups

In larger or more complex Navigation implementations it may make sense to group menu items together into logical sections.

Use separate <details> elements for groups along with the .hc-app-nav-menu-group class, and create toggleable titles at the top using a <summary> element that has both the .hc-app-nav-menu-group-toggle and .hc-app-nav-menu-item classes.


<nav id="hc-app-nav-6" class="hc-app-nav" role="navigation">
  <section class="hc-app-nav-primary">
    <details class="hc-app-nav-menu-group" open>
      <summary class="hc-app-nav-menu-group-toggle hc-app-nav-menu-item">
        <span class="hc-label">Activities</span>
        <i class="hc-icon hc-icon--chevron-up"></i>
      </summary>
      <menu class="hc-app-nav-menu">
        <a href="/" class="hc-app-nav-menu-item hc-active">
          <i class="hc-icon hc-icon--home"></i>
          <span class="hc-label">Home</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--calendar"></i>
          <span class="hc-label">Activities</span>
          <span class="hc-indicator-count hc-indicator--danger">
            3
          </span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--clipboard"></i>
          <span class="hc-label">Forms &amp; Flows</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--book-open"></i>
          <span class="hc-label">Library</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--newspaper"></i>
          <span class="hc-label">Newsletters</span>
        </a>
      </menu>
    </details>
    <details class="hc-app-nav-menu-group" open>
      <summary class="hc-app-nav-menu-group-toggle hc-app-nav-menu-item">
        <span class="hc-label">Members</span>
        <i class="hc-icon hc-icon--chevron-up"></i>
      </summary>
      <menu class="hc-app-nav-menu">
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--user"></i>
          <span class="hc-label">Staff Roster</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--user-group"></i>
          <span class="hc-label">Staff Groups</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--settings"></i>
          <span class="hc-label">Settings</span>
        </a>
      </menu>
    </details>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-3" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-3" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

The markup is slightly different from the basic Navigation example. Each group must use a separate <details element with the <summary> at the top and the regular <menu> element and its items below that.

You must include the open attribute on the <details> element to expand the group by default. Removing this attribute will collapse the group, as will clicking the toggle.

Sometimes it may be necessary to include actions or buttons at the bottom of the Navigation component, right above the collapse toggle. Simply add another <section> right before the toggle with class .hc-app-nav-footer.


<nav id="hc-app-nav-7" class="hc-app-nav h-96">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--book-open"></i>
        <span class="hc-label">Library</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--newspaper"></i>
        <span class="hc-label">Newsletters</span>
      </a>
    </menu>
  </section>
  <section class="hc-app-nav-footer">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--settings"></i>
        <span class="hc-label">Settings</span>
      </a>
    </menu>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-4" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-4" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

If the application requires actions at the top before the primary menu, like a search box or some other control, add another <section> before the primary menu section with a class of hc-app-nav-header.


<nav id="hc-app-nav-8" class="hc-app-nav">
  <section class="hc-app-nav-header">
    <input type="search" 
           class="hc-app-nav-search hc-input hc-input--search hc-input--leading-icon"
           placeholder="Search students...">
  </section>
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--book-open"></i>
        <span class="hc-label">Library</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--newspaper"></i>
        <span class="hc-label">Newsletters</span>
      </a>
    </menu>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-5" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-5" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

Advanced menu items

Menu items can contain secondary information or actions, like an indicator count or a dropdown menu for more options. These should be wrapped in the last element within the hc-app-nav-menu-item.

Reference the Indicator and Dropdown components for the HTML. Basic examples are below.


<nav id="hc-app-nav-9" class="hc-app-nav">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
      </a>
      <a href="/" class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--calendar"></i>
        <span class="hc-label">Activities</span>
        <span class="hc-indicator-count hc-indicator--danger">3</span>
      </a>
      <div class="hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--clipboard"></i>
        <a href="/" class="hc-label">Forms &amp; Flows</a>
        <div class="hc-dropdown">
          <div class="hc-dropdown-toggle">
            <button>
              <i class="hc-icon hc-icon--more hc-icon--solid hc-icon--16"></i>
            </button>
          </div>
          <div class="hc-dropdown-content">
            <menu class="flex flex-col px-3 py-3 whitespace-nowrap">
              <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is an item</a>
              <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is another item</a>
              <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is a third item</a>
            </menu>
          </div>
        </div>
      <div>
    </menu>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-6" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-6" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

Important: when using interactive elements inside of a menu item, the markup will have to change to prevent a “link within a link.”

With the Dropdown example above, the label itself is now the link and menu item is a <div>. This breaks consistency in that the entire menu item will not be clickable anymore, but is necessary to including an interactive element.

Secondary navigation

Sometimes it’s necessary for a secondary navigation column for embedded apps or screens, or for more complicated pages that require their own internal navigation.

Create secondary navigation in the same method as the primary Navigation component, but append the class .hc-secondary-nav to the parent <nav> element. This handles positioning and other minor changes.

It’s also recommended to manually collapse the primary navigation in this context.


<nav id="hc-app-nav-10" class="hc-app-nav">
  <section class="hc-app-nav-primary">
    <menu class="hc-app-nav-menu">
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--home"></i>
        <span class="hc-label">Home</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Home
        </span>
      </a>
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--book-open"></i>
        <span class="hc-label">Library</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Library
        </span>
      </a>
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item hc-active">
        <i class="hc-icon hc-icon--clipboard"></i>
        <span class="hc-label">Forms &amp; Flows</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Forms &amp; Flows
        </span>
      </a>
      <a href="/" class="hc-tooltip-group hc-app-nav-menu-item">
        <i class="hc-icon hc-icon--newspaper"></i>
        <span class="hc-label">Newsletters</span>
        <span class="hc-tooltip hc-tooltip--right" role="tooltip">
          Newsletters
        </span>
      </a>
    </menu>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-7" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-7" class="hc-app-nav-toggle-check" checked>
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>
<nav id="hc-secondary-nav" class="hc-app-nav hc-app-nav--secondary">
  <section class="hc-app-nav-primary">
    <details class="hc-app-nav-menu-group hc-app-nav-menu-group--static" open>
      <summary class="hc-app-nav-menu-group-toggle hc-app-nav-menu-item">
        <span class="hc-label">Forms &amp; Flows</span>
      </summary>
      <menu class="hc-app-nav-menu">
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--clipboard"></i>
          <span class="hc-label">Form Requests</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--edit"></i>
          <span class="hc-label">In-Progress Forms</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item hc-active">
          <i class="hc-icon hc-icon--clipboard-paste"></i>
          <span class="hc-label">Submitted Forms</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--collection"></i>
          <span class="hc-label">Form Center</span>
        </a>
        <a href="/" class="hc-app-nav-menu-item">
          <i class="hc-icon hc-icon--users"></i>
          <span class="hc-label">My Students</span>
        </a>
      </menu>
    </details>
  </section>
  <section class="hc-app-nav-toggle">
    <label class="hc-button hc-button-icon hc-app-nav-toggle-button" for="hc-app-nav-toggle-check-8" tabindex="0" aria-label="Toggle navigation width">
      <input type="checkbox" id="hc-app-nav-toggle-check-8" class="hc-app-nav-toggle-check">
      <i class="hc-icon hc-icon--collapse"></i>
    </label>
  </section>
</nav>

Mobile handling

On mobile or small screens, ideally the Left Navigation component itself is hidden and it’s links are subsumed within the header’s mobile dropdown variant. For this reason, the Nav should be hidden on these screens up until the md or lg breakpoint.

We do not enforce this as a default but recommend adding .hc-for--lg to the primary element to hide the navigation entirely on small screens.