Skip to content
Navigation web component.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
dist
src
.editorconfig
.eslintrc
.gitignore
.stylelintrc
CHANGELOG.md
README.md
package.json
postcss.config.js
webpack.config.js
yarn.lock

README.md

🗺️ Site Navigation

An HTML Custom Element to make site nav a bit easier.

Installation

Currently this package is intended to be added to your project with npm/yarn, and included in your project, likely through webpack. There are other ways you could include it (running webpack on this repo to generate files in /dist, for instance), but the following is the recommended process (i.e. the one I've tested):

$ npm i @murmurcreative/site-navigation
// main.js, or a script that will be run on all pages
import '@murmurcreative/site-navigation';

If you're using webpack, you'll need to make sure that your loaders for js and css aren't ignoring the site-navigation directory (often webpack configuration will ignore node_modules, which will prevent site-navigation from getting picked up.) As an example, in the default webpack.config.js for roots' Sage, make the following changes:

// resources/assets/build/webpack.config.js
test: /\.js$/,
exclude: [/node_modules(?![/|\\](bootstrap|foundation-sites))/],

//...to this:

test: /\.js$/,
exclude: [/node_modules(?![/|\\](bootstrap|foundation-sites|site-navigation))/],

Usage

When used, site-navigation will look at the content you put inside it to build a menu. An example might look this this:

<site-navigation>
  <nav>    
    <button data-toggle>Open</button>
    <div data-drawer>
      <ul>
        <li>
          <a href="/home/">Home</a>
        </li>
        <li>
          <a href="/page-1/">Page One</a>
        </li>
        <li>
          <a href="/page-2/">Page Two</a>
          <button data-toggle>Open</button>
          <ul>
            <li>
              <a href="/page-2/page-3/">Page Three</a>
              <button data-toggle>Open</button>
              <ul>
                <li>
                  <a href="/page-2/page-3/page-4/">Page Four</a>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </nav>
</site-navigation>

Note: The above reflects a recommended layout: a <nav> nested in the master <site-navigation> element, with <div>s as top-level Drawer(s) and <ul>s as nested Drawers. This is the easiest to understand, and the most accessible. site-navigation is flexible enough to support many different layouts, however, so long as you follow the rules below.

Drawers

A Drawer is a section of content that will be hidden and shown when its associated Toggle is clicked. A Drawer can contain whatever you want it to (even other Drawers!) but it will usually contain a list of navigational links. The rules for setting up a Drawer are as follows:

  1. Your Drawer can be any block-level element, but it must meet at least one of the following criteria:
    1. Have the attribute data-drawer
    2. Directly follow a Toggle
  2. Your Drawer must be directly preceeded by a Toggle.

Drawers represent the single source of truth about their state: Toggles take their state from their associated Drawers. This means that if you want to determine or set the state of a Drawer programmatically, you should do so through the Drawer itself, not a Toggle. site-navigation only recognizes Drawers and Toggles in pairs: If you have only one, it will simple ignore that element.

Opening/Closing Drawers Programatically

There are three functions attached to each Drawer which site-navigation uses internally to handle opening and closing Drawers:

  • toggleDrawer() - Switches the state of the Drawer.
  • openDrawer() - Opens the Drawer. Has no effect if the Drawer is already open.
  • closeDrawer() - Closes the Drawer. Has no effect if the Drawer is already closed.

Each of these functions also has a "silent" variant, which means that the event will not bubble up to the parent event: It will only fire on itself. This can be useful if you're doing something that manipulates drawer state based on the state of another drawer (otherwise you can get a lot of recursion).

Example
// Let's assume you have a Drawer with the ID `location-list`, which is currently closed.

document.getElementByID(`location-list`).toggleDrawer();
// The Drawer is now open.

document.getElementByID(`location-list`).openDrawer();
// The state of the Drawer has not changed.

document.getElementByID(`location-list`).closeDrawer();
// The Drawer is now closed.

document.getElementByID(`location-list`).openDrawerSilently();
// The drawer is now open, but the parent <site-navigation> was 
// not notified.

Toggles

Toggles are the buttons used to open and close Drawers. They must obey the following rules:

  1. Have the attribute data-toggle
  2. Directly preceed a Drawer
  3. Be a <button>

Note: Technically, a toggle can be any element which will dispatch the click event when clicked, but in practice and for accessibility reasons they should almost always be <button>s.

Examples

...
<li>
  <a href="/contact">Contact Us</a>
  <button data-toggle>Open</button>
  <ul>...</ul>
</li>
...

👍 Good

...
<li>
  <button data-toggle>Open</button>
  <a href="/contact">Contact Us</a>
  <ul>...</ul>
</li>
...

👎 Bad

The <button> does not immediately preceed the <ul>.

...
<li>
  <a href="/contact">Contact Us</a>
  <ul>...</ul>
</li>
...

👎 Bad

There is no <button> for the <ul>.

Events

Drawers dispatch events when their state should change, which all other parts of site-navigation hook into to do their thing. These events bubble up all the way to the <site-navigation> root element, but stop there (to avoid polluting the wider DOM). You can listen on the root element or to individual Drawers for the drawer-state-change event. The detail property on the event includes the element that displatched the event (el) and the state to which the Drawer is being set (action).

You can’t perform that action at this time.