Skip to content
NewService Map: 30 components for hosts, ports and routes
<PxSelect />ReactFormsForm controlFree

Select

Select with a menu that unfolds downward, a pixel highlight that springs between options and type-ahead by first letter.

View as Markdown
<PxSelect />

Playground

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

Loading <PxSelect />
Props
defaultValueremounts
labellive
disabledlive
React
<PxSelect
  label="Model"
  hint="You can change this per chat"
  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"
    }
  ]}
  defaultValue="sonnet"
/>

Installation

pnpm dlx shadcn@latest add @lumesec/px-select
First timeRegister the @lumesec registry once, or install by URL+

Adds @lumesec to your components.json:

pnpm dlx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json

Or skip the setup and install by URL:

npx shadcn@latest add https://elements.lumesec.ai/r/px-select.json

Usage

px-select-example.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.

optionsTypereadonly PxSelectOption[]

The choices: { value?: string; label: string; description?: string }. value defaults to label; description is a second line in the menu.

valueTypestring

Controlled selected value. Use with onValueChange.

defaultValueTypestringDefaultfirst option

Initially selected value when uncontrolled. A form reset restores it.

openTypeboolean

Controlled open state of the menu. Use with onOpenChange.

defaultOpenTypebooleanDefaultfalse

Initial open state when uncontrolled.

labelTypeReact.ReactNode

Label above the trigger; also names the listbox.

hintTypeReact.ReactNode

Help text under the trigger.

nameTypestring

Form field name; the selected value submits under it.

disabledTypebooleanDefaultfalse

Dims the select and disables the trigger.

onValueChangeType(value: string) => void

Called when the user picks a different option.

onOpenChangeType(open: boolean) => void

Called when the menu opens or closes.

Ref

ref points at the root HTMLDivElement.

Keyboard

KeysAction
ArrowDown / ArrowUp (on the trigger)Open the menu.
ArrowDown / ArrowUp (in the menu)Move the highlight; stops at the first and last option.
Home / EndHighlight the first / last option.
Enter / SpaceChoose the highlighted option and close.
Escape / TabClose and return focus to the trigger.
Printable characterHighlight 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.

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".

Was this page helpful?