Skip to content

I9kSelect ​

Native single-select dropdown that auto-selects the option matching modelValue. Wires its own id and ARIA attributes standalone, and inherits id, size, and error state from a wrapping I9kField when there is one.

View as MarkdownView source
ts
import { I9kSelect } from '@9klabs/design';

Examples ​

Inside I9kField ​

vue
<I9kField label="Service">
  <I9kSelect v-model="service">
    <option value="">Choose a service</option>
    <option value="audit">Technical audit</option>
    <option value="design">Design system</option>
    <option value="development">Development</option>
  </I9kSelect>
</I9kField>

Sizes ​

vue
<I9kField label="Small" size="sm">
  <I9kSelect v-model="a"><option value="audit">Technical audit</option></I9kSelect>
</I9kField>
<I9kField label="Medium" size="md">
  <I9kSelect v-model="b"><option value="audit">Technical audit</option></I9kSelect>
</I9kField>
<I9kField label="Large" size="lg">
  <I9kSelect v-model="c"><option value="audit">Technical audit</option></I9kSelect>
</I9kField>

Error state ​

vue
<I9kField label="Service" error="Select the service you need.">
  <I9kSelect v-model="service">
    <option value="">Choose a service</option>
    <option value="audit">Technical audit</option>
  </I9kSelect>
</I9kField>

Watch out ​

  • The visual scale prop is uiSize, not size; the native size and multiple attributes are stripped and logged as a dev warning.
  • Pass plain <option>/<optgroup> children without a selected attribute — I9kSelect sets it based on modelValue matching the option's value or text.
  • Inside an I9kField, do not pass id, aria-invalid, or aria-describedby — the field supplies them.

API ​

Props ​

PropTypeDefaultRequired
modelValuestring—yes
uiSize'sm' | 'md' | 'lg'—no

Emits ​

EventPayload
update:modelValue[value: string]

Agent prompt ​

Paste this into an agent to have it use the component correctly. It is self-contained.

text
Use I9kSelect from @9klabs/design for a single-choice dropdown, typically inside an I9kField.

import { I9kSelect } from '@9klabs/design';

Props:
- modelValue: string (required) — the v-model target, matched against each child <option>'s value (or its text content if it has no value attribute).
- uiSize?: 'sm' | 'md' | 'lg' — falls back to a wrapping I9kField's size, then to 'md'.

Emits: update:modelValue with the new string.

Slots:
- default — plain <option> and <optgroup> elements. I9kSelect clones them and sets `selected` on the one matching modelValue; do not set `selected` yourself.

Behavior: inside an I9kField, I9kSelect calls useI9kField() and takes its id, described-by ids, invalid state, required state, and size from that context automatically. Standalone, it generates its own id and expects an accessible name via aria-label or aria-labelledby — omitting both triggers a dev-mode console warning. This is a native single-select only: the `multiple` and `size` HTML attributes are stripped and log a dev-mode warning if passed.

IMPORTANT: the visual scale prop is `uiSize`, not `size` — passing the native `size` attribute is rejected with a dev warning. IMPORTANT: inside I9kField, do not pass id, aria-invalid, or aria-describedby — I9kField supplies them.

Usage:
<I9kField label="Service"><I9kSelect v-model="service"><option value="">Choose one</option><option value="audit">Technical audit</option></I9kSelect></I9kField>

Made with love 💚, caffeine, and Claude Code. Built with @9klabs/design itself.