Block Header
A live block's header row in a page — icon · title · View ▾ · Filter · More · ↗ Open — with an empty state that hosts the source picker.
- Status
- Since
0.25.89- Accessibility pattern
- ⋯ menu and Open link named; picker named by the host
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Block Header before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify block-headerInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/block-headerRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/button, @vegastack/dropdown-menu.
Usage
import {
BlockHeader,
BlockHeaderButton,
BlockHeaderOpen,
} from "@/components/ui/block-header";
<DataGrid
embedded
toolbar={
<BlockHeader
icon={<Table2 />}
title={table.name}
menu={<DropdownMenuItem onClick={remove}>Remove block</DropdownMenuItem>}
open={<BlockHeaderOpen render={<Link href={table.href} />} />}
>
<ViewMenu trigger={<BlockHeaderButton />} />
<FilterPopover trigger={<BlockHeaderButton />} />
</BlockHeader>
}
{...grid}
/>;The one header row of a live block inside a page — a table view, a task list, any block that shows
records from somewhere else. Left to right: the block's kind as an icon, what it shows, its
controls (BlockHeaderButtons that open the host's View and Filter popovers), the ⋯ menu and
↗ Open, a link to the source's own page. A block with no source yet passes picker instead: it
sits where the title will be ("Pick a table…"), so a block inserts at once and is set up where it
sits rather than in a dialog first.
Scope
- Owns: the row's layout, the ⋯ menu trigger, the Open link's look, the empty state's place for a picker, wrapping on a narrow block.
- Does not own: the source picker, the View and Filter popovers, or what they change — those are
the host's. Nor the block's frame:
DataGrid embeddedrules the header off as its top, a task list block puts it over its rows. - Compose with:
DataGridembeddedas itstoolbar; aDropdownMenuTriggerorPopoverTriggerwithrender={<BlockHeaderButton />}.
Anatomy
Examples
Table block
The title truncates; the controls follow it, and the ⋯ menu and Open sit at the end.
Before a source is picked
picker replaces the title and the controls. Pick a table in the preview: the header becomes the
ready row; Change table in ⋯ brings the picker back.
Task list block, and a narrow column
The same header serves a task list. In a narrow block the controls wrap under the title and, under 20rem, Open shows its icon alone (its label stays the link's name).
API Reference
BlockHeader
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | The block's controls after the title — BlockHeaderButtons such as View ▾ and Filter.
Hidden while picker shows. |
icon | React.ReactNode | — | The block's kind, as an icon (a table, a task list). Decorative. |
menu | React.ReactNode | — | Items for the ⋯ menu (DropdownMenuItems) — Copy link, Remove block. No menu without it. |
menuLabel | string | "Block actions" | The ⋯ trigger's accessible name. |
open | React.ReactNode | — | The ↗ Open link at the end — a BlockHeaderOpen to the source's own page. |
picker | React.ReactNode | — | The empty state: a picker for the block's source ("Pick a table…"), shown in place of the title and the controls. Pass it only while the block has no source. |
title | React.ReactNode | — | What the block shows — the source's name ("QA fixtures", "Tasks · My open"). |
Data attributes and CSS variables on BlockHeader
| Attribute | Values |
|---|---|
data-slot | "block-header" | "block-header-actions" | "block-header-controls" | "block-header-icon" | "block-header-menu" | "block-header-picker" | "block-header-title" |
data-state | "empty" | "ready" |
BlockHeaderButton
BlockHeaderButton takes Button's props: a small quiet ghost button in the muted ink.
BlockHeaderOpen
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | "Open" | The visible label — and the accessible name when the block is too narrow to show it. |
render | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | <a /> | The link element — a router link such as <Link href="/tables/qa" />. It receives the
classes, the icon and the label; this component's own href and handlers win over the
template's (handlers run both). |
Accessibility
- The icon is decorative; the title is plain text — name the block's content (the grid's
aria-label, the task list's label) for assistive technology. - The ⋯ trigger is named by
menuLabel("Block actions"). - Open is a real link, so it opens in a new tab with a modified click; on a narrow block its label is visually hidden but still names it.
- The picker is the host's control and carries its own name.
| Key | Action |
|---|---|
| Tab | Moves through the controls, ⋯ and Open |
| Enter / Space | Opens a control's popover or the menu |
| Escape | Closes the open popover or menu |
| Contract | States tested |
|---|---|
| Behaviour | default, empty, menu-open, narrow |
| Accessibility | labeled, keyboard, browser-accessibility-test |
| Visual | default, hover, focus, open, empty |
Do / Don't
Data Grid
The full-parity grid — multi-key sort, frozen and resizable columns, grouping, row and column virtualization, a summary row, and APG cell editing.
Recent Strip
One row of the records a person opened last, as compact cards in a sideways strip with edge fades and arrow keys, and a single line of chips on a phone.