8.7 KiB
id, title, status, wave, depends_on, plan, requirements, acceptance_criteria, system_design
| id | title | status | wave | depends_on | plan | requirements | acceptance_criteria | system_design | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-render-grid | Render the conversation grid | done | 2 |
|
plan.md |
|
|
|
Task 02: Render the conversation grid
Summary
Render the saved layout using stable task tiles, with two live desktop/tablet rows and the existing one-chat phone composition. Preserve selection, draft identity, scrolling, and viewport-owned session delivery.
In scope
- Pass effective layout from the page and add the proposed pure
thread-layout.tshelper plus board content-size measurement. - Preserve direct task children and keys; add Grid tracks, odd/single-task handling, height fallback, lower-row navigation, and layout-aware recovery.
- Refresh activation on layout changes, reject stale observer callbacks, and prove both visible rows without increasing offscreen membership/streams.
- Localize the fallback explanation and preserve existing task actions.
Out of scope
Composer disclosure and the Display editor/shortcut, owned by Tasks 03 and 04. Do not change platform traffic contracts, task ordering, or admission limits.
Acceptance
- Columns/Grid match UI-01/UI-02, including odd/single/empty cases and the 300px row-height fallback; saved preferences survive responsive changes.
- Switching layouts or removing a lower-row task retains the deterministic reader/session/draft and existing task navigation behavior.
- Both visible rows load selected conversations; 30-shell tests stay bounded, offscreen chats release, and phone transitions retain one active detail.
ASCII UI preview
UI-02: Grid at a sufficient desktop height, excerpt from full previews.
+--------------+--------------+--------------+
| A [Open] | C [Open] | E [Open] |
| transcript | transcript | transcript |
+--------------+--------------+--------------+
| B [Open] | D [Open] | F [Open] |
| transcript | transcript | transcript |
+--------------+--------------+--------------+
Task 02 retains normal composers; Task 03 supplies the collapsed footer shown in the combined preview. The task order is A, B, C, D, E, F. UI-05 phone excerpt:
[Threads / View] [2/6] [Menu]
[Task B v] [Open]
[one live conversation ]
[normal composer ]
The phone uses swipe/picker navigation. These structures cover all assigned layout criteria. The board scrolls horizontally; each transcript owns its vertical content scroll. Grid tracks must not stretch when content grows.
Verification
From the repository root, after Task 01 bootstrap. Add behavior-specific RED unit/browser assertions before implementation. New files below are planned.
(cd apps/web && pnpm exec vitest run components/threads/thread-layout.test.ts components/threads/threads-board.test.tsx components/threads/thread-column-activation.test.tsx components/threads/use-thread-selection-recovery.test.tsx components/threads/use-mobile-thread-position.test.tsx lib/threads/thread-selection-fallback.test.ts app/threads/threads-page-client.test.tsx)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm exec eslint components/threads/threads-board.tsx components/threads/thread-column.tsx components/threads/thread-layout.ts components/threads/use-thread-column-activation.ts components/threads/use-thread-selection-recovery.ts app/threads/threads-page-client.tsx --max-warnings 0)
(cd apps/web && pnpm run i18n:check)
(cd apps/web && pnpm run i18n:ratchet)
(cd apps/web && pnpm e2e:run --project chromium tests/task/threads-layouts.spec.ts tests/task/threads-view.spec.ts tests/task/threads-task-actions.spec.ts -- --retries=0)
(cd apps/web && pnpm e2e:run --project mobile-chrome tests/task/mobile-threads-view.spec.ts tests/task/mobile-threads-swipe.spec.ts -- --retries=0)
git diff --check
Use the managed runner's builds and memory limits. Confirm discovery and capture rendered UI-01/UI-02 at wide desktop, short height, 767/768px, and a coarse-pointer tablet. API-seeded preferences are fixture setup until Task 04 exposes controls; assertions must read and interact with the rendered board.
Files likely touched
apps/web/app/threads/threads-page-client.tsxapps/web/components/threads/threads-board.tsx,thread-column.tsx,use-thread-column-activation.ts, anduse-thread-selection-recovery.ts.- New
apps/web/components/threads/thread-layout.tsand its test. - New
use-thread-selection-recovery.test.tsxbeside the hook; existing board/activation/page tests named above. - New
apps/web/e2e/tests/task/threads-layouts.spec.ts; reused presentation setup may live in newthreads-presentation-helpers.ts. apps/web/src/locales/*/threads.jsonfor the height fallback.- Existing desktop/task-action/mobile specs only when fixture expectations need the explicit default layout; retain their scenarios.
apps/web/components/threads/AGENTS.mdfor layout and reflow ownership.
Dependencies
Task 01. Layout consumes its normalized effective presentation.
Risks
Pair wrappers or index-based React keys remount editors. An observer can deliver old-layout geometry after resize. Both rows share horizontal offsets, so recovery must retain task identity instead of inferring a unique task from an x-coordinate. Full editors need bounded row sizing.
Parallelism
sequential
Inputs
- Layout requirements
- Layout design
- Existing board, viewport activation, stable order, primary-session E2E, thread task actions, and mobile swipe test patterns.
Results
PR #3626 follow-up: observer rebuilds measure current visibility, height fallback text no longer changes board allocation, wheel interaction records the reader anchor, and deep-link scrolling honors reduced motion. Final commands and results are in the review remediation record. The original implementation evidence below remains historical.
Done, 2026-09-11.
- Behavioral RED: layout helper returned Columns for Grid, stale observer delivery changed active details, and browser geometry remained single-row. The real-page test additionally caught the native boot field omission recorded in Task 01, resize-generated scroll/live snapshots replacing the reader before responsive commit, and layout/width reflow interrupting deep-link scroll.
- GREEN: the seven required Vitest files pass 62 tests. Task shells retain identity, both rows activate, 30-shell preload/stream windows stay bounded, lower-row horizontal anchors survive reflow, and user wheel input retires the initial deep-link mark. Typecheck and the exact ESLint command pass.
pnpm run i18n:check,pnpm run i18n:ratchet, andgit diff --checkpass. Traditional Chinese and pseudo catalogs were generated; unrelated generator changes were removed. No new dependencies or non-test runtime instances were added. Updated the scoped engineering guide's grid and reflow ownership.- First rebuilt desktop run: 19 passed, one deep-link failure. Corrected the reflow handoff. Final desktop command below passes all 20 cases (3.7 minutes) against the final same-membership snapshot guard, with retries disabled. The guard's 62 unit cases, typecheck, lint, and localization ratchet pass too.
- Final mobile command: 10 tests passed with retries disabled (1.6 minutes),
after
pnpm run build:e2e. Both phone-to-tablet selection and an immediate resize after a deep link are covered. Inspected phone and coarse-tablet screenshots: one phone chat, two tablet rows, retained lower-row selection, and 44px Open task touch targets. This is emulator evidence, not a physical keyboard/device check.
Final browser commands ran sequentially from apps/web against the final
production change, with one managed worker and no retries. The backend and
plugin fixtures were built by the earlier managed run; the final change was
frontend-only.
pnpm run build:e2e
pnpm e2e:run --no-build --project chromium tests/task/threads-layouts.spec.ts tests/task/threads-view.spec.ts tests/task/threads-task-actions.spec.ts -- --retries=0
pnpm e2e:run --no-build --project mobile-chrome tests/task/mobile-threads-view.spec.ts tests/task/mobile-threads-swipe.spec.ts -- --retries=0