Repository navigation
Let keyboard users tick tasks off, keep two tabs' progress, and show full task titles - #12
Conversation
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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 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".
| /** 以存储中的最新数据为基础计算下一份进度;change 返回 null 表示不写入。 */ | ||
| const update = useCallback( | ||
| (change: (base: ProgressData) => ProgressData | null) => { | ||
| const base = readStored() ?? latest.current; |
There was a problem hiding this comment.
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 👍 / 👎.
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):role="button"row whose key handler calledpreventDefault().lib/progress.tsxwas not assigned to any PR in the plan, and this is the PR that writes progress, so the fix is included here.Changes
lib/labs.tsx: each row has two sibling controls.role="checkbox"witharia-checked, named "Mark task 01 as done" or 「将任务 01 标记为已完成」..prob-togglebutton witharia-expandedandaria-controlsthat opens the task body. The body now has anid.lib/progress.tsx: every write is computed from the latest stored progress, falling back to memory when storage is unavailable. Astoragelistener brings in what other tabs write.app/globals.css,.prob-*rules only:.prob-toggle, so the rest of the row still expands the task..prob-check::afterextends the tap target to 34 px while the box stays 20 px.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 thestorageevent sync.Verification
npx tsc --noEmit --incremental false: clean.npm test: 7 files, 41 tests pass.npm run build: succeeds.next start:/types, keyboard: with the first checkbox focused, Space storestypes/hover-inferwitharia-checked="true", and the row stays closed. Enter clears it. Tab to the row button and Enter expands the task./types, then on/functionsin a second tab. Storage holds bothtypes/hover-inferandfunctions/annotate-maketea, and the first tab's sidebar shows 2 tasks.🤖 Generated with Claude Code