T2 EducaçãoMidas

Questionnaire

Questionário em etapas guiado por dados. Escolha única ou múltipla, resposta livre (outro), pular, atalhos de teclado (letras ou números), validação, perguntas condicionais, progresso em texto, barra ou fração, variante card, animação, e etapa e respostas controláveis (para salvar e retomar).

Código-fonte

Exemplos

Interaja com o componente e copie o código de cada exemplo.

Básico

Responda para habilitar Próxima.

Pergunta 1 de 3

Qual certificação você vai tirar?

Vamos montar seu plano de estudos.

Múltipla escolha e resposta livre

Quais temas você quer revisar?

Marque todos que se aplicam ou escreva outro.

Atalhos de teclado e pular

Pergunta 1 de 2

Qual seu nível de conhecimento?

Use as teclas A, B ou C.

Atalhos com letras ou números

O que você quer fazer agora?

Use o atalho mostrado ou navegue com o teclado.

Validação, condicional e barra de progresso

Escolha CPRO-R para ver a pergunta extra.

Pergunta 1 de 2

Qual certificação?

Controlado (salvar e retomar)

Etapa salva: 2

Pergunta 2 de 3

Quanto tempo você tem por semana?

Pode mudar depois.

Retomar de onde parou

Pergunta 2 de 3 (retomado)

Quanto tempo você tem por semana?

Estado de navegação

Lendo o status de cada pergunta com isAnswered.

1. Pendente2. Pendente

Pergunta 1 de 2

O que a Tati pode acessar?

Próxima fica desabilitado até você escolher pelo menos uma opção.

Progresso personalizado

Usando renderProgress com o componente Progress.

Etapa 1 de 3: falta 2

Qual certificação você vai tirar?

Animação

A troca de pergunta é animada; animated={false} desliga.

Pergunta 1 de 2

Qual é o seu nível no mercado financeiro?

Card

Quanto detalhe você quer nos resumos?
Escolha a profundidade.
1/2

Dialog

import {
  Questionnaire,
  type QuestionnaireAnswers,
  type QuestionnaireQuestion,
} from "@t2-educacao/midas";

Uso

const perguntas: QuestionnaireQuestion[] = [
  {
    id: "certificacao",
    title: "Qual certificação você vai tirar?",
    description: "Vamos montar seu plano de estudos.",
    options: [
      { value: "cpa", label: "CPA" },
      { value: "cpro-r", label: "CPRO-R" },
      { value: "cpro-i", label: "CPRO-I" },
    ],
  },
  {
    id: "tempo",
    title: "Quanto tempo você tem por semana?",
    options: [
      { value: "ate-3", label: "Até 3 horas" },
      { value: "3-a-6", label: "De 3 a 6 horas" },
      { value: "mais-6", label: "Mais de 6 horas" },
    ],
  },
];

<Questionnaire questions={perguntas} onComplete={(respostas) => salvarPlano(respostas)} />

Props

PropTipoPadrãoDescrição
questionsQuestionnaireQuestion[]obrigatórioAs perguntas
onComplete(answers) => void | PromiseChamado ao enviar a última. Se retornar promise, o botão mostra carregando
value / defaultValue / onValueChangeQuestionnaireAnswersRespostas controladas / iniciais
step / defaultStep / onStepChangenumber0Etapa atual (índice nas perguntas visíveis)
progress"text" | "bar" | "fraction" | "none""text" (se > 1 pergunta)Estilo do progresso
progressLabel(current, total) => ReactNode"Pergunta 1 de 3"Texto do progresso
renderProgress({ current, total, question }) => ReactNodeProgresso totalmente personalizado
shortcuts"letters" | "numbers" | falsefalseAtalhos A, B, C ou 1, 2, 3
variant"default" | "card""default"card envolve em um Card com rodapé
animatedbooleantrueAnima a troca de pergunta
labels{ next, back, submit, skip, otherPlaceholder }"Próxima", "Voltar", "Enviar", "Pular"Textos dos botões

QuestionnaireQuestion

CampoTipoDescrição
idstringChave da resposta
title / descriptionReactNodePergunta e texto de apoio
type"single" | "multiple"Escolha única (padrão) ou múltipla
options{ value, label, description?, disabled? }[]Opções
otherboolean | { placeholder?, label? }Campo de resposta livre abaixo das opções
optionalbooleanPermite avançar sem responder
skippablebooleanMostra o botão "Pular"
validate(answer, answers) => string | undefinedRetorne a mensagem de erro para bloquear
when(answers) => booleanMostra a pergunta só quando retornar true

Formato das respostas

type QuestionnaireAnswers = Record<string, { values: string[]; other?: string; skipped?: boolean }>;

{ certificacao: { values: ["cpa"] }, temas: { values: ["etica"], other: "Previdência" } }

Exemplos

Múltipla escolha com resposta livre

{
  id: "temas",
  title: "Quais temas você quer revisar?",
  type: "multiple",
  options: [{ value: "etica", label: "Ética" }, { value: "investimentos", label: "Investimentos" }],
  other: { placeholder: "Outro tema…" },
}

Validação

{
  id: "temas",
  type: "multiple",
  title: "Escolha os temas",
  options: [...],
  validate: (answer) => (answer.values.length < 2 ? "Escolha pelo menos dois temas." : undefined),
}

Pergunta condicional

{
  id: "modulo",
  title: "Qual módulo da CPRO-R?",
  when: (respostas) => respostas.certificacao?.values[0] === "cpro-r",
  options: [...],
}

Salvar e retomar

const [respostas, setRespostas] = useState<QuestionnaireAnswers>(salvas ?? {});
const [etapa, setEtapa] = useState(etapaSalva ?? 0);

<Questionnaire
  questions={perguntas}
  value={respostas}
  onValueChange={setRespostas}
  step={etapa}
  onStepChange={setEtapa}
/>

Em card ou dialog

<Questionnaire variant="card" progress="fraction" questions={perguntas} />

<Dialog>
  <DialogTrigger asChild><Button>Montar meu plano</Button></DialogTrigger>
  <DialogContent>
    <DialogTitle className="sr-only">Montar plano de estudos</DialogTitle>
    <Questionnaire questions={perguntas} />
  </DialogContent>
</Dialog>

Teclado

TeclaAção
Tab / setasNavega entre as opções (radio nativo)
EspaçoMarca a opção focada
A, B, C... ou 1, 2, 3...Marca a opção (com shortcuts)
EnterPróxima pergunta / enviar

Acessibilidade

  • As opções são inputs nativos (radio/checkbox) dentro de radiogroup/group com o título como nome.
  • Erros de validação são anunciados (role="alert").
  • O botão "Próxima" fica desabilitado até a pergunta obrigatória ser respondida.

On this page