Skip to content

HySidebar ​

Usage examples on this page are written for Lit / plain HTML (<hy-sidebar>). The same component ships as HySidebar in @whitespaceux/harmony-react (native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.

Child components: <hy-sidebar-group>, <hy-sidebar-item> — used only inside this one.

A persistent navigation rail with collapse-to-icon-only state.

hy-sidebar is a single <nav> landmark — it does not wrap in <aside>, because <aside> is itself a complementary landmark and nesting the two would expose two landmarks for one purpose.

Pair with hy-sidebar-group for titled sections and hy-sidebar-item for rows. On mobile, wrap the sidebar inside hy-drawer — the drawer provides overlay/focus-trap semantics, the sidebar provides the content.

When to use

  • The main destinations of an application with more than a few sections.
  • Destinations that fall into groups, with hy-sidebar-group.

Do

  • Make it collapsible when the work needs the width.

When not to use

  • Two or three destinations: navigation in an hy-topbar, or hy-tab-nav.
  • A phone-first screen: hy-bottombar for the top-level destinations, or a temporary hy-drawer for a menu opened on demand.
  • Switching between views inside one page: hy-tab-group.

Accessibility: your part ​

  • Mark exactly one hy-sidebar-item active: the current page.
  • With collapsible or collapsed, give every hy-sidebar-item a leading icon. A collapsed item without one shows as an empty row.

Examples ​

html
<hy-sidebar label="Main navigation">
  <div slot="header">Edelweiss</div>
  <hy-sidebar-group label="Workspace">
    <hy-sidebar-item label="Dashboard" value="dashboard" href="/dashboard" active>
      <hy-icon slot="leading" name="home" decorative></hy-icon>
    </hy-sidebar-item>
    <hy-sidebar-item label="Projects" value="projects" href="/projects">
      <hy-icon slot="leading" name="folder" decorative></hy-icon>
    </hy-sidebar-item>
  </hy-sidebar-group>
  <hy-sidebar-group label="Settings">
    <hy-sidebar-item label="Preferences" value="preferences" href="/preferences">
      <hy-icon slot="leading" name="settings" decorative></hy-icon>
    </hy-sidebar-item>
  </hy-sidebar-group>
</hy-sidebar>

Collapsible rail with the built-in toggle ​

html
<hy-sidebar collapsible toggle-placement="header-end" width-expanded="280px">
  <div slot="header">Edelweiss</div>
  <hy-sidebar-item label="Home" value="home" href="/">
    <hy-icon slot="leading" name="home" decorative></hy-icon>
  </hy-sidebar-item>
</hy-sidebar>
<script>
  document.querySelector('hy-sidebar').addEventListener('collapse', (e) => {
    console.log(e.detail.collapsed);
  });
</script>

API ​

Properties ​

PropertyAttributeTypeDefaultDescription
collapsedcollapsedbooleanfalseWhether the sidebar is collapsed to icon-only mode.
collapsiblecollapsiblebooleanfalseWhether to render a built-in collapse toggle at the top of the sidebar. The toggle is an hy-icon-button so its hit-area, hover/focus styling and theming follow the same scale as every other icon-button in the system (32px at size="small"). The icon name is hard-coded to arrow-collapse so consumers can't accidentally pass an undefined value — the historical foot-gun this slot was designed to avoid.
embeddedembeddedbooleanfalseSet inside a panel that already draws the frame (an app pane, a splitter panel): the sidebar fills the panel's width, paints no surface of its own (the panel's fill shows through), draws no edge of its own (the stroke stays, transparent, so nothing moves; under forced colors too, where the panel's own divider stands) and its header, scroller and footer sit flush — no block padding, no gap between them — so the content sets its own rhythm. The inline padding stays. The shape of a navigation list inside a layout pane (Primer's NavList in a PageLayout pane, Fluent's Nav).
placementplacement'start' | 'end''start'Which edge of the parent the sidebar sits on.
togglePlacementtoggle-placement'top-corner' | 'header-end''top-corner'Where the built-in collapse toggle is placed. See SidebarTogglePlacement for the visual contract of each value. Default top-corner preserves pre-existing behavior; pick header-end when the brand mark is the visual anchor and the toggle should sit below it (Material 3 / modern SaaS pattern).
labellabelstring'Main navigation'Accessible label for the <nav> landmark.
collapseLabelcollapse-labelstring'Collapse'Label on the collapse toggle when the sidebar is expanded.
expandLabelexpand-labelstring'Expand'Label on the collapse toggle when the sidebar is collapsed.
widthExpandedwidth-expandedstring''Width when expanded. Escape hatch; writes --hy-sidebar-width-expanded inline.
widthCollapsedwidth-collapsedstring''Width when collapsed. Escape hatch; writes --hy-sidebar-width-collapsed inline.

Events ​

EventDetailDescription
collapse—Fired on every collapse state change. Detail: { collapsed: boolean }

Slots ​

SlotDescription
headerLogo, brand, or title above the nav. Stays visible when collapsed. Slot icon-only content (≈32px) that reads in the narrow rail. Position relative to the collapse toggle depends on togglePlacement — see that property for the visual contract.
defaultItems and groups.
footerAccount, settings, version badge. Hidden chrome when empty.

CSS Parts ​

PartDescription
baseThe <nav> landmark.
headerHeader region.
contentScrollable middle region containing items/groups.
footerFooter region.
collapse-toggleThe built-in collapse toggle button (only rendered when collapsible).

CSS Custom Properties ​

The documented hooks. Every override hook the component reads — one per token it paints — is listed in @whitespaceux/harmony/theme-api.json, and @whitespaceux/harmony/component-bindings.json (the Harmony MCP get-bindings tool) says which part and state each one paints.

PropertyDefaultDescription
--hy-sidebar-width-expanded—Width when expanded (default: 260px)
--hy-sidebar-width-collapsed—Width when collapsed (default: 64px)
--hy-sidebar-background-surface-basevar(--hy-background-surface-base)Background color (default: surface-base)
--hy-sidebar-border-default-restvar(--hy-border-default-rest)Border color (default: border-default-rest)
--hy-sidebar-padding-shell-blockvar(--hy-padding-shell-block)Block padding for header/content/footer
--hy-sidebar-padding-shell-inlinevar(--hy-padding-shell-inline)Inline padding for header/content/footer
--hy-sidebar-gap-shell-blockvar(--hy-gap-shell-block)Gap between items at the root
--hy-sidebar-padding-layout-nonevar(--hy-padding-layout-none)Block padding of header, content and footer when embedded
--hy-sidebar-gap-layout-nonevar(--hy-gap-layout-none)Gap between header, content and footer when embedded
--hy-sidebar-motion-transition-expand-durationvar(--hy-motion-transition-expand-duration)Collapse transition duration
--hy-sidebar-padding-layout-smvar(--hy-padding-layout-sm)Distance from the top + inline-end corner to the absolute-positioned collapse toggle (default: padding-sm)
--hy-sidebar-collapsed—Host-scope variable exposing 1 (collapsed) or 0 (expanded) for descendant / consumer styling (read it via var(); nothing in Harmony consumes it yet)
--hy-sidebar-motion-transition-expand-easingvar(--hy-motion-transition-expand-easing)Easing for the collapse and expand transition

Methods ​

expand() ​

Expand the sidebar. No-op if already expanded.

collapse() ​

Collapse the sidebar. No-op if already collapsed.

toggle() ​

Toggle the collapsed state.

Built with Lit. Documented with VitePress.