Skip to content

Keep quiz focus, announce verdicts, and accept IME and single-quote answers - #13

Merged
renrenmimi merged 2 commits into
masterfrom
fix/quiz
Oct 10, 2026
Merged

renrenmimi merged 2 commits into
masterfrom
fix/quiz

Conversation

@renrenmimi

Copy link
Copy Markdown
Owner

Branches from #9 (commit 2148ad8), so it can be merged before or after it, and independently of #10–#12.

Summary

Fixes from the 2026-10-09 audit:

  • A11 (04-TSer-代码与体验.md)
    • After a keyboard answer the pressed option became disabled, so focus fell to <body>.
    • Verdicts were not announced.
    • Enter while an input method was composing submitted the answer.
    • Full-width -?, “dark” and | were rejected.
  • A19 (fill field) The fill field used 14px text, so iOS zoomed in when it was focused.
  • A26 (fill field) The fill field had no label.
  • A27 (question counter) The question counter stayed English in Chinese mode. This follows the sister site's decision in AlgoAlgo Correct the prologue and chapter 01: tsc still emits on errors, and arithmetic on any is a number #17.
  • B11 (04-TSer-内容.md) The finale's fill answers rejected 'dark' and 'oolong' | 'mango', which are equally valid TypeScript.
  • B21 (result copy) The Chinese result line used the gaming term 通关 and colloquial phrasing.

Changes

  • lib/quiz.tsx:
    • Focus
      • Answered options use aria-disabled instead of disabled, and a solved fill field is readOnly, so focus stays where it was.
      • After a multiple-choice check, focus moves to the verdict.
      • "Redo the quiz" hands focus to the first question.
    • Announcements: each question has a persistent role="status" region, and so does the final score.
    • Answer matching: normAnswer / answerMatches compare after NFKC, case and space folding, and fold every quote style to ".
    • Input: Enter is ignored while isComposing. The fill field is named by its question through aria-labelledby.
    • Copy: the counter reads 第 N 题 / 共 N 题 in Chinese. The Chinese result copy is formal: 全部答对,本章已完成。
  • app/globals.css, quiz rules only:
    • [aria-disabled] states for options and the quiz's own buttons.
    • .q-live:focus without a ring.
    • .q-input at 16px.
  • Test: test/quiz.test.tsx.

Verification

  • npx tsc --noEmit --incremental false: clean.
  • npm test: 7 files, 43 tests pass.
  • npm run build: succeeds.
  • Headless Chrome against a local next start, 390 px phone:
    • Keyboard on /types: Enter on the first option keeps focus on it (aria-disabled="true", not disabled), the verdict is in the question's role="status", and the next Tab stays in the quiz.
    • /mindset fill answers:
      • 'dark' and “dark” are judged right.
      • 'oolong' | 'mango' is judged right.
    • /type-magic fill answer: -? is judged right.
    • All four fill cases:
      • A synthetic Enter with isComposing: true does not submit.
      • The field keeps focus after the right answer.
      • The text is 16px.
      • The field's label is the question text.

🤖 Generated with Claude Code

renrenmimi and others added 2 commits October 9, 2026 16:07
JSX trims each line of a text block and joins the lines with one space.
The Chinese copy is wrapped across source lines throughout the course, so
it rendered with spaces between Chinese characters and around full-width
punctuation: 1,572 of them in 36 files.

- 1,548 line breaks are joined by a script that walks the TypeScript
  syntax tree and touches only JSX text and JSX attribute strings, never
  code samples, template literals or comments. Breaks next to Latin
  letters, digits, expressions, "——" or operators keep their space.
- 24 more spaces go: 20 after full-width punctuation, 3 between Chinese
  text and a tag whose text is Chinese, and one {" "} between a
  full-width mark and Chinese text.
- test/zh-copy-spacing.test.ts, the check DataData and AlgoAlgo use,
  scans every TSX file and fails on any new stray space; CLAUDE.md states
  the rule.

Apart from the one {" "}, the diff changes nothing but whitespace. The
text every edited file renders differs from master only by deleted
spaces, each next to Chinese text, so the English copy is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nswers

- Answered options use aria-disabled instead of disabled, so the option the learner pressed
  keeps keyboard focus; a solved fill field is read-only for the same reason.
- Every question has a persistent role="status" region, so each verdict and the final score
  are announced. After a multiple-choice check the vanished button's focus moves to the
  verdict, and "Redo the quiz" hands focus to the first question.
- Fill answers are compared after NFKC, case and space folding, with every quote style
  folded to a plain double quote: 'dark', “dark” and "dark" match "dark", and -? matches -?.
  Enter while an input method is composing no longer submits.
- The fill field is named by its question (aria-labelledby) and uses 16px text so iOS does
  not zoom. The question counter follows the interface language, and the Chinese result copy
  no longer uses the gaming term 通关.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 10, 2026 02:04
@vercel

vercel Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
tser Ready Ready Preview Oct 10, 2026 2:04am UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-10T02:06:55.657639Z 435a584 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 435a5841b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/quiz.tsx
type="button"
className={cls}
disabled={locked}
aria-disabled={locked || undefined}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove inert answered choices from the tab order

When a keyboard user answers a choice question, locked applies aria-disabled to every option, but unlike native disabled, these buttons all remain in the tab order while onPick makes them no-ops. Consequently, pressing Tab after answering a four-option question traverses the remaining unavailable choices instead of advancing to the next question. Preserve focus only on the activated option, or move focus to the verdict while making the other locked options natively disabled.

Useful? React with 👍 / 👎.

This branch was successfully deployed

1 active deployment
Preview — 435a5841 Deployed Oct 10, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants