Site Bar

A thin bar across the top of a whole site. Items can open a full-width menu panel while the page behind blurs.

Hover Cameras or Lenses, or tab to the arrow beside them and press Enter.

import { SiteBar } from '@brand-studio/ui';

const shop = [{ label: 'Buy a camera', href: '#buy' }, { label: 'Compare kits', href: '#compare' }, { label: 'Straps and cases', href: '#straps' }];

export default function SiteBarDemo() {
  // The transform keeps the menu's page curtain inside this frame instead of the docs page.
  return (
    <div style={{ position: 'relative', width: '100%', height: 340, overflow: 'hidden', transform: 'translateZ(0)' }}>
      <SiteBar
        brand={<a href="#">Halden</a>}
        items={[
          { label: 'Cameras', href: '#cameras', current: true, menu: [{ label: 'Explore cameras', links: [{ label: 'Halden R', href: '#r' }, { label: 'Halden S', href: '#s' }] }, { label: 'Shop', links: shop }] },
          { label: 'Lenses', href: '#lenses', menu: [{ label: 'Explore lenses', links: [{ label: '35 mm ƒ/2', href: '#35' }, { label: '50 mm ƒ/1.4', href: '#50' }] }, { label: 'Shop', links: shop }] },
          { label: 'Film', href: '#film' },
          { label: 'Service', href: '#service' },
        ]}
        actions={<a href="#bag">Bag</a>}
      />
      <p style={{ padding: '3rem 1.5rem', margin: 0, color: 'var(--bs-muted)' }}>Hover Cameras or Lenses, or tab to the arrow beside them and press Enter.</p>
    </div>
  );
}

Installation

pnpm add @brand-studio/ui

Usage

import { SiteBar } from '@brand-studio/ui';
<SiteBar
  brand={<a href="/">Halden</a>}
  items={[
    { label: 'Cameras', href: '/cameras', current: true, menu: [
      { label: 'Explore cameras', links: [{ label: 'Halden R', href: '/r' }] },
      { label: 'Shop', links: [{ label: 'Buy a camera', href: '/buy' }] },
    ] },
    { label: 'Film', href: '/film' },
  ]}
/>

The first group in each menu is set large, for the products; later groups hold smaller links. The bar scrolls away with the page unless you pass sticky. Stack a Product Bar under it for one product's pages; set --bs-productbar-top: 44px on the Product Bar when the Site Bar is sticky too.

Accessibility

  • The item link always goes to its page. A separate arrow button, with aria-expanded and aria-controls, opens the menu for keyboard and touch.
  • Escape closes the menu and returns focus to its button. Moving focus out of the bar closes it too.
  • Each menu group is a list labelled by its heading.
  • When the bar is narrower than 40rem, the items move into Mobile Navigation.

API Reference

PropTypeDefault
brandReact.ReactNode
itemsSiteBarItem[]
actions?React.ReactNode
label?string'Site'
sticky?booleanfalse
className?string''

Still, Deskhand and Hollis are fictional brands. The coffee photographs are original generated artwork. @brand-studio/ui is MIT licensed.