BaseSelect

A native <select>, wearing the kit's field.

Import it from rei-kit: import { BaseSelect } from 'rei-kit'

Open BaseSelect in the live documentation, where every prop below is a control you can change, in four materials and ten palettes.

Usage

<script setup lang="ts">
import { ref } from 'vue'
import { BaseSelect } from 'rei-kit'

const currency = ref()
const options = [
  { value: 'TRY', label: 'Turkish lira' },
  { value: 'JPY', label: 'Japanese yen' },
]
</script>

<template>
  <BaseSelect v-model="currency" label="Currency" :options="options" placeholder="Choose one" />
</template>

Props

Props
PropTypeRequired or defaultWhat it is for
labelstringyes
optionsreadonly { value: T; label: string; disabled?: boolean | undefined }[]yes
errorstring''
hintstring''
labelHiddenbooleanfalse
placeholderstring''An unselectable first row, for a field with no sensible default. Disabled rather than merely empty: an empty option that can be chosen lets someone go back to having answered nothing, which no form wants.
size'sm' | 'md''md'`sm` for a select that filters or sorts rather than answers a form. Every hand-written select across the three consuming apps was this one.
variant'default' | 'unstyled''default'`unstyled` keeps the wiring and drops the surface. The label, the generated id, `aria-describedby` and the error are what a field is; the border and the height are what it looks like. A search box inside a bordered row, a url field in an editor popover — those places were hand-writing the whole thing to avoid the appearance, and losing the wiring with it. The same reasoning as `BaseButton`'s `unstyled`, and the same test: a primitive is finished when the app can take its behaviour without its paint.
fieldIdstringundefinedTies the generated id to a name you choose, so `ErrorSummary` can link to this field. Its links point at nothing without it, and the kit's own `FormField` has taken one since 2.22.0 while the fields built on it did not — which left building a form out of these and summarising its errors impossible without hand-writing the control.
controlClassstringundefinedClasses for the control itself, rather than for the field around it. `class` lands on the field, because that is where Vue puts a component's class and because a layout class means "space this field". That leaves `variant="unstyled"` with no way to paint the control it just stripped — the point of stripping it — which is why an app with a large amount field wrote the whole thing by hand instead. It appends, so with the default variant a conflict is settled by Tailwind's own order rather than by writing it here; reach for it with `unstyled`, where there is nothing to settle.

About rei-kit

rei-kit is an accessible Vue 3 and Tailwind CSS 4 component library: 106 components, themed by role rather than by colour on three independent axes — ten WCAG-checked palettes, four materials and light or dark, each switched with one attribute. Typed, tested, SSR-safe, no runtime dependencies, MIT.

pnpm add rei-kit · npm · GitHub