feat(app): clearer interactive question card#1643
Conversation
Bring the AskUserQuestion card closer to the Claude Code CLI's clarity: - Legible typography: option labels 16px semibold, descriptions 14px, matching the surrounding conversation instead of receding below it. - Discoverable multi-select: a static left-side control (checkbox for multi-select, radio for single-select) replaces a trailing check that only appeared on selection and reflowed the row. - Multi-question nav shows each question's title, with a check on answered ones, instead of bare numbered circles. - a11y: single-select options grouped in a radiogroup; per-row checkbox/radio roles; aria-selected -> aria-checked. Updates the e2e question helper for the new option roles. No protocol change; multiSelect was already parsed on the client. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| packages/app/src/components/question-form-card.tsx | UI/a11y overhaul: correct checkbox/radio roles and aria-checked for options, new always-visible selection controls, and a QuestionNav component that shows titled tabs (hidden for single questions). Accessible name for nav tabs overrides the visible header text, partially counteracting the a11y goals. |
| packages/app/e2e/helpers/questions.ts | Helper updated to use radio/checkbox roles and aria-checked for option assertions, and a tab role for nav; includes a guard that skips the nav assertion for single-question cards (noted in prior review comments). |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[QuestionFormCard] --> B{questions.length <= 1?}
B -- yes --> C[No nav rendered]
B -- no --> D[QuestionNav tablist]
D --> E[QuestionNavButton x N
role=tab, aria-selected]
A --> F[questionHeader
active question text]
A --> G{activeQuestion.multiSelect?}
G -- yes --> H[optionsWrap
no role wrapper]
G -- no --> I[optionsWrap
role=radiogroup]
H --> J[QuestionOptionRow
role=checkbox
accessibilityState.checked]
I --> K[QuestionOptionRow
role=radio
accessibilityState.checked]
J --> L[selectionControl square
filled when checked]
K --> M[selectionControl circle
radio dot when selected]
A --> N[Actions row
Dismiss + Next/Submit]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[QuestionFormCard] --> B{questions.length <= 1?}
B -- yes --> C[No nav rendered]
B -- no --> D[QuestionNav tablist]
D --> E[QuestionNavButton x N
role=tab, aria-selected]
A --> F[questionHeader
active question text]
A --> G{activeQuestion.multiSelect?}
G -- yes --> H[optionsWrap
no role wrapper]
G -- no --> I[optionsWrap
role=radiogroup]
H --> J[QuestionOptionRow
role=checkbox
accessibilityState.checked]
I --> K[QuestionOptionRow
role=radio
accessibilityState.checked]
J --> L[selectionControl square
filled when checked]
K --> M[selectionControl circle
radio dot when selected]
A --> N[Actions row
Dismiss + Next/Submit]
Reviews (2): Last reviewed commit: "fix(app): model question nav as a tablis..." | Re-trigger Greptile
Addresses review feedback on getpaseo#1643: - The nav tabs were role="button" + aria-selected, which is invalid ARIA (aria-selected isn't defined for the button role). Model the nav as role="tablist" containing role="tab" items, which makes aria-selected valid and is semantically accurate for a question switcher. - Guard expectCurrentQuestion's nav assertion so it only runs for multi-question cards — the nav is hidden for a lone question, so the helper would otherwise time out if used on a single-question flow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed Greptile feedback in 34f1025:
Pagination e2e re-run green against the new roles. |
Linked issue
Closes #1642
Type of change
What does this PR do
Brings the interactive question card (
AskUserQuestion) closer to the Claude Code CLI's clarity, all in one component (packages/app/src/components/question-form-card.tsx):radiogroup; per-rowcheckbox/radioroles;aria-selected→aria-checked(the correct state for these roles).No protocol/schema change —
multiSelectwas already parsed on the client. Also updates the e2e question helper (e2e/helpers/questions.ts) for the new option roles.How did you verify it
npm run typecheck,npm run lint,npm run format— clean.npx playwright test e2e/question-prompt-pagination.spec.ts— passes (exercises the new option roles + the updated helper).Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatran (Biome)