# Select
> Select with a menu that unfolds downward, a pixel highlight that springs between options and type-ahead by first letter.
- React: `import { PxSelect } from "@/components/lumesec/px-select"`
- Collection: Pixel UI (https://elements.lumesec.ai/components/pixel-ui)
- Registry item: https://elements.lumesec.ai/r/px-select.json
- Page: https://elements.lumesec.ai/components/pixel-ui/select



Live preview: https://elements.lumesec.ai/view/px-select

Demo source:

```tsx
import { PxSelect } from "@/components/lumesec/px-select";

export default function PxSelectDemo() {
  return (
    <div className="w-full max-w-[400px] rounded-[14px] border border-border bg-card px-5 py-[18px] shadow-[0_14px_34px_-20px_rgb(0_0_0/0.4)]">
      <PxSelect
        name="model"
        label="Model"
        hint="You can change this per chat"
        defaultValue="sonnet"
        options={[
          { value: "opus", label: "Opus 5.5", description: "Most capable" },
          { value: "sonnet", label: "Sonnet 5.5", description: "Balanced" },
          { value: "haiku", label: "Haiku 4.5", description: "Fastest" },
        ]}
      />
    </div>
  );
}
```

## Playground

Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.

## Installation

```bash
npx shadcn@latest add @lumesec/px-select
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/px-select.json
```

## Usage

React:

```tsx
import { PxSelect } from "@/components/lumesec/px-select";

export function Example() {
  return (
    <PxSelect
      name="model"
      label="Model"
      hint="You can change this per chat"
      defaultValue="sonnet"
      options={[
        { value: "opus", label: "Opus 5.5", description: "Most capable" },
        { value: "sonnet", label: "Sonnet 5.5", description: "Balanced" },
        { value: "haiku", label: "Haiku 4.5", description: "Fastest" },
      ]}
    />
  );
}
```

## Behaviour

Takes a typed list of options. The menu unfolds downward, a pixel highlight follows your pointer or the arrow keys, and typing a letter jumps to it.

## API reference

### Props

Also accepts every prop of `<div>` (`React.ComponentProps<"div">`), spread onto the root element.

| Prop            | Type                        | Default        | Description                                                                                                                                      |
| --------------- | --------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `options`       | `readonly PxSelectOption[]` | —              | The choices: `{ value?: string; label: string; description?: string }`. `value` defaults to `label`; `description` is a second line in the menu. |
| `value`         | `string`                    | —              | Controlled selected value. Use with `onValueChange`.                                                                                             |
| `defaultValue`  | `string`                    | `first option` | Initially selected value when uncontrolled. A form reset restores it.                                                                            |
| `open`          | `boolean`                   | —              | Controlled open state of the menu. Use with `onOpenChange`.                                                                                      |
| `defaultOpen`   | `boolean`                   | `false`        | Initial open state when uncontrolled.                                                                                                            |
| `label`         | `React.ReactNode`           | —              | Label above the trigger; also names the listbox.                                                                                                 |
| `hint`          | `React.ReactNode`           | —              | Help text under the trigger.                                                                                                                     |
| `name`          | `string`                    | —              | Form field name; the selected value submits under it.                                                                                            |
| `disabled`      | `boolean`                   | `false`        | Dims the select and disables the trigger.                                                                                                        |
| `onValueChange` | `(value: string) => void`   | —              | Called when the user picks a different option.                                                                                                   |
| `onOpenChange`  | `(open: boolean) => void`   | —              | Called when the menu opens or closes.                                                                                                            |

### Ref

`ref` points at the root `HTMLDivElement`.

## Keyboard

| Keys                                 | Action                                                            |
| ------------------------------------ | ----------------------------------------------------------------- |
| ArrowDown / ArrowUp (on the trigger) | Open the menu.                                                    |
| ArrowDown / ArrowUp (in the menu)    | Move the highlight; stops at the first and last option.           |
| Home / End                           | Highlight the first / last option.                                |
| Enter / Space                        | Choose the highlighted option and close.                          |
| Escape / Tab                         | Close and return focus to the trigger.                            |
| Printable character                  | Highlight the next option whose label starts with that character. |

## Accessibility

* The trigger is a native button with `aria-haspopup="listbox"`, `aria-expanded` and `aria-labelledby` pointing at the label and the selected value.
* The menu is a `role="listbox"` labelled by the label, with `aria-activedescendant` on the highlighted option; options have `role="option"` and `aria-selected`.
* Opening moves focus to the listbox; choosing, Escape or Tab return it to the trigger. A pointer press outside closes the menu without moving focus.
* `hint` is not linked with `aria-describedby`. The highlight canvas is `aria-hidden`.
* With `name`, a hidden input submits the selected option's value. There is no validation. Form reset restores `defaultValue` (or the first option) and calls `onValueChange` when that changes the value.
* Reduced motion: the menu opens without unfolding, the chevron does not rotate, the highlight jumps and the value swaps without rolling.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--foreground`, `--muted-foreground`, `--card`, `--border` and `--lumesec`.

## Notes

* The menu opens below the whole component, under the hint, and overlays the content after it (`z-index: 30`).
* The root carries `data-state="open"` or `data-state="closed"`.


