Select

Displays a list of options for the user to pick from—triggered by a button. Replicates the core capabilities of the shadcn-vue Select component, supporting single selection, multiple selection, search, grouping, and other functions. Based on BrConfigProvider for global theme configuration.

Component Features

  • Single & Multiple Selection: Supports both single and multiple selection modes.
  • 🔍 Search Support: Supports local and remote search filtering.
  • 📦 Grouping Support: Supports option grouping via BrSelectGroup.
  • Clearable: Supports clearable prop to clear selection.
  • 📏 Multiple Sizes: Supports sm, md, lg size specs.
  • ⚠️ Error State: Supports error prop to display error state.
  • 🎨 Theme Customization: Based on BrConfigProvider for global theming and TailwindCSS local overrides.

Basic

The most basic single selection mode, supports custom placeholder.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref('apple')
const options = [
  { label: 'Apple', value: 'apple' },
  { label: 'Banana', value: 'banana' },
  { label: 'Orange', value: 'orange' },
  { label: 'Blueberry', value: 'blueberry' },
  { label: 'Grapes', value: 'grapes' },
  { label: 'Pineapple', value: 'pineapple' },
]
</script>

<template>
  <div class="flex flex-col gap-4 w-[280px]">
    <BrSelect 
      v-model="value" 
      :options="options" 
      placeholder="Select a fruit" 
    />
    <div class="text-sm text-muted-foreground">
      Selected: {{ value }}
    </div>
  </div>
</template>

Grouping

Display options in groups using the group field.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref('')
const options = [
  { label: 'Apple', value: 'apple', group: 'Fruits' },
  { label: 'Banana', value: 'banana', group: 'Fruits' },
  { label: 'Blueberry', value: 'blueberry', group: 'Fruits' },
  { label: 'Carrot', value: 'carrot', group: 'Vegetables' },
  { label: 'Potato', value: 'potato', group: 'Vegetables' },
  { label: 'Broccoli', value: 'broccoli', group: 'Vegetables' },
  { label: 'Beef', value: 'beef', group: 'Meat' },
  { label: 'Chicken', value: 'chicken', group: 'Meat' },
]
</script>

<template>
  <div class="w-[280px]">
    <BrSelect 
      v-model="value" 
      :options="options" 
      placeholder="Select food" 
    />
  </div>
</template>

Enable the filterable prop and listen to the search event to implement remote search. Supports loading state.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref, watch } from 'vue'

const value = ref('')
const loading = ref(false)
const options = ref<{ label: string; value: string }[]>([])

// Simulate remote search
const handleSearch = (query: string) => {
  if (!query) {
    options.value = []
    return
  }
  
  loading.value = true
  // Mock API call
  setTimeout(() => {
    options.value = [
      { label: query + ' Option 1', value: query + '-1' },
      { label: query + ' Option 2', value: query + '-2' },
      { label: query + ' Option 3', value: query + '-3' },
    ]
    loading.value = false
  }, 1000)
}
</script>

<template>
  <div class="w-[280px]">
    <BrSelect 
      v-model="value" 
      :options="options" 
      filterable 
      :loading="loading" 
      placeholder="Type to search..." 
      empty-text="No results found."
      @search="handleSearch"
    />
    <div class="mt-4 text-sm text-muted-foreground">
      Current Value: {{ value }}
    </div>
  </div>
</template>

Multiple Selection & Clearable

Enable the multiple prop to support multiple selection, and clearable for one-click clearing.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref(['react', 'vue'])
const options = [
  { label: 'Vue', value: 'vue' },
  { label: 'React', value: 'react' },
  { label: 'Angular', value: 'angular' },
  { label: 'Svelte', value: 'svelte' },
  { label: 'Solid', value: 'solid' },
]
</script>

<template>
  <div class="flex flex-col gap-4 w-[350px]">
    <BrSelect 
      v-model="value" 
      :options="options" 
      multiple 
      clearable 
      placeholder="Select frameworks" 
    />
    <div class="text-sm text-muted-foreground">
      Selected: {{ value }}
    </div>
  </div>
</template>

Size

Supports default, sm, lg sizes.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref('apple')
const options = [
  { label: 'Apple', value: 'apple' },
  { label: 'Banana', value: 'banana' },
  { label: 'Orange', value: 'orange' },
]
</script>

<template>
  <div class="flex flex-col gap-4 w-full max-w-sm">
    <div class="grid gap-2">
      <label class="text-sm font-medium">Extra Small Size (xs)</label>
      <BrSelect v-model="value" :options="options" size="xs" />
    </div>

    <div class="grid gap-2">
      <label class="text-sm font-medium">Small Size (sm)</label>
      <BrSelect v-model="value" :options="options" size="sm" />
    </div>

    <div class="grid gap-2">
      <label class="text-sm font-medium">Default Size</label>
      <BrSelect v-model="value" :options="options" />
    </div>

    <div class="grid gap-2">
      <label class="text-sm font-medium">Medium Size (md)</label>
      <BrSelect v-model="value" :options="options" size="md" />
    </div>
    
    <div class="grid gap-2">
      <label class="text-sm font-medium">Large Size (lg)</label>
      <BrSelect v-model="value" :options="options" size="lg" />
    </div>

    <div class="grid gap-2">
      <label class="text-sm font-medium">Extra Large Size (xl)</label>
      <BrSelect v-model="value" :options="options" size="xl" />
    </div>

    <div class="grid gap-2">
      <label class="text-sm font-medium">2X Large Size (2xl)</label>
      <BrSelect v-model="value" :options="options" size="2xl" />
    </div>
  </div>
</template>

Status

Supports error state.

<script setup lang="ts">
import { BrSelect } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref('apple')
const options = [
  { label: 'Apple', value: 'apple' },
  { label: 'Banana', value: 'banana' },
  { label: 'Orange', value: 'orange' },
]
</script>

<template>
  <div class="flex flex-col gap-4 w-full max-w-sm">
    <div class="grid gap-2">
      <label class="text-sm font-medium">Error State</label>
      <BrSelect v-model="value" :options="options" error />
    </div>
  </div>
</template>

Theming

The BrSelect component fully follows the theme specifications of BrConfigProvider.

Global Configuration & Local Override

  • Global Configuration: Configure global colors via the theme prop of BrConfigProvider, and the Select component will automatically adapt.
  • Local Override: You can use Tailwind CSS class names to directly override styles.
<script setup lang="ts">
import { BrSelect, BrConfigProvider } from '@breezeui/vue'
import { ref } from 'vue'

const value = ref('light')
const options = [
  { label: 'Light Mode', value: 'light' },
  { label: 'Dark Mode', value: 'dark' },
  { label: 'System', value: 'system' },
]

// Custom theme configuration
const customTheme = {
  background: '222.2 84% 4.9%',
  foreground: '210 40% 98%',
  popover: '222.2 84% 4.9%',
  popoverForeground: '210 40% 98%',
  primary: '210 40% 98%',
  primaryForeground: '222.2 47.4% 11.2%',
  border: '217.2 32.6% 17.5%',
  input: '217.2 32.6% 17.5%',
  ring: '212.7 26.8% 83.9%',
}
</script>

<template>
  <div class="space-y-8">
    <!-- Default Theme -->
    <div class="space-y-2">
      <h3 class="text-sm font-medium">Default Theme</h3>
      <div class="w-[280px]">
        <BrSelect v-model="value" :options="options" />
      </div>
    </div>

    <!-- Custom Dark Theme via ConfigProvider -->
    <div class="space-y-2">
      <h3 class="text-sm font-medium">Custom Dark Theme (via ConfigProvider)</h3>
      <BrConfigProvider :theme="customTheme" class="p-6 rounded-lg border bg-background text-foreground">
        <div class="w-[280px]">
          <BrSelect v-model="value" :options="options" />
        </div>
      </BrConfigProvider>
    </div>
  </div>
</template>

API

Props

PropTypeDefaultDescription
modelValuestring | number | (string | number)[]-Binding value
options(string | number | SelectOption)[][]Options data
placeholderstring'Select an option'Placeholder
disabledbooleanfalseWhether disabled
clearablebooleanfalseWhether clearable
filterablebooleanfalseWhether searchable
multiplebooleanfalseWhether multiple selection
loadingbooleanfalseWhether loading (for remote search)
emptyTextstring'No options found.'Text to display when no options are found
size'default' | 'sm' | 'lg''default'Size
errorbooleanfalseWhether error state

SelectOption Type

interface SelectOption {
  label: string
  value: string | number
  disabled?: boolean
  group?: string
}

Events

NameDescriptionPayload
update:modelValueEmitted when binding value changesvalue: string | number | (string | number)[]
changeEmitted when selected value changesvalue: string | number | (string | number)[]
clearEmitted when clear button is clicked-
searchEmitted when search input changesquery: string