Select

One choice from a short, known list (dropdown). Under a mouse and the keys it opens the Combobox's list; under a finger the system's picker, a wheel on the phone.

import { Select } from "@umriss-ui/core";

The field is a native <select>: it holds the value and the form, and onChange fires as it always did. Write the choices as <option> and <optgroup>; the list is drawn from them.

An option with the empty value is the placeholder: muted in the field, and never marked as the choice in the list.

Examples

Select

Write the choices as native option elements; a disabled empty option stands in for the placeholder.

import { useState } from "react";
import { FormField, Select } from "@umriss-ui/core";

export default function SelectExample() {
  const [centre, setCentre] = useState("");

  return (
    <FormField label="Cost centre" style={{ maxWidth: 320 }}>
      <Select value={centre} onChange={(event) => setCentre(event.target.value)}>
        <option value="" disabled>
          Choose a cost centre
        </option>
        <option value="CC-1100">CC-1100 Sales</option>
        <option value="CC-1200">CC-1200 Marketing</option>
        <option value="CC-2100">CC-2100 Engineering</option>
        <option value="CC-2200">CC-2200 Design</option>
        <option value="CC-3100">CC-3100 Customer service</option>
      </Select>
    </FormField>
  );
}

States

size="sm" suits dense forms; errors come from the FormField, and a long option is cut at the field's edge.

import { FormField, Grid, Select } from "@umriss-ui/core";

export default function States() {
  return (
    <Grid minItemWidth="220px" gap={4}>
      <FormField label="Month" hint="Small size.">
        <Select size="sm" defaultValue="2026-03">
          <option value="2026-01">January 2026</option>
          <option value="2026-02">February 2026</option>
          <option value="2026-03">March 2026</option>
        </Select>
      </FormField>
      <FormField label="VAT rate" error="Invoices from abroad are booked with reverse charge.">
        <Select defaultValue="19">
          <option value="19">19 %</option>
          <option value="7">7 %</option>
          <option value="0">Reverse charge</option>
        </Select>
      </FormField>
      <FormField label="Approver" hint="Set by the cost centre.">
        <Select disabled defaultValue="rafael">
          <option value="rafael">Rafael Ortiz</option>
        </Select>
      </FormField>
      <FormField label="Booking text">
        <Select defaultValue="long">
          <option value="long">Accrual for the annual audit fee, split over twelve months and released in December</option>
          <option value="short">Audit fee</option>
        </Select>
      </FormField>
    </Grid>
  );
}

With an error

A FormField with an error marks the field invalid by itself. Without one, set invalid and tie your message to the field with aria-describedby.

import { useId, useState } from "react";
import { Select, Stack, Text } from "@umriss-ui/core";

export default function WithAnError() {
  /* The supplier invoices from Austria, so only reverse charge is right. */
  const [rate, setRate] = useState("19");
  const messageId = useId();
  const error = rate === "0" ? undefined : "Invoices from abroad are booked with reverse charge.";

  return (
    <Stack gap={1} style={{ maxWidth: 360 }}>
      <Select
        aria-label="VAT rate, Alpenholz GmbH (Austria)"
        value={rate}
        onChange={(event) => setRate(event.target.value)}
        invalid={error !== undefined}
        aria-describedby={error ? messageId : undefined}
      >
        <option value="19">19 %</option>
        <option value="7">7 %</option>
        <option value="0">Reverse charge</option>
      </Select>
      {error && (
        <Text id={messageId} size="xs" style={{ color: "var(--u-color-danger-text)" }}>
          {error}
        </Text>
      )}
    </Stack>
  );
}

Clear the choice

For an optional choice set clearable with onClear; the cross appears once something is chosen.

import { useState } from "react";
import { FormField, Select, Stack, Text } from "@umriss-ui/core";

export default function ClearTheChoice() {
  const [owner, setOwner] = useState("helen");

  return (
    <Stack gap={3} style={{ maxWidth: 320 }}>
      <FormField label="Filter by budget owner">
        <Select clearable value={owner} onChange={(event) => setOwner(event.target.value)} onClear={() => setOwner("")}>
          <option value="" disabled>
            All owners
          </option>
          <option value="helen">Helen Marsh</option>
          <option value="rafael">Rafael Ortiz</option>
          <option value="anika">Anika Sørensen</option>
        </Select>
      </FormField>
      <Text size="xs" tone="muted" mono>
        value: "{owner}"
      </Text>
    </Stack>
  );
}

When to use something else

Keyboard

Key Action
Arrow Down / Arrow Up, Space, Alt + Arrow, F4 Opens the list on the chosen option. Enter in a closed field is passed on, to a form or a grid.
Arrow Up / Arrow Down, Home / End, Page Up / Page Down Moves in the open list.
Typing a letter Jumps to the next option starting with it; in a closed field it changes the choice.
Enter or Space Chooses the option the list stands on.
Escape or Tab Closes the list.

API

SelectProps

NameTypeDefaultDescription
size"sm" | "md"the size of a ControlSizeProvider around it, else "md"sm for a toolbar and dense forms, md otherwise.

Shown in: Configurator, States, Build a filter bar (Tag) and 1 more

charsnumber—The width in characters - room for the chosen option; the field adds its own padding, chevron and cross. Given, the field is that wide wherever it stands, and never wider than its place. Without it the field fills its place, and is 20 characters wide where the place asks - never as wide as its longest option.

Shown in: Configurator, A row of fields (Sizes)

invalidboolean—Marks the field as invalid. FormField sets it itself as soon as it carries an error – by hand only necessary without FormField.

Shown in: Configurator, With an error

clearablebooleanfalseShows a × once a selection has been made, which fades in on hover/focus and empties the selection. Requires a controlled field (value) and onClear; sensible for optional selects with a placeholder option.

Shown in: Clear the choice

refRef<HTMLSelectElement>—Receives the component's root element. from RefProp

Shown in: A row that holds still (Sizes), An anchored surface (Popover), Take the width of the trigger (Popover) and 2 more

Events

NameTypeDefaultDescription
onClear() => void—Called by the ×; resets the selection to the placeholder option.

Shown in: Clear the choice

Also takes every attribute of <select> – without size.

Known limits

What umriss deliberately does not build, and why: ADR-0032.

Every page of @umriss-ui/core

Getting started

Customising

Layout

Typography

Actions

Forms

Choosing

Dates and times

Feedback

Overlays

Navigation

Data display

API index