MeSingleSelect
Select de seleção única com suporte a busca, limpeza, badges e navegação por teclado. Detecta automaticamente o espaço disponível na viewport para abrir para cima ou para baixo.
Playground
Importação
vue
<script>
import { MeSingleSelect } from '@/components/global/utils/export/index'
</script>Uso Básico
Selecione
vue
<script setup>
import { ref } from 'vue'
const value = ref(null)
const options = [
{ text: 'Opção 1', value: 1 },
{ text: 'Opção 2', value: 2 },
{ text: 'Opção 3', value: 3 },
]
</script>
<template>
<MeSingleSelect v-model="value" :options="options" />
</template>Com Label
Use a prop label para exibir um rótulo acima do select.
Selecione
vue
<MeSingleSelect
v-model="value"
label="Categoria"
:options="options"
/>Placeholder
Escolha uma opção...
vue
<MeSingleSelect
v-model="value"
:options="options"
placeholder="Escolha uma opção..."
/>Clearable
Adiciona um botão de limpeza quando há uma opção selecionada. Emite o evento @clear ao limpar.
Opção 2
vue
<MeSingleSelect
v-model="value"
:options="options"
clearable
:show-first-empty-option="false"
@clear="onClear"
/>Searchable
Exibe um campo de busca ao abrir o dropdown. A busca ignora acentos e é case-insensitive.
Buscar estado...
vue
<MeSingleSelect
v-model="value"
:options="states"
searchable
placeholder="Buscar estado..."
/>Disabled
Opção 1
vue
<MeSingleSelect
v-model="value"
:options="options"
disabled
/>Sem Radio Buttons
Use :show-radio-buttons="false" para uma lista mais compacta, sem os marcadores de seleção.
Selecione
Selecione
vue
<!-- Com radio buttons (padrão) -->
<MeSingleSelect v-model="value" :options="options" />
<!-- Sem radio buttons -->
<MeSingleSelect v-model="value" :options="options" :show-radio-buttons="false" />Com Badges
Adicione tag a uma opção para exibir um badge ao lado do texto.
Selecione
vue
<script setup>
const options = [
{ text: 'Ativo', value: 'active', tag: { message: 'Novo', variant: 'green' } },
{ text: 'Pendente', value: 'pending', tag: { message: 'Atenção', variant: 'orange' } },
{ text: 'Inativo', value: 'inactive', tag: { message: 'Inativo', variant: 'gray' } },
]
</script>
<template>
<MeSingleSelect
v-model="value"
:options="options"
:show-first-empty-option="false"
/>
</template>Opções Desabilitadas
Defina disabled: true em uma opção para torná-la não selecionável.
Selecione
vue
<script setup>
const options = [
{ text: 'Disponível', value: 1 },
{ text: 'Indisponível', value: 2, disabled: true },
{ text: 'Disponível 2', value: 3 },
]
</script>
<template>
<MeSingleSelect
v-model="value"
:options="options"
:show-first-empty-option="false"
/>
</template>initSelected
Use :init-selected="true" para pré-selecionar automaticamente a primeira opção válida quando v-model começa como null.
vue
<script setup>
import { ref } from 'vue'
// value inicia como null, mas o componente auto-seleciona a primeira opção
const value = ref(null)
const options = [
{ text: 'Opção 1', value: 1 },
{ text: 'Opção 2', value: 2 },
]
</script>
<template>
<MeSingleSelect
v-model="value"
:options="options"
:init-selected="true"
:show-first-empty-option="false"
/>
</template>Eventos
Selecione
Último evento: Nenhum
vue
<script setup>
import { ref } from 'vue'
const value = ref(null)
const lastEvent = ref('Nenhum')
</script>
<template>
<MeSingleSelect
v-model="value"
:options="options"
@change="(opt) => lastEvent = `change: ${opt?.text}`"
@open="lastEvent = 'open'"
@close="lastEvent = 'close'"
@clear="lastEvent = 'clear'"
/>
<p>Último evento: <strong>{{ lastEvent }}</strong></p>
</template>API
Props
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
modelValue | string | number | object | null | null | Valor selecionado — use com v-model |
options | OptionSingleSelectType[] | [] | Lista de opções disponíveis |
placeholder | string | 'Selecione' | Texto exibido quando nenhuma opção está selecionada |
label | string | undefined | Texto do label exibido acima do select |
disabled | boolean | false | Desabilita o select |
searchable | boolean | false | Habilita campo de busca/filtro nas opções |
clearable | boolean | false | Exibe botão para limpar a seleção |
showFirstEmptyOption | boolean | true | Exibe uma primeira opção vazia ("Selecione") |
initSelected | boolean | false | Inicializa com a primeira opção válida selecionada |
showRadioButtons | boolean | true | Exibe radio buttons ao lado das opções |
openDirection | 'down' | 'up' | 'down' | Direção de abertura do dropdown |
Tipo das Opções
typescript
type OptionSingleSelectType = {
text: string // Texto exibido na lista
value: string | number | null // Valor emitido no v-model
disabled?: boolean // Desabilita a opção
params?: unknown // Dados extras opcionais
tag?: { // Badge ao lado do texto
message: string
variant: string // 'green' | 'orange' | 'gray' | ...
}
}Eventos
| Evento | Payload | Descrição |
|---|---|---|
update:modelValue | string | number | object | null | Emitido ao selecionar — use com v-model |
change | OptionSingleSelectType | null | Emitido ao selecionar (objeto completo da opção) |
clear | — | Emitido ao limpar a seleção via botão clearable |
open | — | Emitido ao abrir o dropdown |
close | — | Emitido ao fechar o dropdown |
focus | — | Emitido ao focar o componente |
blur | — | Emitido ao perder o foco |
inputChange | string | null | Emitido ao digitar no campo de busca (searchable) |
Acessibilidade
- Implementa o padrão WAI-ARIA Combobox com
role="combobox",role="listbox"erole="option" aria-expandedreflete o estado do dropdownaria-activedescendantaponta para o item com foco no teclado- Opções desabilitadas têm
aria-disabled="true"
Navegação por Teclado
| Tecla | Ação |
|---|---|
Enter / Space | Abre/fecha o dropdown ou seleciona o item focado |
ArrowDown | Move o foco para a próxima opção (pula desabilitadas) |
ArrowUp | Move o foco para a opção anterior (pula desabilitadas) |
Escape | Fecha o dropdown e devolve o foco ao trigger |
Tab | Fecha o dropdown e avança o foco |
Posicionamento inteligente
O MeSingleSelect detecta automaticamente o espaço disponível na viewport e abre para cima quando não há espaço suficiente abaixo. Use :open-direction="'up'" para forçar sempre para cima.