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
modelValuestringBound value (v-model)
size'sm' | 'md' | 'lg''md'Size preset (matches GTInput)
placeholderstring'Vælg...'Disabled first option text
labelstringVisible label above select
helpTextstringHelp text below label
errorTextstringError message (replaces helpText)
disabledbooleanfalseDisabled state
requiredbooleanfalseRequired field
optionalLabelstringLabel suffix for optional fields
namestringHTML 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.