{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "option-tile", "type": "registry:lib", "title": "optionTileClass", "description": "The selectable-tile class recipe shared by ToggleGroup and CheckboxGroup.", "categories": [ "utilities" ], "registryDependencies": [ "https://whiskeyjack.net/r/utils.json" ], "files": [ { "path": "lib/option-tile.ts", "type": "registry:lib", "target": "lib/option-tile.ts", "content": "import { cn } from '@/lib/utils'\n\n/**\n * The selectable-tile recipe: a bordered square that fills with the accent when\n * chosen.\n *\n * It lives here because it had been hand-copied sixteen times across five app\n * files plus `ToggleGroup`, and every copy was the same eight utility classes\n * with the same two-branch conditional. `ToggleGroup` (pick one) and\n * `CheckboxGroup` (pick any) now both draw from this, so the two stay visually\n * identical by construction rather than by vigilance.\n *\n * Exported so an app can build a tile the two group components do not cover --\n * Chip Away's icon picker renders a glyph rather than a label, and its weekday\n * strip is seven single characters. Reach for a group component first; this is\n * for the case where the layout genuinely differs but the tile should not.\n */\nexport interface OptionTileOptions {\n /** Renders the accent fill and raises the tile. */\n selected: boolean\n /** Dims and blocks pointer events, without removing it from the tab order. */\n disabled?: boolean\n /** Stacks an icon above the label instead of centering a lone label. */\n stacked?: boolean\n}\n\nexport function optionTileClass({ selected, disabled, stacked }: OptionTileOptions): string {\n return cn(\n 'wj-focus-ring relative rounded-xl border-2 px-3 py-3 text-sm font-medium transition-all',\n stacked ? 'flex flex-col items-center gap-1.5' : 'flex items-center justify-center',\n selected\n ? 'bg-[var(--color-accent-500)] border-[var(--color-accent-500)] text-[var(--color-accent-foreground)] shadow-md'\n : [\n 'bg-[var(--color-surface-light)] border-[var(--color-border-light)]',\n 'text-[var(--color-text-secondary-light)]',\n 'hover:border-[var(--color-accent-400)]',\n 'dark:bg-[var(--color-surface-dark)] dark:border-[var(--color-border-dark)]',\n 'dark:text-[var(--color-text-secondary-dark)]',\n 'dark:hover:border-[var(--color-neutral-500)]',\n ],\n // Kept tabbable on purpose: a disabled option a keyboard user cannot reach is\n // an option they cannot discover the existence of.\n disabled && 'opacity-50 pointer-events-none',\n )\n}\n" } ], "docs": "Reach for a group component first -- ToggleGroup for pick-one, CheckboxGroup for pick-any. This is the tile they share, exported for the case where the LAYOUT genuinely differs but the tile should not: an icon-only picker, or a seven-across weekday strip. It had been hand-copied sixteen times across five app files before it lived here, which is the argument for using it rather than re-deriving the eight classes.", "meta": { "group": "utilities", "related": [ "toggle-group", "checkbox-group" ], "exports": [ "optionTileClass" ], "siteSlug": "option-tile" } }