> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Select

> A select field with optional label, helper/error text, and an icon slot, built on Radix UI Select for full accessibility and keyboard navigation.

```tsx theme={null}
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
} from "@fanvue/ui";
import type {
  SelectContentProps,
  SelectGroupProps,
  SelectItemProps,
  SelectItemSize,
  SelectLabelProps,
  SelectProps,
  SelectSeparatorProps,
  SelectSize,
} from "@fanvue/ui";
```

## Examples

## Default

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-select--default&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="280" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Select — Default" />
</Frame>

```tsx theme={null}
import { Select, SelectContent, SelectItem } from "@fanvue/ui";

const COUNTRIES = [
  { value: "us", label: "United States" },
  { value: "uk", label: "United Kingdom" },
  { value: "ca", label: "Canada" },
  { value: "au", label: "Australia" },
  { value: "de", label: "Germany" },
];

const DefaultContent = () => (
  <SelectContent>
    {COUNTRIES.map((c) => (
      <SelectItem key={c.value} value={c.value}>
        {c.label}
      </SelectItem>
    ))}
  </SelectContent>
);

<Select label="Label" placeholder="Placeholder Text" helperText="Helper Text">
  <DefaultContent />
</Select>
```

## Without Label

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-select--without-label&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="280" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Select — Without Label" />
</Frame>

```tsx theme={null}
import { Select, SelectContent, SelectItem } from "@fanvue/ui";

const COUNTRIES = [
  { value: "us", label: "United States" },
  { value: "uk", label: "United Kingdom" },
  { value: "ca", label: "Canada" },
  { value: "au", label: "Australia" },
  { value: "de", label: "Germany" },
];

const DefaultContent = () => (
  <SelectContent>
    {COUNTRIES.map((c) => (
      <SelectItem key={c.value} value={c.value}>
        {c.label}
      </SelectItem>
    ))}
  </SelectContent>
);

<Select aria-label="Country" placeholder="Select a country">
  <DefaultContent />
</Select>
```

## All Sizes

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-select--all-sizes&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="280" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Select — All Sizes" />
</Frame>

```tsx theme={null}
import { Select, SelectContent, SelectItem } from "@fanvue/ui";

const COUNTRIES = [
  { value: "us", label: "United States" },
  { value: "uk", label: "United Kingdom" },
  { value: "ca", label: "Canada" },
  { value: "au", label: "Australia" },
  { value: "de", label: "Germany" },
];

const DefaultContent = () => (
  <SelectContent>
    {COUNTRIES.map((c) => (
      <SelectItem key={c.value} value={c.value}>
        {c.label}
      </SelectItem>
    ))}
  </SelectContent>
);

<div className="flex w-[375px] flex-col gap-4">
  <Select size="48" label="Size 48" placeholder="Placeholder Text">
    <DefaultContent />
  </Select>
  <Select size="40" label="Size 40" placeholder="Placeholder Text">
    <DefaultContent />
  </Select>
  <Select size="32" label="Size 32" placeholder="Placeholder Text">
    <DefaultContent />
  </Select>
</div>
```

## Full Width

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-select--full-width&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="280" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Select — Full Width" />
</Frame>

```tsx theme={null}
import { Select, SelectContent, SelectItem } from "@fanvue/ui";

const COUNTRIES = [
  { value: "us", label: "United States" },
  { value: "uk", label: "United Kingdom" },
  { value: "ca", label: "Canada" },
  { value: "au", label: "Australia" },
  { value: "de", label: "Germany" },
];

const DefaultContent = () => (
  <SelectContent>
    {COUNTRIES.map((c) => (
      <SelectItem key={c.value} value={c.value}>
        {c.label}
      </SelectItem>
    ))}
  </SelectContent>
);

<Select label="Country" placeholder="Select a country" fullWidth>
  <DefaultContent />
</Select>
```

## With Groups And Separator

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-select--with-groups-and-separator&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="280" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="Select — With Groups And Separator" />
</Frame>

```tsx theme={null}
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
} from "@fanvue/ui";

<Select label="Location" placeholder="Select a location">
  <SelectContent>
    <SelectGroup>
      <SelectLabel>North America</SelectLabel>
      <SelectItem value="us">United States</SelectItem>
      <SelectItem value="ca">Canada</SelectItem>
    </SelectGroup>
    <SelectSeparator />
    <SelectGroup>
      <SelectLabel>Europe</SelectLabel>
      <SelectItem value="uk">United Kingdom</SelectItem>
      <SelectItem value="de">Germany</SelectItem>
      <SelectItem value="fr">France</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>
```

## Props

## Select

A select field with optional label, helper/error text, and an icon slot, built on Radix UI Select for full accessibility and keyboard navigation.

Pair with `SelectContent` and `SelectItem` to provide options.

<ParamField path="aria-label" type="string">
  Accessible name applied directly to the trigger button when no visible `label` is provided.
</ParamField>

<ParamField path="aria-labelledby" type="string">
  ID of an external element that labels the trigger button.
</ParamField>

<ParamField path="className" type="string">
  Wraps the `className` of the outermost container div.
</ParamField>

<ParamField path="defaultValue" type="string" />

<ParamField path="error" type="boolean" default="false">
  Whether the field is in an error state.
</ParamField>

<ParamField path="errorMessage" type="string">
  Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`.
</ParamField>

<ParamField path="fullWidth" type="boolean" default="false">
  Whether the field stretches to fill its container width.
</ParamField>

<ParamField path="helperText" type="string">
  Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`.
</ParamField>

<ParamField path="id" type="string">
  HTML `id` applied to the trigger button. Auto-generated if omitted.
</ParamField>

<ParamField path="label" type="string">
  Label text displayed above the trigger. Also used as the accessible name.
</ParamField>

<ParamField path="leftIcon" type="ReactNode">
  Icon element displayed at the left side of the trigger.
</ParamField>

<ParamField path="onValueChange" type="((value: string) => void)" />

<ParamField path="placeholder" type="string">
  Placeholder shown when no value is selected.
</ParamField>

<ParamField path="size" type="&#x22;32&#x22; | &#x22;40&#x22; | &#x22;48&#x22;" default="48">
  Height of the select field in pixels.
</ParamField>

<ParamField path="value" type="string" />

## SelectContent

The dropdown panel rendered inside a portal. Place `SelectItem` elements (and optionally `SelectGroup` / `SelectLabel`) as children.

<ParamField path="asChild" type="boolean" />

## SelectGroup

Groups related `SelectItem` elements under a `SelectLabel`.

A direct re-export of the Radix `SelectPrimitive.Group` primitive. It accepts all of that primitive's props, unchanged.

## SelectItem

An individual option inside `SelectContent`, following the V2 Menu Item spec.

Supports a leading icon or avatar, an optional two-line layout via `description`, and the standard hover / selected / disabled states. The selected row is marked with a trailing check indicator.

<ParamField path="asChild" type="boolean" />

<ParamField path="avatar" type="ReactNode">
  Leading avatar rendered in place of `SelectItemProps.leadingIcon`, for rows representing a person or account. Pass an `Avatar` sized to `24`. Takes precedence over `leadingIcon`.
</ParamField>

<ParamField path="description" type="ReactNode">
  Optional secondary text rendered on a second line below the label.
</ParamField>

<ParamField path="leadingIcon" type="ReactNode">
  Icon (or other node) rendered before the label. Ignored when `SelectItemProps.avatar` is set.
</ParamField>

<ParamField path="size" type="&#x22;32&#x22; | &#x22;40&#x22;" default="48">
  Row height. Defaults to the parent `Select` size (`48`/`40` → `40`, `32` → `32`).
</ParamField>

## SelectLabel

A non-interactive label shown above a `SelectGroup`.

<ParamField path="asChild" type="boolean" />

## SelectSeparator

A horizontal rule that visually separates groups in `SelectContent`.

<ParamField path="asChild" type="boolean" />

## Exported types

Also exported from `@fanvue/ui`: `SelectContentProps`, `SelectGroupProps`, `SelectItemProps`, `SelectItemSize`, `SelectLabelProps`, `SelectProps`, `SelectSeparatorProps`, `SelectSize`.

***

**Setup:** [Installation](/docs/ui/installation) · [Theming](/docs/ui/theming)
