Select
Lista de seleção com trigger custom, listbox flutuante e suporte a teclado.
-
SUS
-
Amil
-
Bradesco Saúde
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
export function SelectExample() {
return (
<Select>
<SelectTrigger className="w-[240px]">
<SelectValue placeholder="Selecione o convênio" />
</SelectTrigger>
<SelectContent>
<SelectItem value="sus">SUS</SelectItem>
<SelectItem value="amil">Amil</SelectItem>
<SelectItem value="bradesco">Bradesco Saúde</SelectItem>
</SelectContent>
</Select>
)
} <script setup lang="ts">
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
</script>
<template>
<Select>
<SelectTrigger class="w-[240px]">
<SelectValue placeholder="Selecione o convênio" />
</SelectTrigger>
<SelectContent>
<SelectItem value="sus">SUS</SelectItem>
<SelectItem value="amil">Amil</SelectItem>
<SelectItem value="bradesco">Bradesco Saúde</SelectItem>
</SelectContent>
</Select>
</template> <div class="itps-select" data-itps-select data-state="closed">
<button
type="button"
id="select-convenio"
role="combobox"
aria-haspopup="listbox"
aria-expanded="false"
aria-controls="select-convenio-listbox"
class="itps-select__trigger"
data-itps-select-trigger
>
<span class="itps-select__value" data-itps-select-value data-placeholder="true">
Selecione o convênio
</span>
<i class="itps-select__chevron ti ti-chevron-down" aria-hidden="true"></i>
</button>
<input type="hidden" name="convenio" value="" class="itps-select__input" data-itps-select-input />
<ul
id="select-convenio-listbox"
role="listbox"
aria-labelledby="select-convenio"
class="itps-select__panel"
data-itps-select-panel
>
<li
id="select-convenio-listbox-option-0"
role="option"
data-value="sus"
data-itps-select-option
aria-selected="false"
tabindex="-1"
class="itps-select__option"
>
<div class="itps-select__option-content">
<span class="itps-select__option-label" data-itps-select-option-label>SUS</span>
</div>
</li>
<li
id="select-convenio-listbox-option-1"
role="option"
data-value="amil"
data-itps-select-option
aria-selected="false"
tabindex="-1"
class="itps-select__option"
>
<div class="itps-select__option-content">
<span class="itps-select__option-label" data-itps-select-option-label>Amil</span>
</div>
</li>
<li
id="select-convenio-listbox-option-2"
role="option"
data-value="bradesco"
data-itps-select-option
aria-selected="false"
tabindex="-1"
class="itps-select__option"
>
<div class="itps-select__option-content">
<span class="itps-select__option-label" data-itps-select-option-label>Bradesco Saúde</span>
</div>
</li>
</ul>
</div> Instalação
Instale o Select da sua stack e rode o comando individual ITpS em seguida. O comando itps add select é theme-only: ele valida o slug e confirma que o contrato visual vem do tema ITpS, das classes copy-first e dos snippets desta página.
terminal · React/Next
pnpm dlx shadcn@latest add select
pnpm dlx github:ITPS/sinapse-ui-cli add select terminal · Vue3/Nuxt4
pnpm dlx shadcn-vue@latest add select
pnpm dlx github:ITPS/sinapse-ui-cli add select O comando individual adapta só este componente; não instala o catálogo inteiro.
Uso
Em React/Next com shadcn/ui e Vue3/Nuxt4 com shadcn-vue, use o Select composto da stack. O tema ITpS vem dos tokens aplicados pela CLI, então o exemplo deve seguir a API oficial de compound components.
Use itps-select quando precisar do contrato copy-first em HTML ou wrappers finos. No site, src/scripts/forms.ts inicializa os elementos com data-itps-select*; em produto, mantenha o mesmo contrato ou use o componente da sua stack.
Exemplos
Opções
| Necessidade | React/Next e Vue3/Nuxt4 | HTML |
|---|---|---|
| Placeholder | SelectValue placeholder="..." | itps-select__value[data-placeholder="true"] |
| Opção simples | SelectItem value="sus" | li[role="option"][data-value="sus"] |
| Opção com descrição | componha conteúdo dentro de SelectItem quando a stack permitir | itps-select__option-description |
| Valor enviado | estado controlado ou formulário da stack | input[type="hidden"][data-itps-select-input] |
Sizes e estados
| Estado | React/Next e Vue3/Nuxt4 | HTML |
|---|---|---|
| Pequeno | ajuste no SelectTrigger instalado | itps-select--sm |
| Padrão | default do componente | sem modificador |
| Grande | ajuste no SelectTrigger instalado | itps-select--lg |
| Desabilitado | disabled | disabled no trigger |
| Inválido | aria-invalid="true" | aria-invalid="true" no trigger |
Conecte textos de apoio ou erro com aria-describedby. Para valor controlado em React/Vue, siga o estado da stack em vez de copiar o JS do exemplo.
Com Field
Quando houver label, obrigatório, apoio ou erro, componha com Field e conecte o texto auxiliar ao trigger.
-
SUS Atendimento público
-
Particular Pagamento direto
Obrigatório para confirmar o cadastro.
<div class="itps-field">
<label for="select-field-convenio" class="itps-field__label">
Convênio
<span class="itps-field__required" aria-hidden="true">*</span>
</label>
<div class="itps-select" data-itps-select data-state="closed">
<button
type="button"
id="select-field-convenio"
role="combobox"
aria-haspopup="listbox"
aria-expanded="false"
aria-controls="select-field-convenio-listbox"
aria-required="true"
aria-describedby="select-field-convenio-help"
class="itps-select__trigger"
data-itps-select-trigger
>
<span class="itps-select__value" data-itps-select-value data-placeholder="true">
Selecione
</span>
<i class="itps-select__chevron ti ti-chevron-down" aria-hidden="true"></i>
</button>
<input type="hidden" name="field-convenio" value="" class="itps-select__input" data-itps-select-input />
<ul
id="select-field-convenio-listbox"
role="listbox"
aria-labelledby="select-field-convenio"
class="itps-select__panel"
data-itps-select-panel
>
<li
id="select-field-convenio-listbox-option-0"
role="option"
data-value="sus"
data-itps-select-option
aria-selected="false"
tabindex="-1"
class="itps-select__option"
>
<div class="itps-select__option-content">
<span class="itps-select__option-label" data-itps-select-option-label>SUS</span>
<span class="itps-select__option-description">Atendimento público</span>
</div>
</li>
<li
id="select-field-convenio-listbox-option-1"
role="option"
data-value="particular"
data-itps-select-option
aria-selected="false"
tabindex="-1"
class="itps-select__option"
>
<div class="itps-select__option-content">
<span class="itps-select__option-label" data-itps-select-option-label>Particular</span>
<span class="itps-select__option-description">Pagamento direto</span>
</div>
</li>
</ul>
</div>
<p id="select-field-convenio-help" class="itps-field__hint">
Obrigatório para confirmar o cadastro.
</p>
</div> API copy-first
| Classe/atributo | Uso |
|---|---|
itps-select | Wrapper visual e raiz de estado. |
data-itps-select | Marca a raiz inicializável pelo script. |
itps-select__trigger | Botão com role="combobox". |
data-itps-select-trigger | Elemento que abre e fecha o painel. |
itps-select__value | Texto visível ou placeholder. |
data-itps-select-value | Elemento atualizado ao selecionar opção. |
itps-select__input | Input hidden que envia o valor no formulário. |
data-itps-select-input | Input sincronizado pelo script. |
itps-select__panel | Painel com role="listbox". |
data-itps-select-panel | Lista usada para navegação por teclado. |
itps-select__option | Item com role="option". |
data-itps-select-option | Opção selecionável pelo script. |
data-state | Expõe estado visual aberto ou fechado. |
aria-expanded | Comunica se o painel está aberto. |
aria-selected | Comunica a opção selecionada. |
aria-describedby | Liga o trigger ao texto de apoio ou erro. |
Acessibilidade
Use role="combobox" no trigger, role="listbox" no painel e role="option" em cada item. Atualize aria-expanded no trigger e aria-selected na opção selecionada. O teclado esperado é: Enter, Space ou ArrowDown abre; ArrowUp/ArrowDown navegam; Home/End vão aos extremos; Enter/Space seleciona; Escape fecha; Tab segue o fluxo.