("en");
const selected = languages.find((language) => language.id === value);
return (
setValue(key)}>
Language
{languages.map((language) => (
{language.name}
))}
Selected: {selected?.name ?? "None"}
);
}
```
## Custom Value
Render a custom display for the selected value with a function child on `CellSelect.Value`.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
const statuses = [
{color: "bg-success", id: "online", name: "Online"},
{color: "bg-warning", id: "away", name: "Away"},
{color: "bg-danger", id: "busy", name: "Busy"},
{color: "bg-muted", id: "offline", name: "Offline"},
];
export function CustomValue() {
return (
Status
{({defaultChildren, isPlaceholder, state}) => {
if (isPlaceholder || state.selectedItems.length === 0) {
return defaultChildren;
}
const status = statuses.find((s) => s.id === state.selectedItems[0]?.key);
if (!status) {
return defaultChildren;
}
return (
{status.name}
);
}}
{statuses.map((status) => (
{status.name}
))}
);
}
```
## Disabled
Pass `isDisabled` to disable the cell.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
{id: "de", name: "Deutsch"},
{id: "ja", name: "日本語"},
];
export function Disabled() {
return (
Language
{languages.map((language) => (
{language.name}
))}
);
}
```
## Font Family
Each option and the selected value can be rendered in its own font family.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
const fonts = [
{family: "ui-sans-serif, system-ui, sans-serif", id: "sans", name: "Sans Serif"},
{family: "ui-serif, Georgia, serif", id: "serif", name: "Serif"},
{family: "ui-monospace, SFMono-Regular, monospace", id: "mono", name: "Monospace"},
];
export function FontFamily() {
return (
Font Family
{({defaultChildren, isPlaceholder, state}) => {
if (isPlaceholder || state.selectedItems.length === 0) {
return defaultChildren;
}
const font = fonts.find((f) => f.id === state.selectedItems[0]?.key);
if (!font) {
return defaultChildren;
}
return {font.name};
}}
{fonts.map((font) => (
{font.name}
))}
);
}
```
## Leading Icon
Add a `CellSelect.Icon` before the label. Pass the `tile` prop to render it as a colored
rounded "tile" (the icon's color can be customized with `className` or `style`).
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
{id: "de", name: "Deutsch"},
];
export function WithIcon() {
return (
Language
{languages.map((language) => (
{language.name}
))}
Language
{languages.map((language) => (
{language.name}
))}
);
}
```
## Two-line Cell
Wrap the label and a `CellSelect.Description` in `CellSelect.Content` to build a two-line
cell with a muted subtitle. The one-line API keeps working when `Content` is omitted.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
{id: "de", name: "Deutsch"},
];
export function TwoLine() {
return (
Language
Choose your preferred language
{languages.map((language) => (
{language.name}
))}
);
}
```
## Sizes
Use the `size` prop (`sm`, `md`, `lg`) to control the cell height, padding, and text size.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
{id: "de", name: "Deutsch"},
];
export function Sizes() {
return (
{(["sm", "md", "lg"] as const).map((size) => (
{size}
{languages.map((language) => (
{language.name}
))}
))}
);
}
```
## Settings Group
Wrap multiple cells in `CellSelect.Group` to fuse them into a single inset panel with
merged corners and hairline dividers. Add an optional `header` and `footer`.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
];
const themes = [
{id: "system", name: "System"},
{id: "light", name: "Light"},
{id: "dark", name: "Dark"},
];
const regions = [
{id: "us", name: "United States"},
{id: "eu", name: "Europe"},
{id: "apac", name: "Asia Pacific"},
];
export function SettingsGroup() {
return (
Language
{languages.map((language) => (
{language.name}
))}
Theme
{themes.map((theme) => (
{theme.name}
))}
Region
{regions.map((region) => (
{region.name}
))}
);
}
```
## Variants
Use `variant="secondary"` for an accent-tinted cell. The variant styles the trigger row.
```tsx
"use client";
import {CellSelect, ListBox} from "@darkcode-ui/react";
const languages = [
{id: "en", name: "English"},
{id: "es", name: "Español"},
{id: "fr", name: "Français"},
{id: "de", name: "Deutsch"},
];
export function Variants() {
return (
Default
{languages.map((language) => (
{language.name}
))}
Secondary
{languages.map((language) => (
{language.name}
))}
);
}
```
## Styling
CellSelect wraps the [Select](/react/components/select) component, so all Select styling
patterns apply. The cell layout is provided by the BEM classes below.
### CSS Classes
The CellSelect component uses the following CSS classes:
#### Base Classes
- `.cell-select` - Root wrapper
#### Element Classes
- `.cell-select__trigger` - The visible cell row (wraps Select.Trigger)
- `.cell-select__trigger--default` - Default variant trigger styling
- `.cell-select__trigger--secondary` - Secondary variant trigger styling
- `.cell-select__trigger--sm` / `.cell-select__trigger--lg` - Size modifiers (base is `md`)
- `.cell-select__icon` - Leading icon slot (`[data-tile="true"]` renders the colored tile)
- `.cell-select__content` - Column wrapping the label and description (two-line cell)
- `.cell-select__label` - Leading text label
- `.cell-select__description` - Secondary text under the label
- `.cell-select__value` - Selected value display
- `.cell-select__indicator` - Chevron icon
- `.cell-select__popover` - Dropdown panel
- `.cell-select__group-section` - Group wrapper (header + card + footer)
- `.cell-select__group` - Inset card that fuses the cells
- `.cell-select__group-header` / `.cell-select__group-footer` - Group header and footer text
## API Reference
### CellSelect
The root component. Wraps DarkCode UI [Select](/react/components/select) with cell-style layout.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `variant` | `'default' \| 'secondary'` | `'default'` | Visual style variant. |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Cell height, padding, and text size. |
Also supports all [DarkCode UI Select](/react/components/select) props except `variant`.
### CellSelect.Trigger
The visible cell row containing the icon, label, value, and indicator.
Also supports all DarkCode UI `Select.Trigger` props.
### CellSelect.Icon
Leading icon slot rendered as a `span`.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `tile` | `boolean` | `false` | Render the icon as a colored rounded tile. |
| `children` | `ReactNode` | - | Icon element. |
Also supports all native `span` HTML attributes.
### CellSelect.Content
Column that stacks the label and description for a two-line cell. Rendered as a `div`.
Also supports all native `div` HTML attributes.
### CellSelect.Label
Leading text label rendered as a `span`.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | - | Label text. |
Also supports all native `span` HTML attributes.
### CellSelect.Description
Secondary text rendered under the label (inside `CellSelect.Content`), as a `span`.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | - | Description text. |
Also supports all native `span` HTML attributes.
### CellSelect.Value
Display of the currently selected value.
Also supports all DarkCode UI `Select.Value` props.
### CellSelect.Indicator
Chevron icon. Defaults to a `ChevronsExpandVertical` icon when no children are provided.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | - | Custom indicator icon. |
Also supports all DarkCode UI `Select.Indicator` props.
### CellSelect.Popover
Dropdown panel for selection options.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `placement` | `Placement` | `'bottom end'` | Popover placement relative to the trigger. |
Also supports all DarkCode UI `Select.Popover` props.
### CellSelect.Group
Wraps multiple cells into one inset panel with merged corners and hairline dividers. Used
outside individual `CellSelect` roots.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `header` | `ReactNode` | - | Optional section header rendered above the panel. |
| `footer` | `ReactNode` | - | Optional section footer rendered below the panel. |
Also supports all native `div` HTML attributes.
## Accessibility
CellSelect is built on the same React Aria Select primitive as the
[Select](/react/components/select) component and provides:
- Full keyboard navigation support (Arrow keys, Home, End, type-ahead)
- Screen reader announcements for the listbox and selection
- Proper focus management between the trigger and popover
- Support for disabled states
For more information, see the [React Aria Select documentation](https://react-spectrum.adobe.com/react-aria/Select.html).