Skip to content

No.206 · Navbars· New

Docket Nav

A product navbar that knows where you are: a hairline under the links slides to the section in view, and on a narrow bar the links fold into a Menu that still names the current section and opens into a numbered docket.

The prompt

Copy this text

Automatic copying is unavailable. Copy the selected text using your device’s copy command.

Written for the variant you picked above: Paper

Build a sticky product navbar that reports position instead of decorating. A 60px bar: brand (small square mark and name) on the left, section links, one solid call to action on the right. Hairline border appears under the bar only once the page has scrolled. Scrollspy. The active link is the last section whose top has passed a line at header height + 33% of the viewport; at the very bottom of the scroll the last link is active. Use scroll and resize listeners throttled with requestAnimationFrame, and a scroll container passed as scrollRef (falls back to window). The active link gets aria-current="location". The marker. A single 2px hairline sits on the bar's bottom edge. It is one element that is moved with transform only: translateX to the active link's measured offsetLeft (+10px of link padding) and scaleX to its measured width (-20px), 380ms cubic-bezier(.2,.8,.2,1). It appears (opacity) only after the first measurement so it never slides in from the left. Re-measure with a ResizeObserver. Narrow bars. Use a container query (container-type: inline-size, breakpoint 44rem), never a viewport query. Below it, links and the CTA leave the bar and a Menu button takes their place: the word "Menu" (or "Close") and, beside it in 11px mono capitals, the current section as "02 Changelog". Opening grows a docket below the bar with grid-template-rows 0fr to 1fr (320ms): a ruled ordered list in 24px serif, rows numbered 01, 02, 03 in mono, the current row in full ink with a small drawn tick, the rest muted, then the CTA full width. Rows arrive with a 40ms stagger. Closed content is visibility: hidden so it leaves the tab order. Production behaviour: link clicks scroll the section to just under the bar (smooth unless reduced motion), move focus to the section, and close the docket. Escape closes it and returns focus to the Menu button, as does a pointerdown outside. Menu has aria-expanded and aria-controls. Paper and Night themes. Selected variant — Paper (paper): Palette for this theme (Paper): --dn-accent #2f6bff; --dn-bg #f6f5f1; --dn-ink #1b1a17; --dn-line rgb(27 26 23 / 0.1); --dn-muted #6b6861; --dn-on-ink #ffffff. Treat these as the root colour tokens, one value per role, and name them to suit your code. Select it with the theme option set to "paper". Keep every dimension, spacing value, state and motion from the brief unchanged, and keep text at 4.5:1 contrast or better on these surfaces. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Scroll and the hairline follows the section in view. Click a link to travel there. Narrow the bar and open Menu, then pick a row; Escape closes it. Motion: Marker slide 380ms; docket grow 320ms; rows rise 320ms with a 40ms stagger; current-section label rises 240ms when it changes. Accessibility: A header with a labelled nav; the active link is aria-current="location". The Menu button exposes aria-expanded and aria-controls, and the closed docket is hidden from the tab order. Escape closes it and restores focus. Reduced motion removes the marker slide, the stagger and smooth scrolling; the state changes still happen. Responsive behavior: Driven by the bar's own width with a container query at 44rem; the menu button is 44px tall. Touch: Nothing depends on hover. Tap Menu, tap a row, tap outside to close. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.

Notes

Interaction
Scroll and the hairline follows the section in view. Click a link to travel there. Narrow the bar and open Menu, then pick a row; Escape closes it.
Motion
Marker slide 380ms; docket grow 320ms; rows rise 320ms with a 40ms stagger; current-section label rises 240ms when it changes.
Accessibility
A header with a labelled nav; the active link is aria-current="location". The Menu button exposes aria-expanded and aria-controls, and the closed docket is hidden from the tab order. Escape closes it and restores focus. Reduced motion removes the marker slide, the stagger and smooth scrolling; the state changes still happen.
Responsive
Driven by the bar's own width with a container query at 44rem; the menu button is 44px tall.
On touch
Nothing depends on hover. Tap Menu, tap a row, tap outside to close.

Featured

425 components