Stable

Select

Select lets users choose one option from a list, styled to match the filled Text Field trigger. It's powered by bits-ui's Select.Root and is entirely driven by an options array — it does not accept option elements as children.

Overview

Material Design 3 doesn't have a standalone top-level page for "Select" — dropdown selection is specified as part of the Menus family. This component pairs a Text-Field-style trigger with a menu-style Select.Content popover.

Pass a flat array of { value, label } items to options, or nest them under { type: "group", heading, items } entries for labelled sections.

Import

import { Select } from '@noxlovette/material';

Live Demo

See it live, with Controls, in Storybook rather than a hand-rolled preview here.

widgets

Playground

Open the Select story, plus Grouped Options and States variants.

Basic Usage

Bind value and pass an options array:

<script lang="ts">
  import { Select } from '@noxlovette/material';
  import type { SelectOption } from '@noxlovette/material';

  let fruit = $state<string | undefined>();

  const options: SelectOption[] = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'cherry', label: 'Cherry' }
  ];
</script>

<Select type="single" placeholder="Choose a fruit" {options} bind:value={fruit} />

Select Props

PropTypeDefaultDescription
type required
"single" | "multiple"Selection mode, from bits-ui's Select.RootProps — 'single' binds value to a string, 'multiple' to a string[].
value
string | string[] | undefinedThe selected value(s), matching bits-ui Select.RootProps. Bindable.
open
booleanfalseWhether the option list is open. Bindable.
options
SelectOption[][]Flat or grouped list of options; drives the entire dropdown content (see below).
placeholder required
stringText shown in the trigger when no value is selected.
disabled
booleanfalseDisables the select.
error
booleanfalseRenders the select in an error state.
supportingText
SnippetHelper text displayed below the select.
leadingIconProps
IconPropsProps for an optional leading icon in the trigger.
triggerProps
Select.TriggerPropsAdditional props forwarded to bits-ui's Select.Trigger.
contentProps
Select.ContentPropsAdditional props forwarded to bits-ui's Select.Content.
portalDisabled
booleanfalseDisables the portal — useful when the select is nested inside a Dialog/Sheet that manages its own stacking.

Option Shape (SelectOption)

Each entry in options is either an item or a group:

FieldTypeDefaultDescription
value required
stringThe option value.
label
stringDisplay label; also used as the accessible name.
disabled
booleanfalseDisables this individual option.
type
"item" | "group""item"Set to 'group' with a heading and nested items to render a labelled group instead of a single option.

When type: 'group' is set, use heading (optional) and a nested items: SelectOption[] array instead of value/label.

Themed Primitives

SelectItem, SelectGroup, SelectLabel, and SelectSeparator are also exported. They carry the same MD3 styling as the internal rendering Select does from its options prop, but Select itself does not expose a slot to compose them as children — its Select.Content is built entirely from options. These primitives are meant for consumers who need a custom dropdown built directly against bits-ui's Select.Root instead of this component, and want matching visuals.

Accessibility

keyboard

Keyboard navigation

Arrow keys move through options, Enter/Space selects, Escape closes — all handled by bits-ui Select primitives.

check

Selected indicator

The selected item shows a check icon in addition to a colored background, avoiding a color-only signal.

block

Disabled options

Individual options can be disabled via SelectOption.disabled and are skipped during keyboard navigation.