Chip is the ONE primitive used for every "label-on-the-left + control-on-the-right" row in the editor sidebar. There is no ToolbarRowFrame, PopoverChip, BgWrap, Wrap, Labler, or MobileDesktopLabels — those existed historically and have a…
Chip is the ONE primitive used for every "label-on-the-left + control-on-the-right" row in the editor sidebar. There is no ToolbarRowFrame, PopoverChip, BgWrap, Wrap, Labler, or MobileDesktopLabels — those existed historically and have all been deleted. If you find a reference to one of them, replace with Chip.
Source: packages/sdk/src/chrome/primitives/Chip.tsx. Re-exported via @/chrome/primitives.
[ label ⓢ ] [ frame holding the control ] [ trailing X ]
↑ ↑ ↑ ↑
truncation border (or bare), optional clear /
tooltip + focus ring, h-8 secondary actions
click-forward (or min-h-8 with `grow`)
↑
`swatch` variant drops left
padding for full-bleed leading
The label gutter (w-20 by default) is baked into Chip. The breakpoint-pill indicator (BreakpointChip) renders next to the label automatically when propKey + propType indicate a class-typed prop. Authors do not render BreakpointChip themselves.
mode="input" (default)Use when the row's control is an inline element (text input, segmented control, swatch button, slider, etc.).
<Chip label="Format" frame="bare">
<ToolbarSegmentedControl … />
</Chip>
<Chip label="Background Color" propKey="background" propType="class">
<input type="text" className="input-plain" … />
</Chip>
Props:
label?: string — gutter label. Omit for label-less rows.onLabelClick?: () => void — click forward (focus / open the control).trailing?: ReactNode — affordance(s) inside the frame, after children (e.g. InlineClearButton).onClick? — click handler attached to the frame.variant?: "default" | "swatch" — swatch drops left padding so a full-bleed leading control hits the inner border (color picker swatch).frame?: "bordered" | "bare" — drop the input-wrapper border for controls that own their own chrome (segmented controls, custom buttons, multi-line layouts).grow?: boolean — replace h-8 with min-h-8 (textarea / multi-line content).passthrough?: boolean — escape hatch. Render children directly with no frame, label, or trailing. Used when a parent already provides the row shape.propKey?, propType?, index?, propItemKey? — when set + class-typed, the breakpoint pill renders next to the label.labelWidth?: string — override the default w-20 gutter (rare; only when alignment with neighbouring rows requires it).mode="popover"Use when the entire row is a click-to-open trigger for a FloatingPanel. Chip owns the leading icon + summary + session-aware clear ×.
<Chip
mode="popover"
ref={triggerRef}
label={typeLabel}
open={open}
onTriggerClick={() => (open ? setOpen(false) : openPanel())}
onClear={handleClear}
triggerAriaLabel="Edit action"
clearAriaLabel="Remove action"
leading={<Icon className="size-3.5" aria-hidden />}
summary={summary}
/>
Props (in addition to label / propKey / etc. from ChipCommon):
onTriggerClick: () => void — click on the chip body opens the popover.onClear: () => void — click on the trailing × clears the underlying value. Composes with SessionAddedAtom so empty popover-mode rows hide on the next render.triggerAriaLabel: string, clearAriaLabel: string — required.leading?: ReactNode — icon / swatch / color preview to the left of summary.summary?: ReactNode — short description of the current value (e.g. "Link → /shop").variant?: "default" | "preview" — preview makes leading take the full chip body (gradient swatch / image preview); previewOverlay renders a small pill on top.trailingExtras?: ReactNode — extras rendered inside the frame's trailing column, BEFORE the ×. Keep them small (size-5 icon-button shape). Used by show-hide chips for the eye-toggle peek.forwardRef lands on the trigger button so the panel can position next to it.
<Chip label="Title" propKey="title" propType="component">
<input
type="text"
className="input-plain flex-1"
value={value}
onChange={e => setValue(e.target.value)}
/>
</Chip>
Segmented controls own their own track. Use frame="bare".
<Chip label="Direction" frame="bare" propKey="flexDirection" propType="class">
<ToolbarSegmentedControl … />
</Chip>
variant="swatch" drops the left padding so the swatch fills the rounded-left corner.
<Chip
label="Background"
variant="swatch"
propKey={propKey}
propType="class"
trailing={value ? <InlineClearButton onClick={clear} /> : null}
>
<button className="relative h-full w-full" onClick={openPicker}>
{/* swatch fill */}
</button>
</Chip>
<Chip
mode="popover"
ref={triggerRef}
label="Action"
open={open}
onTriggerClick={openPanel}
onClear={removeAction}
triggerAriaLabel="Edit action"
clearAriaLabel="Remove action"
leading={<TbLink className="size-3.5" />}
summary={`${type} → ${target}`}
/>
{open && <Suspense fallback={null}><ActionEditorPanel … /></Suspense>}
<LabeledAddChip label="Action" cta="Add..." onClick={openPicker} />
(LabeledAddChip is a thin shell over Chip.)
Chip in a <div className="flex items-center gap-0.5"><span>{label}</span>…</div> outer. The chip owns the row.BreakpointChip next to a Chip. Pass propKey + propType and the chip places it for you.<Chip><Chip>…</Chip></Chip> for a single visual row. Pick the mode/variant/frame combo that produces the row you want.input-wrapper h-8 … markup. If the chip can't produce the shape you need, talk to the team — extending Chip beats a parallel primitive.ToolbarRowFrame / PopoverChip / BgWrap / Wrap / Labler / MobileDesktopLabels — they don't exist anymore.