Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Select

Dropdown select with searchable options, keyboard navigation, and full ARIA listbox semantics for accessible form inputs.

Components Select
input interactive
<arc-select>

Overview

The Select component replaces the native `<select>` element with a fully styled, accessible dropdown that integrates seamlessly with ARC UI's design tokens. It provides built-in type-ahead search filtering, allowing users to quickly locate options in long lists without scrolling. Select implements the ARIA listbox pattern, ensuring screen readers announce the current selection, available options, and navigation cues. Keyboard users can open the dropdown with Enter or Space, navigate with arrow keys, filter by typing, and confirm a choice with Enter — all without reaching for a mouse. Use Select any time you need a single-choice dropdown in a form: assigning a team member, choosing a category, picking a status, or selecting a locale. For multi-choice scenarios, reach for MultiSelect instead. For short lists of three or fewer visible options, consider RadioGroup for faster scanning.

Guidelines

When to use

  • Always provide a visible label so users understand what they are selecting
  • Use a meaningful placeholder like "Choose a team member..." rather than generic "Select..."
  • Keep option labels concise — ideally under 40 characters
  • Order options logically (alphabetical, by frequency, or by workflow step)
  • Pre-select a sensible default when one exists to reduce interaction cost
  • Use the disabled state to indicate temporarily unavailable choices (e.g. permissions)

When not to use

  • Do not use Select for fewer than 3 options — use RadioGroup for better scannability
  • Do not nest selects inside other selects — flatten the hierarchy or use a staged flow
  • Do not rely solely on placeholder text as a label — placeholders disappear once a value is chosen
  • Do not use Select for navigation — use NavigationMenu or tabs for moving between views
  • Do not disable the component without explaining why — pair disabled state with a tooltip or helper text

Features

  • Type-ahead search filtering narrows options as the user types
  • Full keyboard navigation: Arrow keys, Home, End, Enter, Escape
  • ARIA listbox role with active-descendant tracking for screen readers
  • Supports placeholder text for empty-state guidance
  • Controlled and uncontrolled value modes
  • Disabled state prevents interaction and conveys unavailability visually
  • Automatic scroll-into-view for the highlighted option in long lists
  • Works with dynamic option lists — update the options array at any time
  • Consistent styling across browsers via Shadow DOM encapsulation

Preview

Alice Chen Bob Martinez Carol Nguyen David Okafor Eva Johansson

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<script type="module" src="@arclux/arc-ui"></script>

<!-- Basic select -->
<arc-select label="Assign to team member" placeholder="Choose a person...">
  <arc-option value="alice-chen">Alice Chen</arc-option>
  <arc-option value="bob-martinez">Bob Martinez</arc-option>
  <arc-option value="carol-nguyen">Carol Nguyen</arc-option>
  <arc-option value="david-okafor">David Okafor</arc-option>
  <arc-option value="eva-johansson">Eva Johansson</arc-option>
</arc-select>

<!-- Pre-selected value -->
<arc-select label="Status" value="in-progress">
  <arc-option value="open">Open</arc-option>
  <arc-option value="in-progress">In Progress</arc-option>
  <arc-option value="review">In Review</arc-option>
  <arc-option value="done">Done</arc-option>
</arc-select>

<!-- In a native form -->
<form action="/api/assign" method="post">
  <arc-select name="assignee" label="Assignee" placeholder="Pick someone...">
    <arc-option value="alice">Alice</arc-option>
    <arc-option value="bob">Bob</arc-option>
  </arc-select>
  <button type="submit">Save</button>
</form>

<script>
  document.querySelector('arc-select')
    .addEventListener('arc-change', (e) => {
      console.log('Selected:', e.detail.value, e.detail.label);
    });
</script>
import { Select, Option } from '@arclux/arc-ui-react';
import { useState } from 'react';

function TeamAssigner() {
  const [assignee, setAssignee] = useState('');

  return (
    <Select
      label="Assign to team member"
      placeholder="Choose a person..."
      value={assignee}
      onArcChange={(e) => setAssignee(e.detail.value)}
    >
      <Option value="alice-chen">Alice Chen</Option>
      <Option value="bob-martinez">Bob Martinez</Option>
      <Option value="carol-nguyen">Carol Nguyen</Option>
      <Option value="david-okafor">David Okafor</Option>
      <Option value="eva-johansson">Eva Johansson</Option>
    </Select>
  );
}

function StatusPicker() {
  return (
    <Select label="Status" value="in-progress">
      <Option value="open">Open</Option>
      <Option value="in-progress">In Progress</Option>
      <Option value="review">In Review</Option>
      <Option value="done">Done</Option>
    </Select>
  );
}
<script setup>
import { Select, Option } from '@arclux/arc-ui-vue';
import { ref } from 'vue';

const assignee = ref('');
</script>

<template>
  <Select
    label="Assign to team member"
    placeholder="Choose a person..."
    :value="assignee"
    @arc-change="assignee = $event.detail.value"
  >
    <Option value="alice-chen">Alice Chen</Option>
    <Option value="bob-martinez">Bob Martinez</Option>
    <Option value="carol-nguyen">Carol Nguyen</Option>
    <Option value="david-okafor">David Okafor</Option>
    <Option value="eva-johansson">Eva Johansson</Option>
  </Select>
</template>
<script>
  import { Select, Option } from '@arclux/arc-ui-svelte';

  let status = 'open';
</script>

<Select label="Task status" value={status}
  on:arc-change={(e) => status = e.detail.value}>
  <Option value="open">Open</Option>
  <Option value="in-progress">In Progress</Option>
  <Option value="review">In Review</Option>
  <Option value="done">Done</Option>
  <Option value="closed">Closed</Option>
</Select>
import { Component } from '@angular/core';
import { Select, Option } from '@arclux/arc-ui-angular';

@Component({
  imports: [Select, Option],
  template: `
    <arc-select label="Assign to team member" placeholder="Choose a person..."
      [value]="assignee" (arc-change)="assignee = $event.detail.value">
      <arc-option value="alice-chen">Alice Chen</arc-option>
      <arc-option value="bob-martinez">Bob Martinez</arc-option>
      <arc-option value="carol-nguyen">Carol Nguyen</arc-option>
      <arc-option value="david-okafor">David Okafor</arc-option>
      <arc-option value="eva-johansson">Eva Johansson</arc-option>
    </arc-select>
  `,
})
export class AssignmentComponent {
  assignee = '';
}
import { Select, Option } from '@arclux/arc-ui-solid';
import { createSignal } from 'solid-js';

function CategoryPicker() {
  const [category, setCategory] = createSignal('');

  return (
    <Select label="Category" placeholder="Choose a category..."
      value={category()} onArcChange={(e) => setCategory(e.detail.value)}>
      <Option value="bug">Bug Report</Option>
      <Option value="feature">Feature Request</Option>
      <Option value="docs">Documentation</Option>
      <Option value="question">Question</Option>
    </Select>
  );
}
import { Select, Option } from '@arclux/arc-ui-preact';
import { useState } from 'preact/hooks';

function LocalePicker() {
  const [locale, setLocale] = useState('en');

  return (
    <Select label="Language" value={locale}
      onArcChange={(e) => setLocale(e.detail.value)}>
      <Option value="en">English</Option>
      <Option value="es">Español</Option>
      <Option value="fr">Français</Option>
      <Option value="de">Deutsch</Option>
      <Option value="ja">日本語</Option>
    </Select>
  );
}

API

value string ''
The currently selected value. Must match one of the child `arc-option` value attributes. Setting this programmatically updates the displayed label and internal selection state.
placeholder string 'Select...'
Hint text displayed inside the trigger button when no option is selected. Use it to communicate what kind of choice the user should make, such as "Choose a team member..." or "Pick a status". The placeholder disappears once a value is chosen.
label string ''
Visible label rendered above the select trigger. Also serves as the accessible name for assistive technologies. Always provide a label for accessibility compliance.
name string ''
Form field name submitted with the selected value. Required for native form integration via ElementInternals.
disabled boolean false
When true, the select trigger becomes non-interactive: it cannot be opened, focused via keyboard, or clicked. The component renders with reduced opacity to visually convey the unavailable state.
size 'sm' | 'md' | 'lg' 'md'
Controls the select trigger size.
error string ''
Error message displayed below the select. When set, the trigger border turns red.
open boolean false
Controls whether the dropdown is visible. Set programmatically to open or close the dropdown. Automatically set to `false` when an option is selected or the user clicks outside.
formAssociated boolean true
properties object { required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, }
Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
autoValidates boolean true
Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
form
validity
validationMessage
required boolean false
readonly boolean false

Events

arc-change
Fired when the selected option changes

Option

<arc-option>

Individual option rendered inside a Select or MultiSelect. Each Option provides a value for form submission and displays its text content as the label in the dropdown.

label
Expose text content as label
value string ''
The value identifier for this option, used to match against the parent control value.
disabled boolean false
When true, dims this option and prevents it from being selected.
selected boolean false

See Also