Skip to content
Areia
Esc
navigateopen⌘Jpreview
On this page

Select

Displays a native list of options for the user to pick from.

Source Code

Areia’s Select uses the platform <select> primitive, so it keeps native keyboard, form, and mobile behavior while adding Areia styling and field helpers.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="fruit"
    label="Fruit"
    value="apple"
    items={{
      apple: "Apple",
      banana: "Banana",
      cherry: "Cherry",
    }}
  />
));

Import

import { Select } from "areia";

Usage

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="plan"
    label="Plan"
    placeholder="Choose a plan"
    items={{
      free: "Free",
      pro: "Pro",
      team: "Team",
    }}
  />
));

Examples

Basic

A select with a visible label. When you provide the label prop, the select renders with a field wrapper and label above it.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="basic-fruit"
    label="Fruit"
    value="apple"
    items={{
      apple: "Apple",
      banana: "Banana",
      cherry: "Cherry",
    }}
  />
));

Sizes

Use the size prop to match Input sizing: xs, sm, base, and lg.

import { ilha } from "ilha";
import { Select } from "areia";

const items = {
  apple: "Apple",
  banana: "Banana",
  cherry: "Cherry",
};

export default ilha.render(() => (
  <div class="flex w-full max-w-sm flex-col gap-3">
    <Select
      size="xs"
      aria-label="Extra small select"
      value="apple"
      items={items}
    />
    <Select
      size="sm"
      aria-label="Small select"
      value="apple"
      items={items}
    />
    <Select
      size="base"
      aria-label="Base select"
      value="apple"
      items={items}
    />
    <Select
      size="lg"
      aria-label="Large select"
      value="apple"
      items={items}
    />
  </div>
));

Without Visible Label

When a visible label is not needed, use aria-label for accessibility.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    aria-label="Select fruit"
    value="banana"
    items={{
      apple: "Apple",
      banana: "Banana",
      cherry: "Cherry",
    }}
  />
));

With Description and Error

Select can show description text and validation errors. Error styling is automatically applied when the error prop is truthy.

Choose the category that best matches your report.

Select an issue type before continuing.
import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="issue-type"
    label="Issue type"
    description="Choose the category that best matches your report."
    error="Select an issue type before continuing."
    placeholder="Choose an issue type"
    items={{
      bug: "Bug",
      documentation: "Documentation",
      feature: "Feature",
    }}
  />
));

Placeholder

Use the placeholder prop to render a placeholder option before the selectable items.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="priority"
    label="Priority"
    placeholder="Choose priority"
    items={{
      low: "Low",
      medium: "Medium",
      high: "High",
      critical: "Critical",
    }}
  />
));

Label with Tooltip

Use labelTooltip to add additional context via a native title attribute on the label.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="severity"
    label="Severity"
    labelTooltip="Choose the highest impact level that applies."
    placeholder="Choose severity"
    items={{
      low: "Low",
      medium: "Medium",
      high: "High",
      critical: "Critical",
    }}
  />
));

Disabled

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    label="Fruit"
    disabled
    value="apple"
    items={{
      apple: "Apple",
      banana: "Banana",
      cherry: "Cherry",
    }}
  />
));

Multiple Selection

Enable native multiple selection with the multiple prop. The select becomes a multi-row native control.

Hold Command or Control to select multiple options.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="columns"
    label="Columns"
    multiple
    description="Hold Command or Control to select multiple options."
    items={{
      name: "Name",
      location: "Location",
      size: "Size",
      read: "Read",
      write: "Write",
      createdAt: "Created At",
    }}
  />
));

Disabled Options

Options can be disabled with descriptor objects in the items prop.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="plan-disabled"
    label="Plan"
    value="free"
    items={{
      free: "Free",
      pro: "Pro",
      business: { label: "Business", disabled: true },
      enterprise: { label: "Enterprise", disabled: true },
    }}
  />
));

Options as Children

Use Select.Option when you want explicit control over individual option markup.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="explicit-options"
    label="Fruit"
    placeholder="Choose fruit"
  >
    <Select.Option value="apple" label="Apple" />
    <Select.Option value="banana" label="Banana" />
    <Select.Option value="cherry" label="Cherry" />
  </Select>
));

Grouped Options

Use Select.Group to organize related options under native optgroup labels.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    id="grouped-food"
    label="Food"
    placeholder="Choose food"
  >
    <Select.Group label="Fruits">
      <Select.Option value="apple" label="Apple" />
      <Select.Option value="banana" label="Banana" />
    </Select.Group>
    <Select.Group label="Vegetables">
      <Select.Option value="carrot" label="Carrot" />
      <Select.Option value="lettuce" label="Lettuce" />
    </Select.Group>
  </Select>
));

Ghost Variant

Use variant: "ghost" for compact UIs where the select should blend into the surrounding surface.

import { ilha } from "ilha";
import { Select } from "areia";

export default ilha.render(() => (
  <Select
    variant="ghost"
    aria-label="Sort by"
    value="updated"
    items={{
      updated: "Recently updated",
      created: "Recently created",
      name: "Name",
    }}
  />
));

API Reference

Select

Select accepts standard HTML select attributes plus the following props.

Prop Type Default Description
class string - Additional CSS classes applied to the select.
className string - Alias for class.
size "xs" | "sm" | "base" | "lg" "base" Size of the select. Matches Input component sizes.
variant "default" | "error" | "ghost" "default" Visual variant.
label unknown - Label content for the select. Enables the field wrapper.
placeholder string - Placeholder option shown before selectable items.
items Record<string, SelectItemValue> | Array<{ label: unknown; value: unknown; disabled?: boolean }> - Data structure of items rendered as options.
children unknown - Explicit option markup. Prefer the second Select argument for options.
second argument unknown[] - Option markup, usually Select.Option(...) or Select.Group(...) calls.
description unknown - Helper text displayed below the select.
error unknown | { message: unknown; match?: unknown } - Error message. When truthy, error styling is automatically applied.
disabled boolean - Whether the select is disabled.
required boolean - Whether the select is required. When false, shows optional text.
multiple boolean - Enables native multiple selection.

Select.Root and Select.Static are aliases for the base native select renderer.

Select.Option

Prop Type Default Description
label unknown - Option content.
value unknown - Option value.
disabled boolean - Whether the option cannot be selected.
class string - Additional CSS classes.
className string - Alias for class.

Select.Group

Groups related options together with a native optgroup.

Prop Type Default Description
label string - Visible optgroup label.
second argument unknown[] - Option markup.
disabled boolean - Whether every option in the group is disabled.

Select.Separator

Select.Separator() renders a disabled option that can be used as a simple divider in native selects.

Accessibility

Label Requirement

Selects should have an accessible name via one of:

  • label prop
  • aria-label for selects without a visible label
  • aria-labelledby for custom label association

Native Behavior

Because Select uses the native <select> primitive, it keeps browser-provided keyboard navigation, form submission, and mobile picker behavior.

Error Association

When an id is provided, descriptions and error messages are automatically associated with the select using aria-describedby.

Was this page helpful?