Skip to content

Panel

In review
Live · web

Header bar · body · footer, plus a collapsible panel

Session settings

nockerl-cli · primary

A panel is a persistent, in-layout region: a header bar with a title and actions, a padded body, and an optional footer. Larger than a card; not an overlay.

Unsaved changes

The header chevron collapses and expands the body. The transition animates grid height (flash-free) and freezes under reduced-motion. Click the header to toggle.

Toolbar row · inspector (key / value) · nested sections

Output

A toolbar row hosts secondary controls (toggles, actions) on a slightly raised tier between the header and the body. Word wrap is on.

Inspector

Selected session

Labelproject:nockerl-cli::primary
Enginecloud-agent
Modellarge-2.6
Statusidle
Last active12m ago

Advanced

Sampling

A panel can contain section panels: a nested surface a tier up, with its own header and body.

Permissions

Sections share the panel material at the control radius, divided by hairlines.

Split pane: two panels + a draggable, keyboard-operable splitter

Explorer

12 sessions

The left pane. Drag the splitter, or focus it and press Arrow Left / Right (Home / End to snap). Width is clamped between 25% and 75%.

Detail

nockerl-cli · gateway

The right pane fills the remaining space. A split-pane region stays in the layout; it is not an overlay like a drawer.

Saved 0 times · drag or arrow-key the splitter. The island is live.

The dev-console SIDE PANEL is a view, not a component

The web console’s dockable side panel (inspector, outline, agent details) is a composition of this Panel (with its working splitter) beside the main surface, optionally inside a Drawer on narrow widths. It ships as an app VIEW; no DevSidePanel component exists or is planned. If drag-to-dock behavior is ever needed, it lands here as a Panel extension, never a fork.

// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,
// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
export function Inspector() {
return (
<Panel
title="Session settings"
subtitle="nockerl-cli · primary"
leadingIcon={<SettingsIcon />}
actions={<NockerlIconButton label="More" icon={<MoreIcon />} />}
footer={<><NockerlButton variant="ghost">Reset</NockerlButton><NockerlButton>Save</NockerlButton></>}
>
<p>A persistent, in-layout region: larger than a card, not an overlay.</p>
</Panel>
);
}
// Collapsible: the header chevron toggles the body (aria-expanded).
<Panel title="Context window" collapsible defaultOpen>
<UsageMeter />
</Panel>
// Split pane: two panels + a draggable, keyboard-operable resize handle.
<PanelGroup direction="horizontal">
<Panel title="Explorer" minSize={25} defaultSize={46}><Tree /></Panel>
<PanelResizeHandle />
<Panel title="Detail"><Detail /></Panel>
</PanelGroup>
PropTypeDefaultDescription
title *stringHeader bar title. Bound to the title.small type role.
subtitlestringOptional second line under the title (muted).
leadingIconReactNodeOptional glyph rendered in the accent header tile.
actionsReactNodeHeader-bar actions, right-aligned (icon buttons / overflow).
toolbarReactNodeOptional control strip on a raised tier between the header and body.
footerReactNodeOptional footer content; actions are right-aligned by convention.
collapsiblebooleanfalseRenders the header as a toggle (aria-expanded); the body collapses flush.
defaultOpenbooleantrueInitial expanded state when collapsible.
childrenReactNodeBody content. Padded by the panel; never bleeds to the edge.

PanelGroup takes direction ('horizontal' | 'vertical'); each Panel in a group accepts minSize / maxSize / defaultSize (percent), and PanelResizeHandle is the draggable, keyboard-operable (role="separator", Arrow keys) splitter.

Cross-platform drift (tracked for reconciliation)

Panel vs. card vs. drawer: a panel is a persistent, in-layout region defined by a header bar + body (+ footer). It is larger than a card (a content tile) and, unlike a drawer, it stays in the layout rather than overlaying as an edge-anchored sheet. The real divergences:

  • No panel component yet (web + Android + Swift). Web ships the intended Panel / PanelGroup API above; Android composes a panel from NockerlCard + NockerlPanelShape (as ToolCallCard / AgentTranscriptPanel do); Swift’s closest is SettingsCard (title + body, no footer / toolbar / collapse). One Panel wrapper per platform is the planned step.
  • Panel radius: the token radius.panel is 12 (Compose NockerlPanelShape = 12dp matches). Swift’s SettingsCard uses cardRadius (14pt) though NockerlTheme.panelRadius (12) exists; it should read the panel token.
  • Split pane: web has a draggable, keyboard-operable PanelResizeHandle (role="separator" + Arrow keys). Swift builds a fixed-width pane in an HStack (no live resize) and deliberately avoids NavigationSplitView (its opaque sidebar fights the facet background). Compose has no split-pane idiom yet.
  • Collapse: web animates grid height; Compose uses AnimatedVisibility; Swift SettingsCard has no collapse. One collapse affordance needs to win.