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 preferences
Pane body — content sits below the header.
Customize
Surface
default
md
Behavior

Installation

npx shadcn@latest add https://craftbits.dev/r/pane-header.json

Usage

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

  1. Landmark by default. Always renders a <header> so the pane bar is announced as a banner-like region. No role wrapping needed at the call site.
  2. Two clusters, one row. Left cluster stacks eyebrow (mono caps), title (semibold, balanced wrap), subtitle (muted), and inline meta chips. Right cluster is the actions slot — a flex row with gap-2. The left cluster auto-sizes (min-w-0 flex-1) so titles truncate before pushing actions off the bar.
  3. 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).
  4. Sticky as a prop. When sticky is true, the header gets position: sticky; top: 0 plus a backdrop-filter: blur(...) wash keyed on --cb-bg. Z-index stays at 10 so modals and tooltips still win.
  5. Depth via shadow, not border. The elevated variant layers a hairline plus a longer ambient shadow. Both derive from --cb-fg via color-mix() at low alpha — they re-tone with theme and never produce the unnatural pure-black halo.
  6. Truncation, then balance. Titles get truncate so they ellide in narrow containers, plus text-wrap: balance for the rare multi-line case.
  7. Data-attributes for nested styling. The root carries data-cb-pane-header, data-variant, data-size, and data-sticky so the consumer can target nested elements without re-deriving the props.

Props

PaneHeader

PropTypeDefaultDescription
titleReactNodePrimary label. Sits in the left cluster, semibold.
subtitleReactNodeSecondary line under the title — context, path, count, etc.
eyebrowReactNodeSmall uppercase mono caps label above the title.
metaReactNodeChips / badges / breadcrumbs inline beside the title.
actionsReactNodeRight-side button cluster.
stickybooleanfalsePin 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.
classNamestringMerged onto the rendered <header>.
...restOmit<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-fg and 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 without backdrop-filter get 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 flat label string + a single meta and trailing slot and rendered a fixed-height pane bar with project-specific --color-ink-* / --color-surface-raised tokens. craft-bits widens the API to title/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.