Inspector Group

The container the rows go in: a named, collapsible section that says what it is currently set to while it is closed, with an optional reset in its header. A drawer of twenty settings becomes a drawer of five groups.

Rows of the family go here
One under another

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-group

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import { InspectorGroup } from "@/components/beste/component/inspector-group";

// A section of rows
<InspectorGroup label="Layout">
  <InspectorSlider label="Gap" value={gap} onValueChange={setGap} />
  <InspectorSpacing label="Padding" value={padding} onValueChange={setPadding} />
</InspectorGroup>

// A closed group that says nothing about itself is a door with no sign on it
<InspectorGroup label="Padding" defaultOpen={false} summary={`${padding.top} ${padding.right} px`}>
  <InspectorSpacing label="Padding" value={padding} onValueChange={setPadding} />
</InspectorGroup>

// Reset belongs to the group, not to whichever row happens to be last
<InspectorGroup
  label="Typography"
  onReset={() => setType(defaults)}
  resetDisabled={isDefault}
>
  <InspectorSelect label="Family" options={families} value={family} onValueChange={setFamily} />
  <InspectorStepper label="Size" suffix="px" value={fontSize} onValueChange={setFontSize} />
</InspectorGroup>

<InspectorGroup
  label="Advanced"
  icon={SettingsIcon}     // optional leading icon
  tone="outline"          // "muted" (default) | "outline" | "ghost"
  size="sm"               // "sm" | "default" | "lg"
  open={open}             // controlled; pair with onOpenChange
  onOpenChange={setOpen}
  alwaysShowSummary       // keep the summary visible while open too
  summary="3 changed"
>
  <InspectorCode label="Custom CSS" language="css" value={css} onValueChange={setCss} />
</InspectorGroup>

// A section that is always open: the header becomes a heading rather than offering
// a gesture it will not answer
<InspectorGroup label="Identity" collapsible={false}>
  <InspectorInput label="Name" value={name} onValueChange={setName} />
</InspectorGroup>

// Rows inside a closed group are unmounted, not hidden: each one owns state and
// effects, and a drawer of twenty closed groups would otherwise pay for all of them.

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Rows of the family go here
Usage
import { InspectorGroup } from "@/components/beste/component/inspector-group";

<InspectorGroup
  label="Layout"
  summary="16 24 px"
  children="Rows of the family go here"
/>

Keyboard and gestures

Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.

Enter / Space on the headerOpen or close the group. The header is a button whenever `collapsible` is on.

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringName of the group, in its header.
iconLucideIconOptional leading icon shown before the label.
childrenReact.ReactNodeThe rows.
summaryReact.ReactNodeWhat the group is currently set to, shown in the header while it is closed. A closed group that says nothing about itself is a door with no sign on it.
alwaysShowSummarybooleanKeep the summary visible while the group is open too.
openbooleanControlled open state. Pair it with `onOpenChange`.
defaultOpenbooleantrueWhether it starts open in uncontrolled mode.
onOpenChange(open: boolean) => void
collapsiblebooleanTake away the disclosure: the header becomes a heading and the rows stay out.
onReset() => voidCalled by the reset button, which only appears when this is given. It sits in the header rather than under the rows, since it belongs to the group and not to whichever row happens to be last.
resetDisabledbooleanGrey out the reset button, for a group already at its defaults.
disabledbooleanDim the whole group. What is inside stays the caller's business.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare.
size"sm" | "default" | "lg""default"Padding and header height preset.
classNamestring

More Inspector components

View all Inspector

Inspector Code

Settings block for a snippet: a monospaced field with a language chip and a line count, Tab indenting instead of leaving, and a fixed height so a pasted stylesheet cannot push the rest of the drawer out of reach. Collapsible, since a snippet is the tallest thing in a drawer and the least often touched; folded, it measures exactly what a row measures and still reports its line count.

Dark Mode

Inspector Segmented

Settings row whose choices sit side by side on the right, with a marker that slides between them: the readable alternative to a switch when the two states deserve names, and the compact one to a select at three or four options.

Borders

Inspector Toggles

Settings row holding a set of pills that are each on or off, so any number of them can be on at once: what inspector-segmented is for one choice out of several, this is for several choices at once, and what inspector-switch is for a single flag, this is for a handful that belong together.

Inspector Corners

Settings row for the four corners of a box: the row carries a border-radius shorthand summary and a glyph rounded to match, and opens a square where each field sits on the corner it rounds.

Inspector Border

Settings row for a border: the row draws one exactly as described beside a summary of it, and opens an editor with the sides as icon toggles and the width, style and colour under them, each one a row of the family.

Inspector Switch

Settings row with a label on the left and a switch on the right, sharing the family's pill: the label takes the row's spare width, so a press almost anywhere toggles it.