registry:ui · Layout
terminal-header — the two-wing bezel, chrome only
The site nav bar: LEFT carries the brand (logo slot, wordmark, domain, subtitle — the page's identity), RIGHT carries the navigation pill group plus the switcher slot — the wings never mix, and the bar is a CRT bezel locked dark by default (theme="light" or "system" unlocks). The header owns CHROME ONLY: the nav slot hosts composed navigation-menu parts — triggers with panels whose mega grids you author inside, links-only entries as bare links — and the mobile drawer holds your drawer snippet behind the hamburger fold. The three-level item config tree is gone: what renders is your tree.
terminal-header
A header cannot nest inside a header — this page already wears the component at its top edge. The stage holds the architecture instead; the full source and the composed usage live in the code drawer.
live stage, replaced
You are already wearing the demo
The bar above this page — brand left, pills right, hue switcher in the switcher slot — is the component, rendered exactly once by the site layout with the nav composed from the navigation-menu family. Rendering a second instance here would nest one banner landmark inside the page and duplicate the primary navigation, so the stage shows the structure instead.
Open the code drawer below for the verbatim source (the chrome + the three css bands), then click the Docs pill in the real header above — the mega panel that drops is the docs tree mapped onto NavigationMenuItem/Trigger/Panel in the layout, running live. On a narrow viewport the same routes fold into the hamburger drawer.
the two wings (desktop, >=sm) — they never mix
+---------------------------------------------------------------+
| [] jixoai-ui [ Overview |
| ui.jixoai.com Components v |
| the design language Tokens GitHub ]|
| <-- brand identity (chrome) --> <- composed nav + slot ->|
+---------------------------------------------------------------+
composition (composition-first-apis, 2026-08-25) — the header owns
CHROME ONLY; the nav is the navigation-menu family, composed in
<TerminalHeader> the bar shell, theme lock
<NavigationMenu> the pill box hosts the bar
<NavigationMenuLink> links-only entries, bare
<NavigationMenuItem> the pairing unit (one id)
<NavigationMenuTrigger> button; popovertarget wire
<NavigationMenuPanel> popover=auto; YOUR mega grid
</NavigationMenuPanel></NavigationMenuItem>
</NavigationMenu>
{#snippet drawer()}…{/snippet} the mobile tier's nav, yours
</TerminalHeader>
the chrome keeps: pill box + sliding indicator (vt-nav-active), the
hamburger fold + drawer collapse + Escape, closeAll() navigation
cleanup. TerminalNavItem / panelAction / navColumns are GONE.
two tiers
>=sm full brand stack + pill group + switcher
<sm hamburger -> grid-rows 0fr-to-1fr disclosure holding the
drawer snippet, bounded by the in-bar scroller<script lang="ts">
import TerminalHeader from '@ui/terminal-header.svelte';
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuPanel,
NavigationMenuLink,
} from '@ui/navigation-menu/index';
</script>
<!-- switcherFrame={false}: this example's ThemeToggle (compact default) carries its own bezel frame -->
<TerminalHeader brand="jixoai-ui" domain="ui.jixoai.com" subtitle="the jixoai design language" switcherFrame={false}>
<!-- the nav slot: composed family parts — panels carry YOUR markup -->
<NavigationMenu label="primary">
<NavigationMenuLink href="/" current>Overview</NavigationMenuLink>
<NavigationMenuItem>
<NavigationMenuTrigger current>Components</NavigationMenuTrigger>
<NavigationMenuPanel class="jx-subpanel jx-subpanel-mega">
<!-- the mega grid is authored INSIDE the panel -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(13.5rem,1fr))]">
<div class="jx-group …">
<a class="jx-sub-link" href="/docs/components/card">card</a>
</div>
</div>
</NavigationMenuPanel>
</NavigationMenuItem>
<NavigationMenuLink href="https://github.com/jixoai/ui">GitHub</NavigationMenuLink>
</NavigationMenu>
{#snippet switcher()}<ThemeToggle />{/snippet}
<!-- the mobile drawer's contents — the stacked tier's nav, yours -->
{#snippet drawer()}
<nav aria-label="primary">
<a href="/">Overview</a>
…disclosure rows authored in your tree…
</nav>
{/snippet}
</TerminalHeader>composition
How it attaches
The header renders once per site, inside the shell's header slot. It takes no nav data: the navigation is composed from the navigation-menu family into the default slot (the pill box), and the mobile drawer's contents arrive as the drawer snippet — structure lives in your tree, the bezel comes from the header.
- the pill box + the sliding indicator (
vt-nav-active) are chrome — the header repaints the indicator from the DOM (aria-currentflips), because it never sees your nav data - opt panels into the bezel surface with
jx-subpanel(jx-subpanel-megafor the wide multi-column ceiling); the column count is your grid —navColumnsdied with the config tree - panels stay the browser's —
popover="auto"light dismiss, Escape, one-at-a-time, CSS anchoring; the header adds onlycloseAll()navigation cleanup - the drawer is a shell: hamburger fold, bounded scroller, Escape; your snippet
holds the rows, and
bind:openis your reset signal for disclosure state
<script lang="ts">
import TerminalHeader from '@ui/terminal-header.svelte';
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuPanel,
NavigationMenuLink,
} from '@ui/navigation-menu/index';
</script>
<!-- switcherFrame={false}: this example's ThemeToggle (compact default) carries its own bezel frame -->
<TerminalHeader brand="jixoai-ui" domain="ui.jixoai.com" subtitle="the jixoai design language" switcherFrame={false}>
<!-- the nav slot: composed family parts — panels carry YOUR markup -->
<NavigationMenu label="primary">
<NavigationMenuLink href="/" current>Overview</NavigationMenuLink>
<NavigationMenuItem>
<NavigationMenuTrigger current>Components</NavigationMenuTrigger>
<NavigationMenuPanel class="jx-subpanel jx-subpanel-mega">
<!-- the mega grid is authored INSIDE the panel -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(13.5rem,1fr))]">
<div class="jx-group …">
<a class="jx-sub-link" href="/docs/components/card">card</a>
</div>
</div>
</NavigationMenuPanel>
</NavigationMenuItem>
<NavigationMenuLink href="https://github.com/jixoai/ui">GitHub</NavigationMenuLink>
</NavigationMenu>
{#snippet switcher()}<ThemeToggle />{/snippet}
<!-- the mobile drawer's contents — the stacked tier's nav, yours -->
{#snippet drawer()}
<nav aria-label="primary">
<a href="/">Overview</a>
…disclosure rows authored in your tree…
</nav>
{/snippet}
</TerminalHeader>types
Types
One bar shell, two tiers, three bezel locks — the nav itself is always composed family parts.
Full brand stack + pill group with the sliding indicator + switcher slot.
Hamburger folds the drawer snippet into a grid-rows 0fr→1fr disclosure, bounded by the in-bar scroller.
theme dark (default) | light | system — the CRT shell swap, same as terminal-card.
usage
Usage
Render once per site in the shell's header slot; compose the nav from the navigation-menu family.
<script lang="ts">
import TerminalHeader from '@ui/terminal-header.svelte';
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuTrigger,
NavigationMenuPanel,
NavigationMenuLink,
} from '@ui/navigation-menu/index';
</script>
<!-- switcherFrame={false}: this example's ThemeToggle (compact default) carries its own bezel frame -->
<TerminalHeader brand="jixoai-ui" domain="ui.jixoai.com" subtitle="the jixoai design language" switcherFrame={false}>
<!-- the nav slot: composed family parts — panels carry YOUR markup -->
<NavigationMenu label="primary">
<NavigationMenuLink href="/" current>Overview</NavigationMenuLink>
<NavigationMenuItem>
<NavigationMenuTrigger current>Components</NavigationMenuTrigger>
<NavigationMenuPanel class="jx-subpanel jx-subpanel-mega">
<!-- the mega grid is authored INSIDE the panel -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(13.5rem,1fr))]">
<div class="jx-group …">
<a class="jx-sub-link" href="/docs/components/card">card</a>
</div>
</div>
</NavigationMenuPanel>
</NavigationMenuItem>
<NavigationMenuLink href="https://github.com/jixoai/ui">GitHub</NavigationMenuLink>
</NavigationMenu>
{#snippet switcher()}<ThemeToggle />{/snippet}
<!-- the mobile drawer's contents — the stacked tier's nav, yours -->
{#snippet drawer()}
<nav aria-label="primary">
<a href="/">Overview</a>
…disclosure rows authored in your tree…
</nav>
{/snippet}
</TerminalHeader>a11y
Accessibility
A banner landmark whose panels stay the browser's popovers; the drawer is a disclosure with Escape.
Keyboard
| Key | Action |
|---|---|
| Tab | Brand, the family roving pill walk, switcher — in wing order |
| Escape | Closes the drawer and any open panel (popover=auto native behavior) |
ARIA
| Attribute | Value | Description |
|---|---|---|
| aria-current | page | The indicator repaints from the DOM — the header never sees your nav data |
| banner | landmark | The bar renders once per site; a second instance would duplicate the primary navigation |
| popover | auto | Panels get light dismiss + top layer from the platform; the header adds only closeAll() cleanup |
theming
Theming
Fixed chrome, no density scaling: the bezel speaks the surface tokens; the pill pads and panel pads are the css-band variables.
| Token | Default | Source |
|---|---|---|
| --jx-pop-pad | panel block pad | component |
| --jx-pop-pad-inline | panel inline pad | component |
| --jx-panel-pad | subpanel pad | component |
| --jx-surface-solid-fill | solid bezel fill | color |
| --jx-surface-acrylic-fill | acrylic bezel fill | color |
| --jx-surface-border-color | bezel border | color |
axes
Universal props
The eight-axis surface (explicit-props): size · shape · radius · density · color · theme · elevation · motion — each axis takes named steps, auto (inherit the ambient context; stamps nothing), an exact number (px · coefficient · dp · hue per axis), or query() for responsive/container-conditional values. The bezel bar carries SEVEN lanes: its `theme` prop is the SHELL lock (own-before-ambient), not the theme axis — §13 rules no rename, the axis forwards ambient (the ghostty-term precedent). The bar itself is flat chrome: elevation carries no own.
TerminalHeader · universal props
The header resolves the record once; the composed nav and switcher read the §11 supply through the component tree.
<TerminalHeader brand="jixoai" domain="ui" density="small" />api
API
Props from the TerminalHeader Props interface — brand strings, bezel lock, four snippet seams, and the switcher frame law.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| brand * | string | — | The wordmark line of the brand block. |
| domain | string | — | Second brand line (the domain). |
| subtitle | string | — | Third brand line — desktop tier only. |
| homeHref | string | — | The brand block's link target. |
| logo | Snippet | — | The brand mark (logo slot). |
| switcher | Snippet | — | Right-wing control slot (theme toggle, hue switcher…). |
| switcherFrame | boolean | true | Wrap the switcher slot in the bezel frame (border + p-0.5, the 38px outer band shared with the pill box); opt out for controls carrying their own frame. |
| children | Snippet | — | The desktop nav slot — compose NavigationMenu parts here. |
| drawer | Snippet | — | The mobile drawer's contents (the stacked tier's nav). |
open bind | boolean | — | The drawer's open state; bind:open is your reset signal. |
| class | string | '' | Class passthrough to the bar root. |
Universal props
| Property | Type | Default | Description |
|---|---|---|---|
| size | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | the base scale — root font-size; parts size in em |
| shape | 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto' | 'auto' · ambient scope | corner geometry (CSS corner-shape; §14 degrade table) |
| radius | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | corner size; auto = the concentric broadcast (§3) |
| density | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | spacing/leading scale over the kernel channels (§4) |
| color | 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string | 'auto' · ambient scope | the hue axis of the fixed oklch primary system (§5) |
| theme | 'light' | 'dark' | 'system' | 'auto' | 'auto' · ambient scope | light/dark profile; system = the JS-mutable global (§6) |
| elevation | 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number | 'auto' · ambient scope | official M3 levels over the surface ladder (§7) |
| motion | 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number | 'auto' · ambient scope | intensity across the motion kernels (§8) |