# Bones > Bones is a minimal, themable React component library built on Base UI. > All design values are CSS custom properties prefixed --ub-. Components are > styled through class names (ub-) and data attributes, never > inline styles, so they can be restyled without forking. ## Install - pnpm add @usebones/react @usebones/tokens (components + tokens); React 19 or newer is a peer dependency - pnpm add @usebones/icons (optional icon adapter, Lucide default; experimental, the vocabulary API may change). Icon names are a typed vocabulary: the built-in set plus whatever the app declares with defineIcons (keys become names via IconNamesOf, glyphs go to IconProvider). Never guess a name; add it. Any icon component also works directly as a child of a Bones component. - Import once: "@usebones/tokens/index.css" then "@usebones/react/styles.css" - Use explicit .css paths in imports; TypeScript 7 rejects extensionless side-effect CSS imports. ## Theming - Dark mode: data-theme="dark" (canonical; .dark also works) on or any subtree. - Pill radius: data-radius="pill" on or any subtree. - Components read semantic tokens only: --ub-bg, --ub-surface, --ub-text-primary, --ub-text-secondary, --ub-border, --ub-accent, --ub-ring, --ub-danger, --ub-success, --ub-warning, --ub-info. Override these to retheme; never fork CSS. - Raw scales (50 to 950): gray, red, orange, green, teal, blue, violet, fuchsia, rose. The eight colors share one lightness ladder; gray runs a slightly darker one for backgrounds. Themes reference these; components never do. - Motion: --ub-duration-fast/base/slow and --ub-ease-out/in-out/spring. Durations collapse to zero under prefers-reduced-motion. - Prebuilt accent themes: import "@usebones/tokens/themes/.css" (blue, violet, teal, fuchsia, rose, red, orange, green). They apply on import and recolor primary actions only. - Full themes replace every color role (and may reshape radii) and ship inert: import "@usebones/tokens/themes/matrix.css" then activate with data-theme="matrix" on or any subtree. A custom theme is a plain CSS file overriding semantic tokens after index.css; full themes scope under their own data-theme value. - No theme provider and no config file: attributes and tokens are the configuration API. JS context exists only where CSS cannot express the need (the icon set). ## Components - Accordion: AccordionRoot (value/defaultValue as string arrays, multiple, disabled) + AccordionItem (value, disabled) + AccordionTrigger (label as children, heading and chevron automatic) + AccordionPanel (hiddenUntilFound keeps closed content findable by in-page search, keepMounted keeps a closed panel in the DOM; both default false). One open at a time by default. States via [data-panel-open] on triggers, [data-open] on items; height animates via --accordion-panel-height. - AlertDialog: a confirmation that interrupts on purpose. Same six-part shape as Dialog (Root/Trigger/Content/Title/Description/Close) but always modal and outside clicks never dismiss; Escape cancels. One AlertDialogClose per choice (Cancel ghost, action primary or danger with onClick). Use only for hard-to-undo actions. - Autocomplete: free text with suggestions; the value is the input string itself (value/defaultValue/onValueChange fire per keystroke). AutocompleteRoot (items, mode "list" default | "both" | "inline" | "none", size default | compact (36px/28px control height, 16px/14px text)) + AutocompleteInput (placeholder, variant default | borderless (a muted fill with no border), clearable default true, invalid: danger border, ring, and hint, plus aria-invalid; a surrounding Field sets it automatically; no chevron) + AutocompleteContent (empty, status for async searches, side/align/sideOffset 4; function children render an AutocompleteItem per suggestion). Shares the Combobox classes. Use Combobox when the value must come from the list. - Avatar: one component; src + alt (the person's name; required with src, "" only when the name is visible beside it) + fallback (initials or icon, shows until the image loads and on error); size default | compact (36px/28px); always round. - AvatarGroup: overlapping Avatars (a Bones composition, no Base UI part); children are regular Avatars ordered most-important first; max={n} collapses the rest into a +N chip; size default | compact sizes the chip (match the Avatars). Ring color via --ub-avatar-group-ring on surfaces. - Badge: a small label (a Bones component, no Base UI part); a plain span, never focusable. color "neutral" (default) | red | orange | green | teal | blue | violet | fuchsia | rose (categories, not feedback); size default (24px) | compact (20px, small radius); status adds a decorative dot in a feedback color before the label; icons are children before the text. Fills come from the --ub-tint--bg/-text tokens. - Button: variant primary (default) | secondary | ghost | danger; size default | compact (36px/28px control height, 16px/14px text); iconOnly (requires aria-label). Icons are children. Native button props pass through; type defaults to "button". Anchors can reuse the styling: class="ub-button" data-variant="...". - Checkbox: checked/defaultChecked/onCheckedChange/indeterminate/disabled/ required; value joins a CheckboxGroup. Style states via [data-checked], [data-indeterminate], [data-disabled]. - CheckboxGroup: wraps Checkboxes (each joins via value); defaultValue or value + onValueChange (string arrays); allValues + for select-all with indeterminate; disabled disables members. - Collapsible: CollapsibleRoot (defaultOpen or open + onOpenChange, disabled) + CollapsibleTrigger (label as children, chevron automatic) + CollapsiblePanel (hiddenUntilFound, keepMounted). Height animates via --collapsible-panel-height; state via [data-panel-open] on the trigger. - Combobox: ComboboxRoot (items required for filtering/empty; itemToStringLabel for object items; value or defaultValue + onValueChange; multiple for arrays; size default | compact (36px/28px control height, 16px/14px text)) + ComboboxInput (placeholder, variant default | borderless (a muted fill with no border), clearable default true: the clear button takes the chevron's place while something is selected; invalid: danger border, ring, and hint, plus aria-invalid; a surrounding Field sets it automatically; disabled) + ComboboxContent (empty="..."; searchInput puts the text input inside the popup, a string sets its placeholder; status is a politely announced line for async searches; side/align/sideOffset 4; function children render a ComboboxItem per filtered item) + ComboboxGroup/GroupLabel/Collection. Chips for multiple: ComboboxChips > ComboboxValue fn children mapping to ComboboxChip + inline ComboboxInput. ComboboxTrigger is the select-like button (placeholder is visual only, so aria-label is required; invalid works there too). Prefer Select for short fixed lists. - ContextMenu: ContextMenuRoot (size default | compact (36px/28px control height, 16px/14px text); open/defaultOpen + onOpenChange) + ContextMenuTrigger (a div around the right-clickable surface) + ContextMenuContent; opens at the pointer, long press on touch. Fill the content with the regular Menu parts (MenuItem, MenuCheckboxItem, ...); the popup shares Menu's classes. - Dialog: DialogRoot (open/defaultOpen + onOpenChange; modal default true, false keeps the page interactive, "trap-focus" traps without dimming; disablePointerDismissal default false) + DialogTrigger (attach via render={