Select

A labelled single-choice list that opens in a popup.

Roast
import { Select } from '@brand-studio/ui';

const roasts = [
  { value: 'light', label: 'Light roast' },
  { value: 'medium', label: 'Medium roast' },
  { value: 'dark', label: 'Dark roast' },
  { value: 'decaf', label: 'Decaf', disabled: true },
];

export default function SelectDemo() {
  return (
    <div style={{ width: '100%', maxWidth: 280 }}>
      <Select label="Roast" options={roasts} placeholder="Choose a roast" />
    </div>
  );
}

Installation

pnpm add @brand-studio/ui

Usage

import { Select } from '@brand-studio/ui';
<Select
  label="Roast"
  options={[
    { value: 'light', label: 'Light roast' },
    { value: 'dark', label: 'Dark roast' },
  ]}
/>

Examples

Controlled

Pass value and onValueChange to own the state.

Bag size

Selected: 500 g

'use client';

import { useState } from 'react';
import { Select } from '@brand-studio/ui';

const sizes = [
  { value: '250', label: '250 g' },
  { value: '500', label: '500 g' },
  { value: '1000', label: '1 kg' },
];

export default function SelectControlled() {
  const [size, setSize] = useState('500');
  return (
    <div style={{ width: '100%', maxWidth: 280, display: 'grid', gap: 12 }}>
      <Select label="Bag size" options={sizes} value={size} onValueChange={setSize} />
      <p style={{ margin: 0, color: 'var(--bs-muted)' }}>Selected: {size} g</p>
    </div>
  );
}

Accessibility

  • Opens with Enter, Space or the arrow keys. Typing a letter jumps to the matching option.
  • Escape closes the list and returns focus to the trigger.
  • Disabled options stay visible and are skipped by the keyboard.

API Reference

PropTypeDefault
labelstring
optionsSelectOption[]
placeholder?string'Select…'
defaultValue?string
value?string
onValueChange?((value: string) => void)
name?string
disabled?boolean
className?string''

Still, Deskhand and Hollis are fictional brands. The coffee photographs are original generated artwork. @brand-studio/ui is MIT licensed.