Skip to the page
TACTILE UI

Block · Navigation menus

Rail

A site's top bar made like the front edge of a hi-fi unit. A debossed wordmark plate, engraved links with a lit lamp under the current page, a search key and a call-to-action key with a real skirt. It condenses on scroll and folds into a Menu key and drawer on a narrow bar.

Version
0.1.0
Size
66.4 KB gzipped
Access
With a Pass
Needs
rail.mjs + rail.css
Tests
11 tests · 10 states
On this page
  1. Use it
  2. Options
  3. Methods
  4. States
  5. How it works
01

Use it

A navigation bar with the character of the rest of the page and none of the usual trouble. The current page is a lit lamp under an engraved label (the only colour on the bar), the bar condenses when the page scrolls while holding the same room in the layout so nothing jumps, and under 720px of its own width the links fold into a Menu key that opens a drawer with a real focus trap, Esc, focus return and aria-expanded. setCurrent(href) lets a router move the lamp; the search key fires an event for a command palette.

Copy the rail folder from its package next to your page, link the stylesheets and mount it on an element. Every option has a default; the lab’s Code tab writes the same example at any settings, and for React, Vue, Svelte or a custom element (Using a framework).

<link rel="stylesheet" href="rail/rail.css">
<div id="rail"></div>

<script type="module">
  import { mount } from './rail/rail.mjs';

  const rail = mount(document.getElementById('rail'), {
    brand: 'Lode',
    links: 'Runtime|Docs|Pricing|Changelog|Company',
    current: 'Docs',
  });

  // rail.update({ … });   change any option in place
  // rail.destroy();        and take it away again
</script>
02

Options

OptionTypeDefaultWhat it does
brandtext'Lode'Debossed into the plate.
linkstext'Runtime|Docs|Pricing|Changelog|Company'Separated by “|”, up to six. A link goes to “#” and its name unless you write Name=/path.
currenttext'Docs'A link’s name or its href. It gets the lamp and aria-current. Empty: no lamp.
searchbooleantrueA key that fires rl-search; wire it to your command palette or search page.
ctatext'Start free'Call to action
ctaHreftext'#start'A page, a path, an anchor, mailto: or tel:.
stickybooleantrueSticks to the top of the page or of the scrolling box it sits in. Condensing needs it.
finishauto · aluminium · graphite'auto'Auto follows the page’s data-finish, then the visitor’s system.
03

Methods

mount(element, options)
Builds the block inside the element and returns its handle.
handle.setCurrent(href)
Move the lamp to the link whose href (or label) is href; none matches: no lamp.
handle.open()
handle.close()
handle.condensed
handle.update(next = {})
Change options in place.
handle.destroy()
Stops it and cleans up after it.

Events it fires, which bubble from the element: rl-menu, rl-navigate, rl-search.

04

States

  1. At the topA 64px bar: the wordmark on its recessed plate, five engraved links, a light search key and the dark call-to-action key; a lit green lamp under the current link, dark lamps under the others.
  2. ScrolledPast 24px of scroll the bar condenses to 48px in 180 ms, the plate and the wordmark tighten and the shadow lengthens; it relaxes again below 8px (no flicker at the line). The room it holds does not change.
  3. Link usedrl-navigate fires (cancelable); if it is not cancelled the lamp moves to the link. setCurrent('/pricing') does the same from a router; an unknown href leaves no lamp.
  4. Key pressedThe search key and the call to action drop 2px onto their pressed shadow.
  5. FoldedUnder 720px of the bar's own width the links and the bar's call to action are hidden; a Menu key shows beside the search key.
  6. Drawer openThe Menu key's lines turn into ×, aria-expanded is true, the drawer slides down under the bar and focus moves into it. Tab and Shift+Tab wrap (the Menu key is the first stop); Esc closes it and returns focus to the key; a press outside closes it; choosing a link closes it.
  7. Widened while openPast 720px the drawer closes itself and the links come back.
  8. KeyboardEvery link, key and drawer row is a stop with a 2px focus ring.
  9. Reduced motionThe bar, keys, lines, lamps and drawer change without transitions.
  10. FinishesAluminium and graphite by data-finish; on graphite the contrast key turns light.
05

How it works

Made of: Debossed plate, Engraved labels, Current page lamp, Condense on passive scroll, Constant layout height, Container query fold, Focus trap drawer, Aria expanded menu key, Skirted keys, Concentric radii, Finish following.

Original composition. The product (Lode) and its links are invented. The plate, the keys and the lamps are CSS drawn here in the kit's tokens; no image. The scroll listener is passive; scroll-driven CSS was left out so the condensing state is a real attribute a page can read. Face: Instrument Sans (SIL OFL 1.1), the kit's own.

Docs
Finish
Volume