Questionário
Um formulário passo a passo que se move entre perguntas com senso de direção, mostra o progresso real e responde pelo teclado.
pnpm dlx shadcn@latest add https://hextaui.com/r/questionnaire.jsonAdiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.
Adicione os tokens de tema ao seu CSS global, se ainda não o fez.
Instale as dependências.
pnpm add @shadcn/react @base-ui/react @tabler/icons-react class-variance-authority cnCopie e cole o código a seguir no seu projeto.
components/ui/questionnaire.tsx components/ui/button.tsx components/ui/input.tsx components/ui/kbd.tsx components/ui/number-flow.tsx lib/motion.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
As respostas são enviadas como um formulário comum, indexadas pelo name de cada item. As perguntas se movem na direção em que você vai, o card suaviza até a altura de cada pergunta, e o progresso só preenche para perguntas respondidas ou puladas.
Transição lift e barra
transition="lift" move as perguntas para cima e para baixo como uma pilha. variant="bar" no progresso mostra uma única barra contínua.
Avanço automático
Com autoAdvance, escolher uma resposta única avança após uma breve pausa, então você pode responder só com 1–5. Alterar uma resposta anterior nunca salta adiante, e a última pergunta nunca é enviada sozinha.
Perguntas condicionais
Desabilite um item para deixá-lo de fora. Ele sai do progresso e do fluxo até passar a valer.
Da direita para a esquerda
O deslizamento segue a direção de leitura.
| Tecla | Ação |
|---|---|
| ↑↓ | Move entre as respostas, incluindo o campo de texto. Mover não escolhe. |
| Space | Escolhe a resposta com foco, ou a alterna em múltipla escolha. |
| Enter | Continua. Em uma resposta única não escolhida, escolhe-a primeiro. Envia na última pergunta. |
| ←→ | Pergunta anterior ou próxima, espelhado da direita para a esquerda. Next treme quando uma resposta é necessária. Dentro do campo de texto, movem o cursor. |
| HomeEnd | Primeira ou última resposta. |
| A1 | Escolhe uma resposta pela sua tecla quando shortcuts está definido. As teclas se iluminam quando o questionnaire recebe foco; clique em qualquer lugar nele para começar. |
| Esc | Sai do campo de texto para os atalhos de letras voltarem a funcionar. |
| ⌘Enter | Envia de qualquer lugar. |
- Cada
QuestionnaireItemé um<fieldset>cujo título é seu<legend>. Perguntas inativas ficam ocultas e inertes, inclusive a que está animando a saída. - O progresso é uma
progressbarque anuncia “Question 2 of 5”; os segmentos e o número giratório são decorativos. - Os erros usam
role="alert"e as respostas inválidas recebemaria-invalid. - Com movimento reduzido, as perguntas trocam instantaneamente e nada treme.
| Prop | Tipo | Padrão |
|---|---|---|
transition | "slide" | "lift" | "slide" |
autoAdvanceAvança 350ms depois que uma resposta única é escolhida pela primeira vez. | boolean | false |
shortcutsAdiciona um atalho de tecla a cada resposta. | "letters" | "numbers" | – |
item | string | – |
defaultItem | string | – |
onItemChange | (item: string) => void | – |
| Atributo | Descrição |
|---|---|
data-slot="questionnaire" | O formulário, com data-transition. |
data-current / data-total | A posição atual e o número de perguntas. |
data-first / data-last | Presente na primeira ou na última pergunta. |
| Prop | Tipo | Padrão |
|---|---|---|
variant | "segments" | "bar" | "segments" |
| Atributo | Descrição |
|---|---|
data-slot="questionnaire-progress-segment" | Um por pergunta, com data-status, data-active e data-invalid. |
| Prop | Tipo | Padrão |
|---|---|---|
nameO nome do campo do formulário. | string | – |
required | boolean | false |
multipleCheckboxes em vez de radios. | boolean | false |
disabledDeixa a pergunta fora do fluxo. | boolean | false |
onStatusChange | (status) => void | – |
| Atributo | Descrição |
|---|---|
data-status | "unanswered", "answered" ou "skipped". |
data-active | A pergunta atual. |
data-invalid | Precisa de uma resposta. |
data-leaving | A pergunta animando a saída. |
| Prop | Tipo | Padrão |
|---|---|---|
value | string | – |
defaultChecked | boolean | – |
disabled | boolean | false |
render | ReactElement | (props, state) => ReactElement | <label> |
| Atributo | Descrição |
|---|---|
data-checked / data-unchecked | Se a resposta está escolhida. |
data-type | "radio" ou "checkbox". |
data-shortcut | A tecla da resposta. |
Uma resposta de texto livre que fica junto das opções. Digitar limpa a opção escolhida. Dê a ela um rótulo ou aria-label.
| Prop | Tipo | Padrão |
|---|---|---|
variant | Button variant | "ghost", or "default" for Next and Submit |
size | Button size | "default" |
QuestionnaireNext e QuestionnaireSubmit compartilham um slot, então na última pergunta Next troca por Submit sem mover nada.
- ButtonBotões em todas as variantes e tamanhos, com um fluxo integrado de carregamento, sucesso e erro que dispensa o spinner em requisições rápidas.
- InputUm campo de texto com três tamanhos, estados inválido e somente leitura, estilo de validação nativa e fonte de 16px no toque para que os celulares nunca façam zoom.
- KbdTeclas para atalhos que mostram os símbolos certos em cada plataforma, são lidas corretamente por leitores de tela e afundam com as teclas reais.
- MotionAs curvas de easing, as durações e a verificação de movimento reduzido com que todo componente anima, além de hooks para transformações de tamanho e destaques deslizantes.
- Number flowNúmeros animados em que só os dígitos alterados giram, com qualquer formato Intl e locale.
- CalendarUma grade de datas para seleção única, de intervalo e múltipla, com meses deslizantes, prévias de intervalo e dias com tamanho adequado ao toque.
Usado em blocos
Blocos que se baseiam em Questionnaire.