Antares
Components

Select

Accessible dropdown component supporting single and multiple selection with keyboard navigation and validation

Installation

npm install --save @godaddy/antares

Props

NameTypeDefault
label?string | undefined

Visible label above the trigger Required if aria-label is not provided

autoFocus?boolean | undefined

Focus on mount

childrenReactNode | ((item: T) => ReactNode)

SelectItem elements or render function

className?string | undefined

Component CSS class

defaultOpen?boolean | undefined

Default open state (uncontrolled)

defaultSelectedKey?RACKey | undefined

Initial selected key (uncontrolled)

description?string | undefined

Help text below the trigger

errorMessage?string | undefined

Error text shown when invalid

isDisabled?boolean | undefined

Disables interaction

isInvalid?boolean | undefined

Shows error styling and errorMessage

isOpen?boolean | undefined

Open state (controlled)

isRequired?boolean | undefined

Shows red asterisk, requires value for submission

items?Iterable<T> | undefined

Items for dynamic rendering (children must be render function)

labelStyle?"default" | "float" | undefined'default'

Label positioning style

name?string | undefined

Form submission name

onOpenChange?((isOpen: boolean) => void) | undefined

Called when open state changes

onSelectionChange?((key: RACKey | null) => void) | undefined

Called when selection changes

placeholder?string | undefined

Placeholder text when empty

selectedKey?RACKey | null | undefined

Selected key (controlled)

selectionMode?"single" | "multiple" | undefined'single'

Whether single or multiple selection is enabled

size?"sm" | "md" | undefined'md'

Visual size variant

Examples

Static

import { Select, SelectItem } from '@godaddy/antares';export function SelectStaticExample() {  return (    <Select aria-label="Coffee drinks">      <SelectItem id="espresso">Espresso</SelectItem>      <SelectItem id="latte">Latte</SelectItem>      <SelectItem id="cappuccino">Cappuccino</SelectItem>      <SelectItem id="americano">Americano</SelectItem>      <SelectItem id="mocha">Mocha</SelectItem>    </Select>  );}

Controlled

Selected: latte
import { useState } from 'react';import { Box, Flex, Select, SelectItem } from '@godaddy/antares';export function SelectControlledExample() {  const [selectedKey, setSelectedKey] = useState<string>('latte');  return (    <Flex direction="column" gap="md">      <Select        aria-label="Coffee drinks"        selectedKey={selectedKey}        onSelectionChange={(key) => setSelectedKey(key as string)}      >        <SelectItem id="espresso">Espresso</SelectItem>        <SelectItem id="latte">Latte</SelectItem>        <SelectItem id="cappuccino">Cappuccino</SelectItem>        <SelectItem id="americano">Americano</SelectItem>        <SelectItem id="mocha">Mocha</SelectItem>      </Select>      <Box padding="md" elevation="card" rounding="lg">        <strong>Selected:</strong> {selectedKey}      </Box>    </Flex>  );}

Dynamic Items

import { Select, SelectItem } from '@godaddy/antares';const items = [  { id: '1', name: 'Espresso', category: 'Classic' },  { id: '2', name: 'Latte', category: 'Classic' },  { id: '3', name: 'Cappuccino', category: 'Classic' },  { id: '4', name: 'Americano', category: 'Classic' },  { id: '5', name: 'Mocha', category: 'Specialty' },  { id: '6', name: 'Macchiato', category: 'Specialty' },  { id: '7', name: 'Cold Brew', category: 'Cold' }];export function SelectDynamicExample() {  return (    <Select aria-label="Coffee drinks" items={items}>      {function renderItem(item) {        return (          <SelectItem id={item.id} textValue={item.name}>            {item.name} ({item.category})          </SelectItem>        );      }}    </Select>  );}

Multiple Selection

import { Select, SelectItem } from '@godaddy/antares';export function SelectMultipleExample() {  return (    <Select aria-label="Coffee drinks" selectionMode="multiple">      <SelectItem id="espresso">Espresso</SelectItem>      <SelectItem id="latte">Latte</SelectItem>      <SelectItem id="cappuccino">Cappuccino</SelectItem>      <SelectItem id="americano">Americano</SelectItem>      <SelectItem id="mocha">Mocha</SelectItem>    </Select>  );}

Customization

Data Attributes

React Aria Components automatically adds data attributes for styling different states:

Select Container: data-invalid, data-disabled, data-required, data-focused

Trigger Button: data-pressed, data-disabled, data-focused, aria-expanded

Select Value: data-placeholder

Popover: data-entering, data-exiting

List Items: data-hovered, data-focused, data-pressed, data-selected, data-disabled, data-selection-mode

[data-selected] {
  background-color: #eff6ff;
  font-weight: 600;
}

[data-invalid] .button {
  border-color: #dc2626;
}

[aria-expanded="true"] {
  border-color: #3b82f6;
}

Component Customization

Individual child components can be styled by passing className props:

<Select label="Coffee">
  <SelectItem id="espresso" className="premium-option">
    Espresso
  </SelectItem>
  <SelectSection className="featured-section">
    <SelectHeader>Featured</SelectHeader>
    <SelectItem id="special">Special Blend</SelectItem>
  </SelectSection>
</Select>

Accessibility

Keyboard Navigation

  • Space/Enter: Opens the popover and focuses the selected item
  • Arrow Down/Up: Navigate through options
  • Home/End: Jump to first/last option
  • Escape: Closes the popover
  • Tab: Moves focus to the next focusable element
  • Type to select: Type characters to jump to matching options
  • Space (in multi-select): Toggle selection of focused item

Troubleshooting

Selection Not Updating

// ❌ Wrong: Using both value and defaultValue
<Select value={value} defaultValue="espresso">
  <SelectItem id="espresso">Espresso</SelectItem>
</Select>

// ✅ Controlled mode
<Select value={value} onChange={setValue}>
  <SelectItem id="espresso">Espresso</SelectItem>
</Select>

// ✅ Uncontrolled mode
<Select defaultValue="espresso">
  <SelectItem id="espresso">Espresso</SelectItem>
</Select>

Styling Overrides Not Applying

/* ❌ May not have enough specificity */
.item {
  background-color: red;
}

/* ✅ Use data attributes for higher specificity */
.my-select [data-selected] {
  background-color: red;
}

Keyboard Navigation Not Working

/* ❌ Don't remove focus outlines without replacement */
.button:focus {
  outline: none;
}

/* ✅ Provide visible focus indicator */
.button:focus-visible {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

On this page