Skip to content

Let keyboard users tick tasks off, keep two tabs' progress, and show full task titles - #12

Merged
renrenmimi merged 2 commits into
masterfrom
fix/lab-list-keyboard
Oct 10, 2026
Merged

renrenmimi merged 2 commits into
masterfrom
fix/lab-list-keyboard

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 and #11.

Summary

Fixes from the 2026-10-09 audit (04-TSer-代码与体验.md):

  • A2 Keyboard users could not mark a task as done. Enter and Space on the ✓ button expanded or collapsed the row instead, because the button sat inside a role="button" row whose key handler called preventDefault().
  • A3 With two tabs open, ticking a task in the second tab overwrote the first tab's progress with its stale in-memory copy. lib/progress.tsx was not assigned to any PR in the plan, and this is the PR that writes progress, so the fix is included here.
  • A20 (task titles) On phones, task titles were cut to one line even after the task was opened.
  • A26 (checkbox) The checkbox's tap target was 20×20 px, below the 24 px minimum.

Changes

  • lib/labs.tsx: each row has two sibling controls.
    • A checkbox: role="checkbox" with aria-checked, named "Mark task 01 as done" or 「将任务 01 标记为已完成」.
    • A .prob-toggle button with aria-expanded and aria-controls that opens the task body. The body now has an id.
  • lib/progress.tsx: every write is computed from the latest stored progress, falling back to memory when storage is unavailable. A storage listener brings in what other tabs write.
  • app/globals.css, .prob-* rules only:
    • The row padding moves to .prob-toggle, so the rest of the row still expands the task.
    • .prob-check::after extends the tap target to 34 px while the box stays 20 px.
    • Titles clamp to two lines in the list and show in full when the task is open.
  • Test: test/lab-list.test.tsx. It checks that the checkbox is never inside the expand control, that ticking does not expand, aria-controls, the merge between two providers, and the storage event sync.

Verification

  • npx tsc --noEmit --incremental false: clean.
  • npm test: 7 files, 41 tests pass.
  • npm run build: succeeds.
  • Headless Chrome against a local next start:
    • /types, keyboard: with the first checkbox focused, Space stores types/hover-infer with aria-checked="true", and the row stays closed. Enter clears it. Tab to the row button and Enter expands the task.
    • Tap target: points 4 px outside the 20 px box on all four sides still hit the checkbox.
    • Two tabs (the audit's steps): tick the first task on /types, then on /functions in a second tab. Storage holds both types/hover-infer and functions/annotate-maketea, and the first tab's sidebar shows 2 tasks.
    • 390 px phone: titles take up to two lines, and an opened task shows its whole title.

🤖 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>
…full task titles

- Split each task row into two sibling controls: a real checkbox (role="checkbox",
  aria-checked, named after the task number) and a button that expands the task with
  aria-expanded and aria-controls. The checkbox used to sit inside a role="button" row whose
  key handler cancelled Enter and Space, so it could never be ticked from the keyboard.
- Enlarge the checkbox's tap target to 34px with a pseudo-element; the box stays 20px.
- Let task titles wrap to two lines in the list and show in full once the task is open.
- Base every progress write on what is in storage and listen for the storage event, so a
  second open tab no longer overwrites the first tab's progress with its stale copy.

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

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.

@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 1:59am UTC

@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:01:27.749200Z 049f076 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: 049f0760c0

ℹ️ 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/progress.tsx
/** 以存储中的最新数据为基础计算下一份进度;change 返回 null 表示不写入。 */
const update = useCallback(
(change: (base: ProgressData) => ProgressData | null) => {
const base = readStored() ?? latest.current;

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 Fall back to memory after storage write failures

When localStorage.getItem() succeeds but setItem() fails—for example, because storage is full or a private-mode implementation rejects writes—readStored() keeps returning the unchanged persisted value rather than null. Every subsequent update therefore uses that stale value instead of latest.current, so checking a second task drops the first in-memory check, and a reset can resurrect the old stored progress. Track a failed write and use the in-memory value thereafter, as promised by the catch path.

Useful? React with 👍 / 👎.

@renrenmimi
renrenmimi merged commit 7615e64 into master Oct 10, 2026
3 of 4 checks passed
@renrenmimi
renrenmimi deleted the fix/lab-list-keyboard branch October 10, 2026 06:21

This branch was successfully deployed

1 active deployment
Preview — 049f0760 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