---
title: "FlatSelect"
description: "A dropdown whose options expand over the trigger from the selected item."
category: Form
status: beta
since: 0.3.4
tags: [select, flat, form, combobox]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
:::TuffDemoWrapper{demo="FlatSelectBasicDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'

  const value = ref('json')
  </script>

  <template>
    <TxFlatSelect v-model="value" placeholder="Select format">
      <TxFlatSelectItem value="json" label="JSON" />
      <TxFlatSelectItem value="csv" label="CSV" />
      <TxFlatSelectItem value="xml" label="XML" />
    </TxFlatSelect>
  </template>
---
:::

### Disabled
Set `disabled` on the whole group or on single items.
:::TuffDemoWrapper{demo="FlatSelectDisabledDemo" code-lang="vue"}
---
code: |
  <template>
    <TxFlatSelect v-model="value" placeholder="Select" disabled>
      <TxFlatSelectItem value="a" label="Option A" />
      <TxFlatSelectItem value="b" label="Option B" />
    </TxFlatSelect>

    <TxFlatSelect v-model="value" placeholder="Select">
      <TxFlatSelectItem value="a" label="Option A" />
      <TxFlatSelectItem value="b" label="Option B" disabled />
      <TxFlatSelectItem value="c" label="Option C" />
    </TxFlatSelect>
  </template>
---
:::

### Release Policy
An admin flow: Cascader sets the scope, FlatSelect the policy, sliders the thresholds, and TagInput the labels.
::TuffDemoWrapper{demo="ComponentsReleasePolicyDemo" code-lang="vue"}
---
code: |
  <template>
    <TxCascader v-model="releasePath" :options="scopeOptions" placeholder="Release scope" />
    <TxFlatSelect v-model="packageFormat" placeholder="Package format">
      <TxFlatSelectItem value="signed" label="Signed build" />
      <TxFlatSelectItem value="archive" label="Archive" />
    </TxFlatSelect>
    <TxFlatSelect v-model="rolloutMode" placeholder="Rollout mode">
      <TxFlatSelectItem value="phased" label="Phased" />
      <TxFlatSelectItem value="guarded" label="Guarded" />
    </TxFlatSelect>
    <TxSegmentedSlider v-model="riskLevel" :segments="riskSegments" />
    <TxSlider v-model="traffic" :min="5" :max="100" :step="5" show-value />
    <TxTagInput v-model="labels" placeholder="Press Enter to add tags" :max="5" />
  </template>
---
::

### Best Practices

- Use for three to six short, stable options; use `TxSelect` for search, remote data, grouping, or virtualization.
- Keep labels short: the trigger and the items both truncate to one line.
- Keep each `value` stable and unique: the parent matches selection and keyboard order by `value`.
- Don't put interactive controls inside `TxFlatSelectItem`; the item is already a button with `role="option"`.
- Mark unavailable options `disabled` instead of filtering them out.

## API Reference

### TxFlatSelect

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `modelValue` / `v-model` | `string \| number` | `''` | The selected value, matching one item's `value`; shows the placeholder when nothing matches. |
| `placeholder` | `string` | `''` | Trigger text while nothing is selected. |
| `disabled` | `boolean` | `false` | Disables the group: the trigger can't be clicked and the dropdown won't open. |

#### Events

| Event | Params | Description |
|-------|--------|-------------|
| `update:modelValue` | `(value: string \| number) => void` | Fires on every commit, including ArrowUp/ArrowDown navigation. |
| `change` | `(value: string \| number) => void` | Fires together with `update:modelValue`. |

#### Slots

| Slot | Description |
|------|-------------|
| `default` | `TxFlatSelectItem` children. |

### TxFlatSelectItem

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | `string \| number` | - | The option value; keep it stable and unique. |
| `label` | `string` | - | Text shown in the trigger and the option. |
| `disabled` | `boolean` | `false` | Makes the option unselectable and skipped by the keyboard. |

#### Slots

| Slot | Description |
|------|-------------|
| `default` | Custom content, replacing `label`. |

## Comparison with TxSelect

| Feature | TxSelect | TxFlatSelect |
|---------|----------|-------------|
| Positioning | floating-ui, teleported to body | CSS absolute + clip-path |
| Expansion | Panel appears below the trigger | Options overlay the trigger, expanding from the selected item |
| Animation | None (avoids scroll lag) | clip-path expand / collapse |
| Search | Supported | Not supported |
| Use case | General and complex forms | Settings pages, simple dropdowns |
| Trigger | Input-style | Button-style with arrow |

## Overview

- The trigger is `role="combobox"`, the panel `role="listbox"`, and each item a `role="option"` with `aria-selected`.
- Options overlay the trigger, with the selected item anchored at the trigger's position.
- While open, ArrowUp / ArrowDown move and commit immediately, skipping disabled items.
- Closing collapses the panel onto the trigger and fades its surface, border, shadow, and selected accent over the same 200ms.

## Technologies

- Source: `packages/tuffex/packages/components/src/flat-select/`.

<TuffDocSourceLink />
