jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

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.

two wings, never mixed composed nav · family parts authored mega grids drawer snippet · 2 tiers

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.

architecture
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
terminal-header-usage.svelte svelte
<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-current flips), because it never sees your nav data
  • opt panels into the bezel surface with jx-subpanel (jx-subpanel-mega for the wide multi-column ceiling); the column count is your grid — navColumns died with the config tree
  • panels stay the browser's — popover="auto" light dismiss, Escape, one-at-a-time, CSS anchoring; the header adds only closeAll() navigation cleanup
  • the drawer is a shell: hamburger fold, bounded scroller, Escape; your snippet holds the rows, and bind:open is your reset signal for disclosure state
usage
<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.

desktop tier (≥sm)

Full brand stack + pill group with the sliding indicator + switcher slot.

mobile tier (<sm)

Hamburger folds the drawer snippet into a grid-rows 0fr→1fr disclosure, bounded by the in-bar scroller.

bezel lock

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.

TerminalHeader usage
<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

KeyAction
TabBrand, the family roving pill walk, switcher — in wing order
EscapeCloses the drawer and any open panel (popover=auto native behavior)

ARIA

AttributeValueDescription
aria-currentpageThe indicator repaints from the DOM — the header never sees your nav data
bannerlandmarkThe bar renders once per site; a second instance would duplicate the primary navigation
popoverautoPanels 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.

xs
brand wingpill wing
sm
brand wingpill wing
default
brand wingpill wing
lg
brand wingpill wing
TokenDefaultSource
--jx-pop-padpanel block padcomponent
--jx-pop-pad-inlinepanel inline padcomponent
--jx-panel-padsubpanel padcomponent
--jx-surface-solid-fillsolid bezel fillcolor
--jx-surface-acrylic-fillacrylic bezel fillcolor
--jx-surface-border-colorbezel bordercolor

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.

terminal-header-universal.svelte svelte
<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

PropertyTypeDefaultDescription
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 booleantrueWrap 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 bindboolean—The drawer's open state; bind:open is your reset signal.
class string''Class passthrough to the bar root.

Universal props

PropertyTypeDefaultDescription
size'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopethe base scale — root font-size; parts size in em
shape'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto' · ambient scopecorner geometry (CSS corner-shape; §14 degrade table)
radius'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopecorner size; auto = the concentric broadcast (§3)
density'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopespacing/leading scale over the kernel channels (§4)
color'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto' · ambient scopethe hue axis of the fixed oklch primary system (§5)
theme'light' | 'dark' | 'system' | 'auto''auto' · ambient scopelight/dark profile; system = the JS-mutable global (§6)
elevation'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto' · ambient scopeofficial M3 levels over the surface ladder (§7)
motion'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto' · ambient scopeintensity across the motion kernels (§8)
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h