Tema
BaseCombobox
Seleção com busca: a pessoa digita parte do nome e a lista mostra só as opções que combinam. Com multiple, escolhe várias, e cada escolha vira uma etiqueta (BaseTag) que pode ser removida. Dentro de um BaseField, se liga sozinho ao rótulo, à ajuda e ao erro, como o BaseInput e o BaseSelect.
Digite parte do nome para filtrar.
2 selecionadas: Vitória, Serra
Valor do v-model: rui e vitoria, serra.
Uso
- Use quando a lista é longa (mais de 15 opções) ou quando a pessoa já sabe o nome do que procura: fiscal, comarca, empresa. Para até 15 opções sem busca, use
BaseSelect; para 3 ou menos,BaseRadioGroup. - Use
multiplequando a pessoa escolhe várias opções da mesma lista. Para poucas opções múltiplas, todas à vista, prefira um grupo deBaseCheckbox. - A busca ignora maiúsculas e acentos: "joao" encontra "João Mendes", "construcao" encontra "Construção". Ela procura o texto em qualquer parte do nome.
- O
v-modeléstring(ovalueescolhido, ou''quando nada foi escolhido) ou, commultiple,string[]na ordem em que as opções foram escolhidas. - Escolha simples: o campo mostra o nome da opção escolhida. Ao sair do campo, um texto digitado que não virou escolha volta ao nome da opção escolhida. Apagar todo o texto e sair (Tab, clique fora ou Enter) limpa a escolha; Esc cancela a edição e mantém a escolha.
- Escolha múltipla: a lista continua aberta depois de cada escolha, para escolher várias seguidas. Clicar de novo numa opção escolhida a desmarca. Cada etiqueta tem um botão "Remover"; Backspace com o campo vazio remove a última.
placeholderdiz o que buscar: "Busque pelo nome do fiscal". Some quando há escolha.- Opção indisponível fica com
disabled: true: aparece na lista, com texto apagado e o sinal ⊘ à direita, mas não pode ser escolhida. Se ela nunca pode ser escolhida, tire-a da lista. loadingmostra "Carregando opções" enquanto as opções chegam da API.readonlymostra a escolha sem permitir mudar: a lista não abre e as etiquetas não têm botão de remover.- Em formulário nativo,
nameenvia os valores escolhidos, um campo oculto por valor. invalidewarnexigeminvalid-text/warn-textnoBaseField: sem texto, o único sinal visível seria a cor da borda. Fora doBaseField, dê o nome comlabel(lido só pelo leitor de tela) e ligue a mensagem comaria-describedby.
Estados
Marta Coelho já é a gestora deste contrato. Escolha outro fiscal.
Paulo Ramos está de férias até 30/11.
2 selecionadas: Vitória, Serra
Tamanhos
1 selecionada: Vitória
1 selecionada: Vitória
1 selecionada: Vitória
Estilo
| Propriedade | Token |
|---|---|
| Fundo do campo | --tj-field-01; desabilitado e somente leitura --tj-field-disabled |
| Borda do campo | --tj-border-strong-01, hover --tj-border-strong-02, foco --tj-border-interactive; somente leitura tracejada |
| Foco do campo | --tj-ring; com erro ou aviso, também um contorno sólido de 2 px na cor do estado (--tj-support-error-text, --tj-support-warning-text), halo --tj-ring-danger no erro |
| Erro e aviso | --tj-support-error-text e --tj-support-warning-text (borda) |
| Altura | --tj-control-sm/md/lg por linha; o campo cresce quando as etiquetas ocupam mais de uma linha |
| Lista | fundo --tj-layer-01, borda --tj-border-subtle-02, sombra --tj-shadow-2, raio --tj-radius-md; rola depois de 6 opções |
| Opção | texto --tj-text-primary, hover --tj-layer-hover-01, escolhida --tj-layer-selected-01 com marca --tj-icon-interactive |
| Opção ativa (teclado) | contorno de 2 px --tj-border-interactive |
| Opção indisponível | texto --tj-text-placeholder, sinal ⊘ --tj-icon-secondary |
Caixa de marcar (multiple) | borda --tj-border-strong-02; marcada --tj-interactive |
| Lista vazia e carregando | --tj-text-helper; indicador --tj-interactive |
| Movimento | lista entra em --tj-duration-fast-02 com --tj-easing-entrance; a seta gira em --tj-duration-moderate-01 |
Código
vue
<BaseField label="Fiscal designado" :invalid="erro" invalid-text="Escolha outro fiscal" required>
<BaseCombobox v-model="contrato.fiscal" :options="fiscais" placeholder="Busque pelo nome do fiscal" />
</BaseField>
<BaseField label="Comarcas atendidas">
<BaseCombobox v-model="contrato.comarcas" :options="comarcas" multiple name="comarcas" />
</BaseField>| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
v-model | string | string[] | '' | Valor escolhido; com multiple, a lista dos valores |
options | ComboboxOption[] | [] | { value: string, label: string, disabled?: boolean }, o mesmo formato de SelectOption: a mesma lista serve ao BaseSelect |
multiple | boolean | — | Várias escolhas, mostradas como etiquetas removíveis |
label | string | — | Nome lido pelo leitor de tela; obrigatório fora de um BaseField |
placeholder | string | — | Texto enquanto nada foi escolhido |
size | 'sm' | 'md' | 'lg' | 'md' | Altura |
loading | boolean | — | A lista diz "Carregando opções" em vez de mostrar as opções |
empty-text | string | 'Nenhuma opção encontrada' | Texto quando a busca não encontra nada |
name | string | — | Envia os valores num formulário nativo |
disabled, readonly, required, invalid | boolean | — | Estados; dentro do BaseField, também valem required, invalid e warn do campo |
| Evento | Carga | Quando |
|---|---|---|
update:modelValue | string | string[] | A pessoa escolhe, desmarca ou remove uma opção, ou apaga o texto da escolha simples |
Outros atributos (aria-label, aria-labelledby, aria-describedby, autocomplete, ouvintes) vão para o campo de texto; class e style vão para o contêiner, para a lista acompanhar a largura do campo.
Acessibilidade
- Segue o padrão combobox com lista do WAI-ARIA APG: o campo tem
role="combobox",aria-autocomplete="list",aria-expandedearia-controlsapontando para a lista (role="listbox"). A lista tem o mesmo nome do campo (o rótulo, oaria-labelledbyou oaria-labeldado a ele) e, commultiple,aria-multiselectable="true". - O foco fica sempre no campo de texto. A opção ativa é indicada por
aria-activedescendante desenhada com um contorno de 2 px. Cada opção tem umidfixo, que não muda quando a busca filtra a lista: assim o leitor de tela anuncia a nova opção ativa a cada letra digitada. Se as opções mudam com a lista aberta (resultado da API chegando), a opção ativa continua a mesma quando ainda está na lista; se ela saiu da lista, ou se a pessoa já tinha digitado, a primeira disponível fica ativa. - Teclado:
| Tecla | Lista fechada | Lista aberta |
|---|---|---|
| ↓ | Abre na opção escolhida ou na primeira | Próxima opção (pula as indisponíveis; para na última) |
| ↑ | Abre na opção escolhida ou na última | Opção anterior (para na primeira) |
| Alt + ↓ / Alt + ↑ | Abre sem mover / — | — / Fecha como o Esc |
| Letras | Abrem a lista e filtram; a primeira opção que combina fica ativa | Filtram |
| Enter | Fica com o formulário (envia) | Escolhe a opção ativa; na escolha simples, fecha |
| Esc | Fica com o diálogo em volta, se houver | Fecha sem mudar a escolha; na escolha simples, o texto volta ao nome escolhido, mesmo se foi apagado |
| Home / End | Movem o cursor no texto | Depois de ↓ ou ↑, primeira e última opção; ← e → voltam ao texto |
| Backspace | Com multiple e o campo vazio, remove a última etiqueta | Igual |
| Tab | Sai do campo | Fecha a lista e sai do campo |
- Cada escolha é anunciada numa região
role="status": "Opção Rui Antunes selecionada", "Opção Rui Antunes removida". Ao filtrar, a mesma região diz quantas opções sobraram ("3 opções disponíveis") ou oempty-text. - Com
multiple, o campo descreve o que já está escolhido ("2 selecionadas: Vitória, Serra") emaria-describedby. As etiquetas ficam numa lista com o nome do campo seguido de "opções selecionadas" ("Comarcas atendidas opções selecionadas"), para duas listas no mesmo formulário não se confundirem, e cada botão de remover se chama "Remover <nome>". Depois de remover, o foco volta ao campo. - O botão da seta fica fora da ordem do Tab (
tabindex="-1"), como no exemplo do APG: pelo teclado, a lista abre com ↓. - A cor nunca é o único sinal: opção escolhida tem marca (✓) ou caixa marcada; opção indisponível tem o sinal ⊘ e
aria-disabled="true"; erro e aviso têm ícone e texto noBaseField; somente leitura tem borda tracejada. - Na escolha múltipla obrigatória, o campo usa
aria-requiredem vez dorequirednativo, que acusaria o campo de busca vazio mesmo com opções escolhidas. Valide a lista no envio. - O foco do campo aparece com
--tj-ringnos dois temas; com erro ou aviso, a borda mantém a cor do estado. Em navegador sem:has(), o campo de texto desenha o próprio contorno de foco. No modo de alto contraste do Windows, o foco vira um contornoHighlighte a caixa marcada usa as cores do sistema. - Com
prefers-reduced-motion, a lista aparece sem animação e a seta não gira. - Desabilitado, o campo não envia valores no formulário nativo, como um controle nativo desabilitado.
- Testado com axe nos estados: fechado, aberto, filtrado com resultado, sem resultado, com escolha simples e múltipla (inclusive com End na lista), carregando, desabilitado, somente leitura (simples e múltipla), com erro, com aviso (fechado e aberto), nos três tamanhos e fora do
BaseField(comlabele comaria-labelledby).