Skip to content

Select ​

Native <select> dropdown with custom styling. Use when the user must choose one value from 5–15 options on limited space.


Demo ​

Basic

With help text

Vælg den region du bor i

With error

Sizes

Grouped options

Disabled

With disabled option


When to use ​

  • User must choose one value from 5–15 mutually exclusive options
  • Limited screen space prevents showing all options as radio buttons
  • Values are predefined and cannot be freely typed

When not to use ​

  • Fewer than 5 options — use radio buttons instead
  • More than 15 options — use a text input with autocomplete/suggestions
  • Multiple selections needed — use checkboxes
  • Navigation between pages — use links or tabs
  • User knows the value by heart (e.g. birth year) — use a text input

Installation ​

bash
pnpm add @grundtone/vue

Usage ​

Basic ​

vue
<script setup>
  import { ref } from 'vue';
  const region = ref('');
  const regions = [
    { value: 'hovedstaden', label: 'Hovedstaden' },
    { value: 'midtjylland', label: 'Midtjylland' },
    { value: 'sjaelland', label: 'Sjælland' },
  ];
</script>

<template>
  <GTSelect v-model="region" label="Region" :options="regions" required />
</template>

Grouped options ​

vue
<template>
  <GTSelect
    label="Land"
    :options="[
      {
        label: 'Norden',
        options: [
          { value: 'dk', label: 'Danmark' },
          { value: 'se', label: 'Sverige' },
        ],
      },
      { value: 'de', label: 'Tyskland' },
    ]"
  />
</template>

With error ​

vue
<template>
  <GTSelect
    :options="regions"
    label="Region"
    error-text="Du skal vælge en region"
    required
  />
</template>

Props ​

PropTypeDefaultDescription
options(SelectOption | SelectOptionGroup)[]requiredFlat or grouped options
modelValuestring—Bound value (v-model)
size'sm' | 'md' | 'lg''md'Size preset (matches GTInput)
placeholderstring'Vælg...'Disabled first option text
labelstring—Visible label above select
helpTextstring—Help text below label
errorTextstring—Error message (replaces helpText)
disabledbooleanfalseDisabled state
requiredbooleanfalseRequired field
optionalLabelstring—Label suffix for optional fields
namestring—HTML name attribute
idstringautoHTML id

SelectOption ​

PropertyTypeDescription
valuestringOption value
labelstringDisplay text
disabledbooleanGreyed out, not selectable

SelectOptionGroup ​

PropertyTypeDescription
labelstringGroup heading
optionsSelectOption[]Options in the group

Events ​

EventPayloadDescription
update:modelValuestringEmitted on selection change

Accessibility ​

  • Native <select> — full keyboard and screen reader support by default
  • <label> linked to select via for/id
  • aria-invalid and aria-describedby for error states
  • aria-required when required
  • Disabled options are greyed out, never removed (preserves spatial consistency)
  • Placeholder is a disabled <option> — not selectable as a value

React Native ​

GTSelect is not available on React Native. Native platforms have their own picker conventions — iOS uses UIPickerView (wheel picker), Android uses Spinner. A custom dropdown would break platform expectations and deliver worse UX than native controls.

For React Native projects, use @react-native-picker/picker directly, which renders the platform-native picker on each OS.


CSS Classes ​

ClassElement
.gt-selectNative <select> element
.gt-select--smSmall size
.gt-select--mdMedium size
.gt-select--lgLarge size
.gt-select--errorError state
.gt-select--placeholderPlaceholder visible

Reuses .input-field, .input-label, .input-help, .input-error from the Input component for form layout consistency.


Design system ​

The CSS-only version of this component is documented in the Design System — Select reference.