{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "compact-control", "type": "registry:lib", "title": "compactControlClass", "description": "The geometry of a compact control: a small pill, chip or segment that sits on a line with body text.", "categories": [ "utilities" ], "registryDependencies": [ "https://whiskeyjack.net/r/utils.json" ], "files": [ { "path": "lib/compact-control.ts", "type": "registry:lib", "target": "lib/compact-control.ts", "content": "import { cn } from '@/lib/utils'\n\n/**\n * The geometry of a compact control: the size-and-shape half of a small pill,\n * chip or segment that sits on a line with body text.\n *\n * It exists because a settings row does not contain one kind of control. Icon\n * Stack's preview row holds a `SegmentedControl` (pick an appearance), a set of\n * size chips (pick a size) and two on/off pills (watch, monochrome) side by side,\n * and each had grown its own padding. Three controls doing the same job at three\n * different heights reads as a rendering fault rather than a design.\n *\n * ## What this owns, and what it does not\n *\n * Geometry only: height, padding, type scale, radius, focus ring, flex. The FILL\n * is the caller's, because the fills genuinely differ and should -- a chosen\n * segment takes the accent, while an active toggle takes a neutral, because \"this\n * one of several\" and \"this is switched on\" are different statements.\n *\n * Tailwind's border-box means a caller can add its own `border` without changing\n * the height, so a bordered pill and an unbordered chip still line up.\n *\n * Same reasoning as `optionTileClass` one level down: the shared thing is\n * extracted so the variants cannot drift, and the part that legitimately varies\n * stays with the caller.\n */\nexport interface CompactControlOptions {\n /**\n * The control sits INSIDE a bordered container that already owns the height\n * and the rounding -- a `SegmentedControl` segment. It fills that height and\n * drops its own radius, so the container's `overflow-hidden` shapes the ends\n * and the inner edges stay square.\n */\n inset?: boolean\n}\n\n/** The height every compact control lands on, container and standalone alike. */\nexport const COMPACT_CONTROL_HEIGHT = 'h-8'\n\nexport function compactControlClass({ inset }: CompactControlOptions = {}): string {\n return cn(\n 'wj-focus-ring inline-flex items-center gap-1.5 px-2.5',\n 'text-xs font-medium transition-colors',\n inset ? 'h-full rounded-none' : cn(COMPACT_CONTROL_HEIGHT, 'rounded-lg'),\n )\n}\n" } ], "docs": "Use when a settings row holds more than one kind of small control and they must line up. Icon Stack's preview row has a SegmentedControl, a set of size chips and two on/off pills side by side; each had grown its own padding, and three controls doing the same job at three different heights reads as a rendering fault rather than a design. It owns geometry only -- height, padding, type scale, radius, focus ring, flex -- and leaves the FILL to the caller, because a chosen segment taking the accent and an active toggle taking a neutral are different statements and should look different. Tailwind border-box means a caller can add its own border without changing the height, so a bordered pill and an unbordered chip still align. Pass inset for a control inside an already-bordered container, which fills that height and drops its own radius. Same reasoning as optionTileClass one level down.", "meta": { "group": "utilities", "related": [ "segmented-control", "option-tile", "toggle-group" ], "exports": [ "compactControlClass", "COMPACT_CONTROL_HEIGHT" ], "siteSlug": "compact-control" } }