Approval content
View (a config of the slots) · context (the host follows it, per the ratified wiring)
Approve shell command
This command modifies the working treerm -rf build/ dist/
Decide with the CTA row: outline confirm, ghost cancel, destructive = outline-red. The host follows the context (desktop → panel, compact → sheet, the ratified wiring); the anatomy never changes.
The one shared approval shape for the agent console: every
moment an agent stops and asks (a tool call, a plan, an AskUserQuestion) renders this
same anatomy, top-down:
- Title row (optional). Only for hosts without their own header (inline panels).
- Preview slot. What is being approved: a
ToolCallCard, Markdown plan content, a diff, a mono command in a sunkenWell. - Options slot. Choice rows: the real
RadioGroup,Checkbox,TextField. - Risk-note slot. Caveats in the ratified
Banner/Calloutalert grammar (recessed status disc + whisper intent border on a solid surface, never a wash, never a rail). - Actions.
NockerlApprovalActions, the ratified CTA grammar (Dialog r5 canon): outline confirm (tertiarycyan) · ghost cancel · destructive confirm = outline-red, never a filled primary on a lifted surface. Confirm can holdconfirmDisableduntil the options slot is satisfied.
Host-agnostic by design
Section titled “Host-agnostic by design”NockerlApprovalContent is pure content: no overlay, no scrim, no chrome. The title
and the actions migrate to whatever chrome the host owns:
| Host | Title | Actions |
|---|---|---|
BottomSheet |
the sheet header (title / subtitle) |
pinned in the sheet’s footer slot (never scroll away) |
Dialog |
the dialog header | the dialog’s own CTA row (same grammar) |
| Inline panel | the content’s own title prop |
the actions slot, inline at the end |
The host wiring is settled: web desktop/pointer
presents approvals in inline panels (the Panel/Dialog grammar, never a desktop
bottom sheet); compact/touch web widths are sheet-idiomatic and host the same
anatomy in the shipped BottomSheet; Android rides
NockerlBottomSheet (the ApprovalSheet shell). The HOST is interaction idiom (law §9);
the ANATOMY is the drift-guard (§12) and never changes across hosts. The demo above
derives the host from the context switch exactly per this rule.
The approval views are configs, not components
Section titled “The approval views are configs, not components”Per the component-vs-view rule, the three console approval moments are pure slot configurations of this one anatomy. They introduce no new components:
| View | preview |
options |
riskNote |
Confirm |
|---|---|---|---|---|
| Tool approval | ToolCallCard (or a mono command Well) |
n/a | Banner on destructive/write commands |
Approve · destructive commands flip tone="destructive" |
| Plan approval | Markdown plan body | n/a | n/a | Approve plan / cancel Keep planning |
| AskUserQuestion | optional context | RadioGroup (+ Checkbox multi-select, TextField “other”) |
n/a | Submit, confirmDisabled until answered |
The Compose mirror (NockerlApprovalContent hosted in the canonical
NockerlBottomSheet, matching ToolApprovalSheet) is the Compose lane.
Same anatomy, same slot names.
Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
title | string | Optional title row for hosts WITHOUT their own header (panels). Sheet/Dialog hosts carry the title themselves and omit this. | |
subtitle | string | Optional supporting line under the title. | |
preview | ReactNode | The PREVIEW slot: what is being approved (ToolCallCard · Markdown · diff…). | |
options | ReactNode | The OPTIONS slot: choice rows (RadioGroup / Checkbox / TextField). | |
riskNote | ReactNode | The RISK-NOTE slot: a Banner / Callout carrying caveats. | |
actions | ReactNode | Optional INLINE actions (panel hosts). Sheet hosts pin NockerlApprovalActions in the sheet footer instead and omit this. | |
className | string | Extra class. |
| Prop | Type | Default | Description |
|---|---|---|---|
confirmLabel | string | 'Approve' | Confirm label (e.g. "Approve", "Run tool", "Submit"). |
cancelLabel | string | null | 'Deny' | Cancel label. null hides cancel (rare: a single-action acknowledge). |
tone | 'primary' | 'destructive' | 'primary' | Emphasis of the confirm: outline cyan (default) or destructive outline-red. |
onConfirm * | () => void | ||
onCancel | (() => void) | undefined | ||
confirmDisabled | boolean | false | Disable confirm (e.g. an unsatisfied option row). |