Pane Header
A horizontal header bar for a pane, panel, sidebar, or sheet. Title on the left, optional metadata or breadcrumb chips, action buttons on the right. Common in IDE-style interfaces, dashboards, and configuration panels. A sticky mode pins the bar to the top of its scroll container with a backdrop-blur wash.
Settings
Workspace · Editor preferencesPane body — content sits below the header.
Customize
Surface
default
md
Behavior
Installation
npx shadcn@latest add https://craftbits.dev/r/pane-header.jsonUsage
Drop a <PaneHeader> at the top of any scrollable region. Title on the left; the right cluster takes any action node.
import { PaneHeader, Button } from "@craft-bits/core";
<PaneHeader
title="Settings"
subtitle="Workspace · Editor preferences"
actions={
<>
<Button variant="ghost" size="sm">Cancel</Button>
<Button variant="primary" size="sm">Save</Button>
</>
}
/>Add an eyebrow for a small mono caps label above the title:
<PaneHeader
eyebrow="WORKSPACE"
title="Editor preferences"
meta={<Badge>3 unsaved</Badge>}
/>Pin the bar with sticky when the body scrolls:
<section className="overflow-auto">
<PaneHeader sticky title="Files" actions={<Button size="sm">New</Button>} />
{/* body scrolls — the header stays put with a backdrop blur */}
</section>Understanding the component
- Landmark by default. Always renders a
<header>so the pane bar is announced as a banner-like region. Norolewrapping needed at the call site. - Two clusters, one row. Left cluster stacks
eyebrow(mono caps),title(semibold, balanced wrap),subtitle(muted), and inlinemetachips. Right cluster is the actions slot — a flex row withgap-2. The left cluster auto-sizes (min-w-0 flex-1) so titles truncate before pushing actions off the bar. - Three variants.
default(hairline bottom border on--cb-bg),elevated(the bar floats — a layered low-alpha shadow, never pure black),subtle(muted background with no border — recedes into a sidebar). - Sticky as a prop. When
stickyis true, the header getsposition: sticky; top: 0plus abackdrop-filter: blur(...)wash keyed on--cb-bg. Z-index stays at10so modals and tooltips still win. - Depth via shadow, not border. The
elevatedvariant layers a hairline plus a longer ambient shadow. Both derive from--cb-fgviacolor-mix()at low alpha — they re-tone with theme and never produce the unnatural pure-black halo. - Truncation, then balance. Titles get
truncateso they ellide in narrow containers, plustext-wrap: balancefor the rare multi-line case. - Data-attributes for nested styling. The root carries
data-cb-pane-header,data-variant,data-size, anddata-stickyso the consumer can target nested elements without re-deriving the props.
Props
PaneHeader
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — | Primary label. Sits in the left cluster, semibold. |
subtitle | ReactNode | — | Secondary line under the title — context, path, count, etc. |
eyebrow | ReactNode | — | Small uppercase mono caps label above the title. |
meta | ReactNode | — | Chips / badges / breadcrumbs inline beside the title. |
actions | ReactNode | — | Right-side button cluster. |
sticky | boolean | false | Pin to the top of the scroll container with a backdrop-blur wash. |
size | 'sm' | 'md' | 'lg' | 'md' | Height + horizontal padding + title typescale. |
variant | 'default' | 'elevated' | 'subtle' | 'default' | Surface treatment. elevated adds a layered low-alpha shadow; subtle swaps to a muted background. |
className | string | — | Merged onto the rendered <header>. |
...rest | Omit<HTMLAttributes<HTMLElement>, 'title'> | — | Any other <header> prop. title is shadowed because we accept it as a ReactNode, not the native string attribute. |
Accessibility
- The root renders a
<header>element. Inside a<section>or<article>, that means assistive tech labels the bar as a header for the surrounding region. - Action buttons in the right cluster carry their own focus rings (they're standard
<Button>instances). The header itself is not interactive; focus passes through to its children. - Color contrast: the title uses
--cb-fgand the subtitle uses--cb-fg-muted— both pass WCAG AA against every default surface (--cb-bg,--cb-bg-elevated,--cb-bg-muted). - The sticky backdrop blur is
supports-[backdrop-filter]guarded — browsers withoutbackdrop-filterget a slightly more opaque fallback so text behind the bar never bleeds through. - No motion. Theme transitions are limited to color + box-shadow at
duration-150, well under the 300ms cap.
Credits
- Extracted from:
craftingattention(app/src/components/ui/PaneHeader.tsx). The original took a flatlabelstring + a singlemetaandtrailingslot and rendered a fixed-height pane bar with project-specific--color-ink-*/--color-surface-raisedtokens. craft-bits widens the API totitle/subtitle/eyebrow/meta/actions, rewires onto--cb-*tokens, adds three surface variants and three sizes, and lifts the bar onto a<header>landmark with a sticky mode.