Header
A site header bar with branding, navigation, actions, and a responsive hamburger and drawer built in. It composes Nav horizontally in the bar and vertically in the drawer, so one item set drives both.
Import
import { Header } from "@hyzer-labs/ui"Demo
Pass items plus the logo and actions snippets.
Header composes a Nav from those same items: horizontal
in the bar, vertical in the mobile drawer. There is nothing for you to wrap.
// No need for a Home item — the logo is the link home.
const navItems: NavItem[] = [
{
// No href — the whole label is the dropdown trigger.
label: 'Components',
children: [
{ label: 'Button', href: '#' },
{ label: 'Card', href: '#' }
]
},
{ label: 'Foundation', href: '#' },
{ label: 'Media', href: '#' }
];
<Header items={navItems} bordered>
{#snippet logo()}<Logo />{/snippet}
{#snippet actions()}<Button size="sm">Sign in</Button>{/snippet}
</Header>variant sets the bar surface; bordered adds a bottom hairline
that composes with either. Each demo sits on a tinted backdrop that is not part of
Header, so transparent has something to show through.
<Header items={navItems} /><Header items={navItems} bordered /><Header items={navItems} variant="transparent" bordered />Drag under 968px and the bar collapses to the hamburger. actions stays in
the collapsed bar, pinned to the end next to the hamburger; override margin-inline-start on .hz-header-actions to move it somewhere else.
Open the drawer to see the vertical Nav with the actions repeated below it. The drawer traps
focus, and Escape closes it.
mobileBreakpoint takes the named tiers ('sm' | 'md' | 'lg'),
which are container queries against the header's own width and need no JavaScript. A px
number measures that same width at runtime instead. Reach for a number once you have
retuned --hz-width-*: a named tier cannot follow that override, because CSS
cannot read a custom property inside a container query. Before hydration a number
renders as its nearest named tier, so a page without JavaScript still collapses at a
sensible width.
collapsed, try the hamburger
<!-- Below the breakpoint the bar hands over to a hamburger + drawer
(a container query on the header width). The drawer holds a
vertical Nav + the actions, and traps focus while open. -->
<Header items={navItems} mobileBreakpoint="md">
{#snippet logo()}<Logo />{/snippet}
{#snippet actions()}<Button size="sm">Sign in</Button>{/snippet}
</Header>Two snippets restyle the header's icons. menuIcon replaces the hamburger in
the collapsed bar. chevronIcon is forwarded to both Navs, so it replaces
the dropdown chevron in the bar and the drawer alike. The theme rotates that chevron
180° while a menu is open, so pick one that reads both ways, like an arrow. Any of the
shared icons works, as does any inline SVG; size and stroke
are the icon's own props.
Drag under 968px to see the custom hamburger; widen for the bar chevron.
collapsed, custom hamburger
<Header items={navItems}>
{#snippet logo()}<Logo />{/snippet}
{#snippet menuIcon()}<IconGrip size={20} />{/snippet}
{#snippet chevronIcon()}<IconArrowDown size={14} strokeWidth={1.5} />{/snippet}
</Header>Props
| Name | Type | Default | Note |
|---|---|---|---|
items | NavItem[] | — | Navigation — rendered horizontally in the bar and vertically in the drawer. See Nav. |
logo | Snippet | — | Logo region at the start. |
actions | Snippet | — | End of the bar; repeated inside the drawer. |
sticky | boolean | false | position: sticky at the top of the nearest scroll container. |
variant | 'default' | 'transparent' | 'default' | |
bordered | boolean | false | Bottom hairline — composes with any variant. |
mobileBreakpoint | 'sm' | 'md' | 'lg' | 'none' | number | 'md' | Below this width the bar collapses into a hamburger and drawer. The named tiers are CSS-only container queries against the header's own width (640/968/1200px); 'none' never collapses. A px number measures the header at runtime instead, for a width scale you have retuned. |
ariaLabel | string | 'Main navigation' | Names the navigation. |
open | boolean | false | Bindable. The mobile drawer state — close it on navigation, or drive it externally. Activating a drawer link closes the drawer on its own. |
menuIcon | Snippet | — | Replaces the hamburger icon. |
chevronIcon | Snippet | — | Forwarded to the Nav. |
navItemClass | string | — | Forwarded to both Navs as their itemClass — one class on every rendered nav link, bar and drawer. class stays the root header hook. |
class | string | — | Merged after the hz-header class. |
Anything not listed above is forwarded as an attribute to the root element (or the native control in form components). So id, data-*, aria-*, and event handlers just work.
Theme hooks
What this component promises your CSS. The reference theme styles exactly these — from @layer hz-theme, so your unlayered rules win. See Styling Components for the how.
Root class: .hz-header
Data attributes
| Hook | Values | Styles |
|---|---|---|
data-variant | 'default' | 'transparent' | Bar surface treatment. Default default. |
data-bordered | present when bordered | Bottom hairline. Composes with any variant. |
data-sticky | present when sticky | Sticks the bar to the top. |
data-mobile-breakpoint | 'sm' | 'md' | 'lg' | 'none' | Which width collapses the bar into the drawer. none never collapses. Default md. |
data-state | 'open' | 'closed' | On .hz-header-drawer — the drawer open/closed vocabulary to animate against. |
Part classes
| Hook | Values | Styles |
|---|---|---|
.hz-header-inner | child element | The flex bar; owns its padding. |
.hz-header-logo | child element | Wrapper for the logo snippet. |
.hz-header-actions | child element | Wrapper for the actions snippet (in the bar). Below the mobile breakpoint, an auto inline-start margin pins it to the end, next to the hamburger — override margin-inline-start on this class (e.g. via a descendant selector off your own class prop) for centering or any other placement. |
.hz-header-toggle | child element | The hamburger button. |
.hz-header-drawer | child element | The mobile drawer. |
.hz-header-drawer-actions | child element | The actions repeated inside the drawer. |
Accessibility
The header is a banner landmark. Its bar and drawer each render a Nav landmark with distinct accessible names (ariaLabel and ariaLabel (menu)), so they do not collide.
The hamburger carries aria-expanded and aria-controls. The open drawer traps focus. Escape closes it and returns focus to the toggle.
At narrow widths, the drawer keeps every link reachable.
References: MDN: <header> · MDN: <nav>