DEV Community

Neural_Ethos
Neural_Ethos

Posted on

Designing a Political Quiz UI as an Explicit State Machine

A questionnaire UI looks simple until the unhappy paths arrive. A user changes an earlier answer, reloads halfway through, reaches the final question with one response missing, or expects a “private” flow to work without a network round trip. At that point, a stack of booleans becomes harder to reason about than the questionnaire itself.

This article treats a public 48-question political test as a black-box product example. It does not claim access to its source code, private architecture, analytics, or production implementation. The goal is to extract reusable frontend questions from what the interface publicly promises.

Start with states, not screens

The visible journey suggests a compact domain model:

type QuizState =
  | { kind: "intro" }
  | { kind: "answering"; index: number; answers: Answer[] }
  | { kind: "review"; answers: Answer[] }
  | { kind: "result"; axes: AxisScore[] }
  | { kind: "error"; message: string };

type Answer = -2 | -1 | 0 | 1 | 2;

type AxisScore = {
  id: string;
  value: number;
  leftLabel: string;
  rightLabel: string;
};
Enter fullscreen mode Exit fullscreen mode

This is a design proposal, not an observation of internal code. Its benefit is that invalid combinations become harder to represent. There is no separate isFinished, showResult, and hasError trio that can accidentally all become true.

Test Ideologia Politica is a useful reference surface because its public promise is unusually concrete: 48 statements, a five-point agreement scale, 12 result axes, no account requirement, and scoring performed on the device.

Make every transition explicit

A transition table is more useful than a component tree when product behavior is still being defined.

Current state Event Guard Next state
intro START questions loaded answering(0)
answering ANSWER valid scale value answering(next)
answering BACK index > 0 answering(previous)
answering FINISH every item answered result
answering FINISH answer missing review
review EDIT valid question id answering(index)
result RESTART always intro

The important rule is that one user event causes one documented transition. “Answer and maybe finish and maybe calculate and maybe navigate” is a cluster of behaviors that deserves decomposition.

For a fixed sequence grouped by axis, the UI should also define whether going back overwrites the previous response, whether progress shows questions seen or questions answered, and whether a neutral answer counts as complete. These are product rules, not implementation details.

Treat local scoring as a verifiable contract

“Calculated on your device” is both a privacy promise and an architectural constraint. A QA plan should be able to verify it without reading source code:

  1. Complete the flow with the network disabled after the initial page load.
  2. Observe whether answers trigger requests.
  3. Reload and check whether partial answers persist, disappear, or are explicitly recoverable.
  4. Confirm that clearing site data removes locally stored responses.
  5. Check that the result can be reproduced from the same answer vector.

The public Test Ideologia Politica interface says answers are not sent to a server and that the result is shown in the browser. That statement should be covered by regression tests because privacy copy becomes a product contract the moment it is published.

Separate scoring from interpretation

Multi-axis products need at least three layers:

  • Answer normalization: convert the five choices into stable numeric values.
  • Axis calculation: aggregate the relevant items, including reverse-scored questions where defined.
  • Presentation: turn scores into labels, charts, explanatory text, and comparisons.

Keeping those layers separate makes tests clearer. A copy change should not alter a score. A chart redesign should not change party affinity. A revised scoring rule should be visible in versioned fixtures rather than hidden inside a component.

The same separation helps with political neutrality. A nearest-party comparison is an editorial reference based on a chosen coordinate set; it should not be represented as a deterministic truth about the user. The UI needs language such as “indicative,” “closest on these dimensions,” and “not a voting recommendation.”

Accessibility is part of the state model

For each new question, focus should land on the question heading, not remain on the button from the previous screen. The five choices should form a radio group with an accessible name. Progress needs text—“Question 17 of 48”—rather than color alone. Keyboard users should be able to choose, continue, return, and review without a pointer.

Result charts also need a nonvisual equivalent. A radar or map can be attractive, but every axis should have a text label and value. Opposing pole labels must not rely on spatial position alone.

Tests that catch real failures

Before shipping a similar interface, cover these cases:

  • starting without JavaScript or with question data unavailable;
  • selecting each of the five answer values;
  • changing an earlier response and recalculating;
  • finishing with the first, middle, or last answer missing;
  • reloading at question 1, 24, and 48;
  • navigating with keyboard only;
  • reduced-motion mode and narrow mobile view;
  • deterministic results for a fixed answer fixture;
  • no answer payload in network traffic when local-only processing is promised;
  • clear restart behavior with no stale scores.

The deeper lesson is that a questionnaire is not a form with a fancy result page. It is a small stateful application handling sensitive opinions. Model it with the same care you would give checkout, onboarding, or account recovery—especially when the copy makes privacy and interpretability part of the product promise.

Top comments (0)