# Props

<!-- GENERATED by `scripts/gen-consumer-skills.mjs` — do not edit. Regenerate: `npm run consumer:gen` -->

Only props the kit declares itself. A component that also forwards its
underlying element's props — and they all do — accepts every attribute that
element accepts; those are not repeated here.

`className` is universal and never listed: every component merges it **last**,
so an app utility wins without `!important`. The two exceptions where it lands
on a wrapper instead are called out in the usage skill.

Components with no rows below declare no props of their own — they are the underlying primitive's API in full: `card`, `form`, `label`, `popover`, `separator`, `skeleton`.

## `<pkg>/accordion`

### Accordion

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'secondary'` | — | — |
| `variant` | `'card' \| 'list' \| null` | `'card'` | — | — |

## `<pkg>/alert`

### Alert

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'sm' \| 'md' \| 'lg' \| null` | `'md'` | — | — |
| `variant` | `'solid' \| 'subtle' \| 'surface' \| 'outline' \| 'default' \| 'destructive' \| 'success' \| 'warning' \| null` | `'solid'` | — | — |

## `<pkg>/avatar`

### Avatar

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'black'` | — | — |
| `shape` | `'circle' \| 'square' \| null` | `'circle'` | — | CBAR names these `shape` and `square`; the round one is the default. |
| `size` | `'sm' \| 'md' \| 'lg' \| '2xs' \| 'xs' \| 'xl' \| null` | `'md'` | — | — |
| `variant` | `'solid' \| 'subtle' \| 'outline' \| null` | `'subtle'` | — | — |

## `<pkg>/badge`

### Badge

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | — | Render the child element instead of a `<span>` — e.g. to make it a link. |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | `'md'` | — | — |
| `variant` | `'secondary' \| 'solid' \| 'subtle' \| 'surface' \| 'outline' \| 'default' \| 'destructive' \| 'success' \| 'warning' \| 'ghost' \| null` | `'solid'` | — | — |

## `<pkg>/breadcrumb`

### BreadcrumbList

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'secondary'` | — | Only the separator takes palette colour; CBAR draws it turquoise. |
| `size` | `'md' \| 'xs' \| null` | `'md'` | — | — |

### BreadcrumbLink

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | — | — | Render the child element instead of an `<a>` — e.g. a router `<Link>`. |

## `<pkg>/button`

### Button

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | — | Render the child element instead of a `<button>`, forwarding all styling and behaviour to it. Use it to make a router `<Link>` look like a button without nesting an anchor inside a button. |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | Which CBAR ramp the treatment draws from. Ignored by the three shorthand variants, which pin their own colour. |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| 'xl' \| 'icon-xs' \| 'icon-sm' \| 'icon' \| 'icon-lg' \| null` | `'md'` | — | Height, padding, type size and glyph size. The icon steps 16 → 24px at `md`, matching CBAR's own set; the four `icon-*` rungs are square. |
| `variant` | `'secondary' \| 'link' \| 'solid' \| 'subtle' \| 'surface' \| 'outline' \| 'default' \| 'destructive' \| 'ghost' \| null` | `'solid'` | — | How filled in the button is. Independent of colorPalettes — `variant` decides the treatment, `colorPalette` decides the hue. |

## `<pkg>/checkbox`

### Checkbox

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | `'sm'` | — | — |

## `<pkg>/combobox`

### Combobox

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `options` | `ComboboxOption[]` | — | yes | — |
| `aria-label` | `string` | — | — | — |
| `aria-labelledby` | `string` | — | — | — |
| `className` | `string` | — | — | Width of the trigger. The popover matches it. |
| `contentClassName` | `string` | — | — | Extra classes for the popover surface. |
| `defaultValue` | `string` | `''` | — | — |
| `disabled` | `boolean` | `false` | — | — |
| `emptyMessage` | `string` | `'No results found.'` | — | — |
| `id` | `string` | — | — | Put it on the trigger, so a `<Label htmlFor>` can point at it. |
| `onValueChange` | `(value: string) => void` | — | — | — |
| `placeholder` | `string` | `'Select an option…'` | — | Shown on the trigger when nothing is selected. |
| `searchPlaceholder` | `string` | `'Search…'` | — | — |
| `value` | `string` | — | — | Controlled selection. Pass with `onValueChange`. |

## `<pkg>/command`

### Command

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `defaultValue` | `string` | `''` | — | — |
| `filter` | `CommandFilter` | `defaultFilter` | — | Replace the matching logic. Return 0 to hide an item. |
| `label` | `string` | `'Suggestions'` | — | Accessible name for the results list. |
| `loop` | `boolean` | `false` | — | Wrap around when arrowing past either end. |
| `onValueChange` | `(value: string) => void` | — | — | — |
| `shouldFilter` | `boolean` | `true` | — | Turn off to filter the list yourself, e.g. against a server. |
| `value` | `string` | — | — | The highlighted item. Controlled — pair it with `onValueChange`. |

### CommandDialog

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `className` | `string` | — | — | — |
| `description` | `string` | `'Search for a command to run…'` | — | — |
| `showCloseButton` | `boolean` | `true` | — | — |
| `title` | `string` | `'Command Palette'` | — | Announced to screen readers; visually hidden by default. |

### CommandInput

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `onValueChange` | `(search: string) => void` | — | — | — |
| `value` | `string` | — | — | — |

### CommandGroup

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `heading` | `React.ReactNode` | — | — | — |

### CommandItem

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `value` | `string` | — | yes | The text this item is matched on, and its identity in the list. |
| `disabled` | `boolean` | — | — | — |
| `keywords` | `string[]` | — | — | Extra terms that should also match — synonyms, shortcuts, ids. |
| `onSelect` | `(value: string) => void` | — | — | — |

## `<pkg>/data-table`

### DataTable

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `columns` | `DataTableColumn<RecordType>[]` | — | yes | — |
| `data` | `readonly RecordType[]` | — | yes | — |
| `aria-label` | `string` | — | — | — |
| `className` | `string` | — | — | — |
| `emptyText` | `React.ReactNode` | `'No results.'` | — | — |
| `expandable` | `DataTableExpandable<RecordType>` | — | — | — |
| `id` | `string` | — | — | — |
| `onRow` | `(record: RecordType, index?: number) => React.HTMLAttributes<HTMLElement>` | — | — | — |
| `onSortChange` | `(sort: DataTableSort \| null) => void` | — | — | — |
| `rowClassName` | `string \| ((record: RecordType, index: number) => string)` | — | — | — |
| `rowKey` | `string \| ((record: RecordType, index?: number) => React.Key)` | `'key'` | — | Field name or function producing a stable key per row. |
| `scroll` | `{ x?: number \| string \| true; y?: number \| string }` | — | — | `{ y }` makes the header sticky; `{ x }` enables horizontal scrolling. |
| `sort` | `DataTableSort \| null` | — | — | Controlled sort. Pass it together with `onSortChange` when something else sorts the data (a server, a query hook). Leave both off and the table sorts its own rows. |
| `sticky` | `boolean` | — | — | Keep the header visible while the table's container scrolls. |

## `<pkg>/date-picker`

### DatePicker

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `allowClear` | `boolean` | `true` | — | Show the clear button once something is selected. |
| `aria-invalid` | `boolean` | — | — | — |
| `aria-label` | `string` | — | — | — |
| `aria-labelledby` | `string` | — | — | — |
| `className` | `string` | — | — | — |
| `defaultValue` | `Date \| null` | `null` | — | — |
| `disabled` | `boolean` | — | — | — |
| `disabledDate` | `(date: Date) => boolean` | — | — | Reject a date. It stays visible but cannot be chosen. |
| `format` | `string` | — | — | Token pattern for the text field. Defaults to one matching `picker`. |
| `id` | `string` | — | — | — |
| `locale` | `string` | `'en-US'` | — | BCP 47 tag driving month names, weekday names and the week start. |
| `onChange` | `(date: Date \| null) => void` | — | — | — |
| `picker` | `DateGranularity` | `'date'` | — | Granularity of the panel and of the value it produces. |
| `placeholder` | `string` | — | — | — |
| `value` | `Date \| null` | — | — | — |

### DateRangePicker

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `allowClear` | `boolean` | `true` | — | Show the clear button once something is selected. |
| `aria-invalid` | `boolean` | — | — | — |
| `aria-label` | `string` | — | — | — |
| `aria-labelledby` | `string` | — | — | — |
| `className` | `string` | — | — | — |
| `defaultValue` | `DateRange \| null` | `null` | — | — |
| `disabled` | `boolean` | — | — | — |
| `disabledDate` | `(date: Date) => boolean` | — | — | Reject a date. It stays visible but cannot be chosen. |
| `format` | `string` | — | — | Token pattern for the text field. Defaults to one matching `picker`. |
| `id` | `string` | — | — | — |
| `labels` | `[string, string]` | `['Start date', 'End date']` | — | Names for the two fields, announced to assistive tech. |
| `locale` | `string` | `'en-US'` | — | BCP 47 tag driving month names, weekday names and the week start. |
| `onChange` | `(range: DateRange) => void` | — | — | — |
| `picker` | `DateGranularity` | `'date'` | — | Granularity of the panel and of the value it produces. |
| `placeholder` | `string` | — | — | — |
| `value` | `DateRange \| null` | — | — | — |

### Calendar

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `month` | `Date` | — | yes | Month the panel is showing. Controlled, so two panels can be linked. |
| `onMonthChange` | `(month: Date) => void` | — | yes | — |
| `onSelect` | `(date: Date) => void` | — | yes | — |
| `className` | `string` | — | — | — |
| `disabledDate` | `(date: Date) => boolean` | — | — | — |
| `hovered` | `Date \| null` | `null` | — | Previewed while the pointer moves over the grid mid-range. |
| `label` | `string` | — | — | Accessible name of the grid, e.g. "Start date". |
| `locale` | `string` | `'en-US'` | — | — |
| `onHoveredChange` | `(date: Date \| null) => void` | — | — | — |
| `picker` | `DateGranularity` | `'date'` | — | Granularity of the panel: days, months or years. |
| `range` | `[Date \| null, Date \| null]` | — | — | Both ends of the range, for highlighting the span. |
| `value` | `Date \| null` | `null` | — | The selected date, or the range endpoints when `range` is set. |

## `<pkg>/dialog`

### DialogContent

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `showCloseButton` | `boolean` | `true` | — | Show the X in the top-right corner. Keep it unless the dialog is blocking. |

## `<pkg>/drawer`

### Drawer

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `direction` | `DrawerDirection` | `'bottom'` | — | Edge the panel comes in from. |
| `dismissible` | `boolean` | `true` | — | Allow dragging and the overlay click to close it. |

### DrawerContent

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `showHandle` | `boolean` | — | — | Show the grab bar. Defaults on for the top and bottom edges. |

## `<pkg>/dropdown-menu`

### DropdownMenuLabel

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `inset` | `boolean` | — | — | — |

### DropdownMenuItem

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `inset` | `boolean` | — | — | Indent the label to line up with rows that have a check or radio marker. |
| `variant` | `'default' \| 'destructive'` | `'default'` | — | — |

### DropdownMenuSubTrigger

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `inset` | `boolean` | — | — | — |

## `<pkg>/field`

### Field

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `invalid` | `boolean` | — | — | Marks the whole group invalid, tinting the label and error text. |
| `orientation` | `'horizontal' \| 'vertical' \| null` | `'vertical'` | — | — |

### FieldLabel

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `required` | `boolean` | — | — | Draws CBAR's required marker after the text — its `.isRequired?` slot. The marker is `aria-hidden`: an asterisk read aloud is noise, and the fact that the field is required belongs on the control. Set `required` (or `aria-required`) there as well — this prop only draws. |

### FieldLegend

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `variant` | `'legend' \| 'label'` | `'legend'` | — | `label` renders at control-label size instead of section-heading size. |

## `<pkg>/input`

### Input

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `classNames` | `{ input?: string }` | — | — | Classes for the inner `<input>` when an adornment is present. With a slot filled, `className` lands on the wrapper — that is the visible box, and `className="w-64"` should size it. Same split as InputNumber. |
| `endElement` | `React.ReactNode` | — | — | Content pinned to the trailing edge — CBAR's `.rightElement?`. Stays interactive, so a clear button or a reveal-password toggle works here. |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | — | — | — |
| `startElement` | `React.ReactNode` | — | — | Content pinned to the leading edge — CBAR's `.leftElement?`. Inert by design: a click passes through to the field, which is what you want for the icon or currency symbol this slot is for. Put anything interactive in InputProps.endElement instead. |
| `variant` | `'outline' \| 'flushed' \| null` | — | — | — |

## `<pkg>/input-number`

### InputNumber

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `classNames` | `{ input?: string; controls?: string }` | — | — | — |
| `controls` | `boolean` | `true` | — | Show the stepper column. |
| `defaultValue` | `number \| null` | — | — | — |
| `formatter` | `(value: number \| null) => string` | — | — | Renders the value for display — currency symbols, units, thousands separators. |
| `keyboard` | `boolean` | `true` | — | Let ArrowUp/ArrowDown step the value. |
| `max` | `number` | `Infinity` | — | — |
| `min` | `number` | `-Infinity` | — | — |
| `onChange` | `(value: number \| null) => void` | — | — | Fires with the parsed value, or `null` once the field is cleared. |
| `parser` | `(displayValue: string) => number` | — | — | Turns a typed string back into a number. Required whenever `formatter` is set. |
| `precision` | `number` | — | — | Decimal places to round to on commit. Defaults to whatever `step` implies. |
| `step` | `number` | `1` | — | — |
| `value` | `number \| null` | — | — | — |

## `<pkg>/pagination`

### Pagination

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | — | — | — |

### PaginationLink

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `isActive` | `boolean` | — | — | — |

### PaginationPrevious

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `isActive` | `boolean` | — | — | — |

### PaginationNext

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `isActive` | `boolean` | — | — | — |

## `<pkg>/progress`

### Progress

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'md' \| 'lg' \| null` | `'md'` | — | CBAR draws the bar at two heights, 6px and 9px. |

### ProgressCircle

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `formatValue` | `(value: number) => React.ReactNode` | — | — | Overrides the printed label. Receives the clamped 0–100 value. |
| `showValue` | `boolean` | — | — | Print the percentage in the middle. Defaults to on from `md` up and off below it: `xs` and `sm` leave 16px and 22px of clear space inside the ring, and "100%" at CBAR's 12px needs about 30px, so the label spills over its own stroke. Pass `true` to force it — with a `formatValue` that returns something short enough to fit. |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| 'xl' \| null` | `'md'` | — | — |

## `<pkg>/radio-group`

### RadioGroupItem

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | `'sm'` | — | — |

## `<pkg>/range-slider`

### RangeSlider

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `classNames` | `RangeSliderClassNames` | — | — | — |
| `marks` | `RangeSliderMark[]` | — | — | Ticks drawn under the track. Purely decorative — they are not selectable. |
| `thumbLabels` | `string[]` | — | — | Accessible name for each thumb, in order. A thumb carries `role="slider"`, and that role takes **no** name from surrounding content — without one, a screen reader announces a bare number. Pass one name per thumb (`['Minimum', 'Maximum']`). For a single thumb an `aria-label` on the slider itself is enough; with several, each thumb falls back to that label suffixed with its position. |

## `<pkg>/select`

### SelectTrigger

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `classNames` | `{ trigger?: string }` | — | — | Classes for the trigger itself when `clearable` is on. With it on, the trigger gains a wrapper and `className` lands there — that is the element a parent lays out, so `className="w-56"` should size it. Same split as Input's adornment wrapper. |
| `clearable` | `boolean` | `false` | — | Show a reset control once something is chosen — CBAR's `.isClearable?`. Clearing sets the value to `''`, which is how Radix returns a Select to its placeholder. That is also why an item may not use `''` as its own value. |
| `clearLabel` | `string` | `'Clear selection'` | — | Accessible name for that control. |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | `'md'` | — | — |
| `variant` | `'outline' \| 'flushed' \| null` | — | — | — |

## `<pkg>/sheet`

### SheetContent

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `showCloseButton` | `boolean` | `true` | — | — |
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` | — | Edge the panel slides in from. |

## `<pkg>/spinner`

### Spinner

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `label` | `string` | `'Loading'` | — | Announced to screen readers. Override it to describe what is loading. |

## `<pkg>/switch`

### Switch

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'primary'` | — | — |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | `'md'` | — | — |

## `<pkg>/tabs`

### TabsList

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `colorPalette` | `'secondary' \| 'primary' \| 'tertiary' \| 'black' \| 'red' \| 'green' \| 'yellow' \| 'third' \| null` | `'secondary'` | — | — |
| `size` | `'md' \| 'lg' \| null` | `'md'` | — | — |
| `variant` | `'line' \| 'subtle' \| 'outline' \| 'default' \| 'plain' \| null` | `'line'` | — | — |

## `<pkg>/textarea`

### Textarea

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xs' \| null` | — | — | — |
| `variant` | `'outline' \| 'flushed' \| null` | — | — | — |

## `<pkg>/toast`

### Toaster

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `className` | `string` | — | — | — |
| `closeButton` | `boolean` | `false` | — | Show a dismiss button on every toast. |
| `duration` | `number` | `4000` | — | Default milliseconds on screen. A toast can override it. |
| `icons` | `Partial<Record<ToastKind, React.ReactNode>>` | — | — | — |
| `label` | `string` | `'Notifications'` | — | Accessible name for the notification region. |
| `position` | `ToastPosition` | `'bottom-right'` | — | — |
| `theme` | `'inherit' \| 'light' \| 'dark'` | `'inherit'` | — | Toasts render in a portal on `document.body`, which sits inside `<html>` — so a `dark` class on the root element reaches them, and the default, `'inherit'`, is right for most apps. Force it only when the app scopes dark mode to a wrapper the portal escapes. |
| `toastClassName` | `string` | — | — | — |
| `visibleToasts` | `number` | `3` | — | How many to show at once; older ones wait their turn. |

## `<pkg>/tooltip`

### TooltipContent

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `showArrow` | `boolean` | `true` | — | Draw the arrow pointing back at the trigger. CBAR makes this a switch on its Tooltip, and it is worth having: an arrow is noise when the tooltip is already visually attached to a small target. |

## `<pkg>/tree`

### Tree

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `treeData` | `TreeNode[]` | — | yes | — |
| `aria-label` | `string` | — | — | Defines a string value that labels the current element. |
| `checkable` | `boolean` | — | — | Show checkboxes, with checked state propagating up and down. |
| `checkedKeys` | `readonly React.Key[]` | — | — | — |
| `defaultCheckedKeys` | `readonly React.Key[]` | — | — | — |
| `defaultExpandAll` | `boolean` | — | — | — |
| `defaultExpandedKeys` | `readonly React.Key[]` | — | — | — |
| `defaultSelectedKeys` | `readonly React.Key[]` | — | — | — |
| `expandedKeys` | `readonly React.Key[]` | — | — | — |
| `height` | `number` | — | — | — |
| `itemHeight` | `number` | `28` | — | Row height, only used when `virtual` is set. |
| `onCheck` | `(keys: React.Key[], info: TreeCheckInfo) => void` | — | — | — |
| `onExpand` | `(keys: React.Key[], info: { node: TreeNode; expanded: boolean }) => void` | — | — | — |
| `onSelect` | `(keys: React.Key[], info: { node: TreeNode; selected: boolean }) => void` | — | — | — |
| `selectedKeys` | `readonly React.Key[]` | — | — | — |
| `switcherIcon` | `(node: { isLeaf: boolean; expanded: boolean }) => React.ReactNode` | — | — | Override the expand/collapse affordance. |
| `virtual` | `boolean` | — | — | Window the rows. Needs `height`; worth it past a few hundred nodes. |

## `<pkg>/tree-select`

### TreeSelect

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `treeData` | `TreeSelectNode[]` | — | yes | — |
| `allowClear` | `boolean` | `true` | — | — |
| `aria-label` | `string` | — | — | — |
| `aria-labelledby` | `string` | — | — | — |
| `className` | `string` | — | — | — |
| `contentClassName` | `string` | — | — | — |
| `defaultValue` | `React.Key \| React.Key[] \| null` | `null` | — | — |
| `disabled` | `boolean` | — | — | — |
| `emptyText` | `React.ReactNode` | `'No results found.'` | — | — |
| `id` | `string` | — | — | — |
| `multiple` | `boolean` | — | — | Allow several selections, shown as removable chips. |
| `onChange` | `(value: React.Key \| React.Key[] \| null) => void` | — | — | — |
| `placeholder` | `string` | `'Select…'` | — | — |
| `searchPlaceholder` | `string` | `'Search…'` | — | — |
| `showSearch` | `boolean` | — | — | Filter the tree from a search box above it. |
| `treeCheckable` | `boolean` | — | — | Checkboxes in the panel. Implies `multiple`. |
| `treeDefaultExpandAll` | `boolean` | — | — | — |
| `value` | `React.Key \| React.Key[] \| null` | — | — | — |

## `<pkg>/upload`

### Upload

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `accept` | `string` | — | — | — |
| `action` | `string \| ((file: UploadFile) => string \| PromiseLike<string>)` | — | — | Where to send the file. A function is resolved per file, for signed URLs. |
| `aria-label` | `string` | — | — | — |
| `beforeUpload` | `(file: UploadFile, fileList: UploadFile[]) => BeforeUploadResult \| Promise<BeforeUploadResult>` | — | — | — |
| `children` | `React.ReactNode` | — | — | — |
| `className` | `string` | — | — | — |
| `classNames` | `{ input?: string }` | — | — | — |
| `customRequest` | `(option: UploadRequestOption, info: { defaultRequest: (option: UploadRequestOption) => UploadRequestHandle }) => UploadRequestHandle \| void` | — | — | Take over the transfer entirely — resumable uploads, SDK clients, S3. |
| `data` | `Record<string, unknown> \| ((file: UploadFile) => Record<string, unknown> \| PromiseLike<Record<string, unknown>>)` | — | — | Extra form fields. A function is resolved per file. |
| `directory` | `boolean` | — | — | Pick a whole folder rather than individual files. |
| `disabled` | `boolean` | — | — | — |
| `headers` | `Record<string, string>` | — | — | — |
| `id` | `string` | — | — | — |
| `method` | `UploadRequestMethod` | `'POST'` | — | — |
| `multiple` | `boolean` | — | — | — |
| `name` | `string` | `'file'` | — | Form field name the file is sent under. |
| `onError` | `(error: UploadRequestError \| ProgressEvent, body: unknown, file: UploadFile) => void` | — | — | — |
| `onProgress` | `(event: UploadProgressEvent, file: UploadFile) => void` | — | — | — |
| `onStart` | `(file: UploadFile) => void` | — | — | — |
| `onSuccess` | `(response: unknown, file: UploadFile, xhr?: XMLHttpRequest) => void` | — | — | — |
| `openFileDialogOnClick` | `boolean` | `true` | — | Set `false` to open the picker yourself, e.g. from a button elsewhere. |
| `variant` | `'button' \| 'dropzone' \| null` | `'dropzone'` | — | — |
| `withCredentials` | `boolean` | — | — | — |

### UploadDropzone

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `hint` | `React.ReactNode` | `'Up to 10 MB each'` | — | — |
| `title` | `React.ReactNode` | `'Drop files here, or click to browse'` | — | — |

## `<pkg>/virtual-list`

### VirtualList

| Prop | Type | Default | Required | Notes |
| --- | --- | --- | --- | --- |
| `children` | `(item: T, index: number) => React.ReactElement` | — | yes | — |
| `data` | `readonly T[]` | — | yes | Rows to render. Only the visible slice is mounted. |
| `height` | `number` | — | yes | Pixel height of the scroll viewport. |
| `itemHeight` | `number` | — | yes | Pixel height of one row. Rows must all be this tall. |
| `itemKey` | `keyof T \| ((item: T) => React.Key)` | — | yes | Stable key per row — an index is not enough once the list reorders. |
| `aria-label` | `string` | — | — | — |
| `className` | `string` | — | — | — |
| `onScroll` | `React.UIEventHandler<HTMLElement>` | — | — | Fires when the viewport scrolls. Use it to trigger infinite loading. |
| `overscan` | `number` | `3` | — | Rows kept mounted above and below the viewport. A few rows of slack mean a fast scroll reveals content rather than blank space. |

