Finish the board screen in the UI language v2 #252

Merged
Grandiras merged 5 commits from ui-v2-board into main 2026-10-04 15:42:17 +00:00
Owner

Finishes the board screen of the UI language v2 against the Figma draft (Desktop · Board · Summer fair light/dark, Phone · Board light/dark, Phone · Holding a card, and the Card, Column, Board header, Sidebar, Menu and Due components).

What changed

  • Cards are a title (three lines at most) over one meta line: the due date, the tags, a mark when there is a description (its words are the mark's tooltip), the comment count, and the faces at the end (Faces: three, then +N, initials on a colour of the member's own). Draft sizes, desktop and phone.
  • Due dates have four looks, each with its own mark: later (date), soon (Today / Tomorrow, orange), overdue (red), done (a green tick in the board's last column). The marks are CSS masks on .card-due::before, so Home's strip, link cards and search wear them too.
  • Column header: name, a raised count, the deck's Show all / Show less, and a ⋯ menu with the tag filter (rows with dot and tick, Clear filter) and, for admins, Edit columns. Same filter state and drop-index rules as before. Add card now follows the last card (inside the list, last by flex order), so the tray stays a full-height drop target. The slot a card will land in is the draft's tinted, dashed one.
  • Board title bar: large title over 17 cards · 5 people (or Everyone / Only you, Home's words), the people's faces, Board · Calendar, a primary Add card (first column) and the board's ⋯ menu with Share and Board settings. Share leaves the account menu (the draft's account menu has none); the calendar and settings pages wear the same bar.
  • Sidebar: each board row counts its cards (live, via BoardService.GetNavAsync: Home's order plus one counting query) and shows a pin on pinned boards; a + beside Boards and a New board row open Home's own form (/?new=1, stripped once acted on). The account block is name over username with an up-down chevron.
  • Moving a card between columns shows Moved to Doing with Undo, which moves it back to its column and place.
  • Phone: no trays and no column headers (the switcher names the column), cards 16px in on the page, the top bar is Back + ⋯ (Share, Settings, and the tag filter for the column on screen, named), subtitle as on desktop. Holding a card dims the others and shows Drop on a column to move it over the tab bar.
  • Dark mode throughout; docs (ui.md, frontend.md, boards-and-permissions.md) updated with the reasons.

Judgement calls

  • Trays stay full height. The brief asked for columns that hug their content, but the board frames (37:2, 73:5397) show full-height trays, and that is also the documented rule (the emptiest column must offer a full-height drop target, pinned by board.spec.js). Only the isolated Column component hugs. Add card now sits right under the cards as in the frames.
  • The column label stays on the cards' rail (8px), where the draft sets it 8px further in: --column-rail is the documented "one left edge" rule.
  • The deck footnote still says "6 more", not the draft's "7 done": the column may be called anything (documented rule).
  • Undo on a move covers every path, the phone's flick and a drop on a switcher segment included: those send the card out of sight, which is exactly when the member needs to hear where it went and get it back. A reorder within its column stays in view and says nothing.
  • Done = the board's last column, the deck's existing rule, since nothing else knows which column is finished.
  • The phone's filter is per column, as before: the menu filters the column on screen and names it; BoardPage asks board-pagination.js which one as the menu opens rather than being told on every swipe.
  • ShareButton keeps its glyph (the draft's share icon differs): it is shared with the card dialog, which is being redesigned in parallel.
  • The title bar's faces hide below 960px and while the inspector is docked, where the views and Add card need the room.

How it was verified

  • tools/verify.sh: build and unit tests green.
  • Full Playwright suite on an isolated copy of the test stack; specs updated for the new structure and extended: the board menu and Add card, the move toast and Undo, the one-line meta and due states, the slot, the column menu, the sidebar's counts, pins and New board, the phone's Back + More bar, trayless board, its menu filtering the column on screen, and the dimmed board under the hint while a card is held.
  • Screenshots of desktop 1440×900 and phone 390×844, light and dark, compared side by side with the Figma frames (plus menus, holding state, 768/1000/1100/1280 widths).

🤖 Generated with Claude Code

Finishes the board screen of the UI language v2 against the Figma draft (Desktop · Board · Summer fair light/dark, Phone · Board light/dark, Phone · Holding a card, and the Card, Column, Board header, Sidebar, Menu and Due components). ## What changed - **Cards** are a title (three lines at most) over **one meta line**: the due date, the tags, a mark when there is a description (its words are the mark's tooltip), the comment count, and the faces at the end (`Faces`: three, then +N, initials on a colour of the member's own). Draft sizes, desktop and phone. - **Due dates have four looks**, each with its own mark: *later* (date), *soon* (Today / Tomorrow, orange), *overdue* (red), *done* (a green tick in the board's last column). The marks are CSS masks on `.card-due::before`, so Home's strip, link cards and search wear them too. - **Column header**: name, a raised count, the deck's Show all / Show less, and a **⋯ menu** with the tag filter (rows with dot and tick, Clear filter) and, for admins, Edit columns. Same filter state and drop-index rules as before. Add card now follows the last card (inside the list, last by flex `order`), so the tray stays a full-height drop target. The slot a card will land in is the draft's tinted, dashed one. - **Board title bar**: large title over *17 cards · 5 people* (or Everyone / Only you, Home's words), the people's faces, Board · Calendar, a primary **Add card** (first column) and the board's **⋯ menu** with Share and Board settings. Share leaves the account menu (the draft's account menu has none); the calendar and settings pages wear the same bar. - **Sidebar**: each board row counts its cards (live, via `BoardService.GetNavAsync`: Home's order plus one counting query) and shows a pin on pinned boards; a + beside *Boards* and a **New board** row open Home's own form (`/?new=1`, stripped once acted on). The account block is name over username with an up-down chevron. - **Moving a card between columns** shows *Moved to Doing* with **Undo**, which moves it back to its column and place. - **Phone**: no trays and no column headers (the switcher names the column), cards 16px in on the page, the top bar is **Back + ⋯** (Share, Settings, and the tag filter for the column on screen, named), subtitle as on desktop. Holding a card dims the others and shows *Drop on a column to move it* over the tab bar. - Dark mode throughout; docs (`ui.md`, `frontend.md`, `boards-and-permissions.md`) updated with the reasons. ## Judgement calls - **Trays stay full height.** The brief asked for columns that hug their content, but the board frames (37:2, 73:5397) show full-height trays, and that is also the documented rule (the emptiest column must offer a full-height drop target, pinned by `board.spec.js`). Only the isolated Column component hugs. Add card now sits right under the cards as in the frames. - **The column label stays on the cards' rail** (8px), where the draft sets it 8px further in: `--column-rail` is the documented "one left edge" rule. - **The deck footnote still says "6 more"**, not the draft's "7 done": the column may be called anything (documented rule). - **Undo on a move covers every path, the phone's flick and a drop on a switcher segment included**: those send the card out of sight, which is exactly when the member needs to hear where it went and get it back. A reorder within its column stays in view and says nothing. - **Done = the board's last column**, the deck's existing rule, since nothing else knows which column is finished. - **The phone's filter is per column, as before**: the menu filters the column on screen and names it; `BoardPage` asks `board-pagination.js` which one as the menu opens rather than being told on every swipe. - **ShareButton keeps its glyph** (the draft's share icon differs): it is shared with the card dialog, which is being redesigned in parallel. - The title bar's faces hide below 960px and while the inspector is docked, where the views and Add card need the room. ## How it was verified - `tools/verify.sh`: build and unit tests green. - Full Playwright suite on an isolated copy of the test stack; specs updated for the new structure and extended: the board menu and Add card, the move toast and Undo, the one-line meta and due states, the slot, the column menu, the sidebar's counts, pins and New board, the phone's Back + More bar, trayless board, its menu filtering the column on screen, and the dimmed board under the hint while a card is held. - Screenshots of desktop 1440×900 and phone 390×844, light and dark, compared side by side with the Figma frames (plus menus, holding state, 768/1000/1100/1280 widths). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Cards are a title over one meta line (due, tags, a description mark, the
comment count, the faces at the end), with four due states. Columns get a
header of name, count and a menu holding the tag filter and, for admins,
Edit columns; Add card follows the last card. The title bar carries the
board's line, its people, Add card and a menu with Share and Settings,
which leave the account menu. The sidebar counts and pins its boards and
opens Home's form for a new one; the account shows name over username.
A move between columns toasts with Undo. On a phone the board loses its
trays and headers, its top bar is Back and a menu that also filters the
column on screen, and a held card dims the rest under a hint.

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

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-03T15-08-32-499Z.md) — updating every ~5 minutes while the review runs.
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/693); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-693.md) — updating every ~5 minutes while the task runs.
claude-reviewer approved these changes 2026-10-03 15:09:02 +00:00
Dismissed
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

This is a coherent, well-documented change, and I found nothing that should block merging. I read the diff only. I did not run the build or the e2e suite.

What I checked:

  • Notifier wiring: NavHeader subscribes to BoardChanged and unsubscribes in Dispose. BoardPage swaps Reload for OnBoardsChanged on both sides.
  • Undo on a move: it captures the old index from the unfiltered column before the move. It then moves back through MoveCardAsync with the board id. A reorder inside one column shows no toast, as the docs say.
  • Home's ?new=1 handling: the redirect only happens when the renderer is interactive. The focus guard on _tiles stops the form field being focused before the tiles load.
  • Face colour: Faces.HueOf uses FNV-1a, so a face keeps its colour across restarts.
  • Conventions: user-visible strings are added in both locales, with a .one plural key for board.people. The docs are updated in the same PR.

Small points, none blocking:

  • Board subtitle flash: BoardPage.Subtitle reads "Only you" whenever _people is empty, because All() on an empty list is true. That can show briefly on a non-open board before people load. It would be worth guarding on _people.Count == 0.
  • Single-column boards: IsDone follows IsDeck. If a one-column board counts as a deck, none of its due dates ever turn red. Confirm that this matches the intent.
  • Nav count queries: GetNavAsync now runs a count query for every circuit on every BoardChanged for a listed board. That is probably fine for a small single-tenant group, but it is the new hot path to watch.
  • Leftover class: the column-filter-clear class stays on the Clear filter button but has no CSS any more. It is harmless, and modal-escape.js and the specs may rely on it.

🧠 claude-sonnet-5-5 · ⏱ 0m 18s · 2 turns · tokens: 72.6k in / 1.8k out (+12.2k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. This is a coherent, well-documented change, and I found nothing that should block merging. I read the diff only. I did not run the build or the e2e suite. What I checked: - **Notifier wiring:** `NavHeader` subscribes to `BoardChanged` and unsubscribes in `Dispose`. `BoardPage` swaps `Reload` for `OnBoardsChanged` on both sides. - **Undo on a move:** it captures the old index from the unfiltered column before the move. It then moves back through `MoveCardAsync` with the board id. A reorder inside one column shows no toast, as the docs say. - **Home's `?new=1` handling:** the redirect only happens when the renderer is interactive. The focus guard on `_tiles` stops the form field being focused before the tiles load. - **Face colour:** `Faces.HueOf` uses FNV-1a, so a face keeps its colour across restarts. - **Conventions:** user-visible strings are added in both locales, with a `.one` plural key for `board.people`. The docs are updated in the same PR. Small points, none blocking: - **Board subtitle flash:** `BoardPage.Subtitle` reads "Only you" whenever `_people` is empty, because `All()` on an empty list is true. That can show briefly on a non-open board before people load. It would be worth guarding on `_people.Count == 0`. - **Single-column boards:** `IsDone` follows `IsDeck`. If a one-column board counts as a deck, none of its due dates ever turn red. Confirm that this matches the intent. - **Nav count queries:** `GetNavAsync` now runs a count query for every circuit on every `BoardChanged` for a listed board. That is probably fine for a small single-tenant group, but it is the new hot path to watch. - **Leftover class:** the `column-filter-clear` class stays on the Clear filter button but has no CSS any more. It is harmless, and `modal-escape.js` and the specs may rely on it. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 18s · 2 turns · tokens: 72.6k in / 1.8k out (+12.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-693.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:282ce3d424a39a653913f513b4033251c1899117 -->
opencode-reviewer left a comment

💬 Verdict: comment — the reviewer did not submit a structured review; the raw output follows.

(empty)


⏱ 30m 3s · 38 steps · $0.1242 · tokens: 355.0k in / 1.8k out (+1952.1k cache-read) · Go: 5h 3% · wk 11% · mo 88%
📜 Full session transcript

💬 **Verdict: comment** — the reviewer did not submit a structured review; the raw output follows. (empty) --- ⏱ 30m 3s · 38 steps · $0.1242 · tokens: 355.0k in / 1.8k out (+1952.1k cache-read) · Go: 5h 3% · wk 11% · mo 88% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-03T15-08-32-499Z.md)
Grandiras force-pushed ui-v2-board from 282ce3d424
All checks were successful
CI / build (pull_request) Successful in 41s
to 5cbe095649
All checks were successful
CI / build (pull_request) Successful in 40s
2026-10-04 15:24:55 +00:00
Compare
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-04T15-25-56-436Z.md) — updating every ~5 minutes while the review runs.
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/699); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-699.md) — updating every ~5 minutes while the task runs.
claude-reviewer approved these changes 2026-10-04 15:26:17 +00:00
Dismissed
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

I read the diff only. I did not run the build or the e2e suite.

Of my earlier notes, the board-subtitle flash is fixed. BoardPage.Subtitle now returns just the card count while _people is empty on a non-open board, so "Only you" no longer shows before people load.

Still open, none blocking:

  • Single-column boards: IsDone follows IsDeck. If a one-column board counts as a deck, its due dates never turn red. Please confirm that is intended.
  • Nav count query: GetNavAsync runs one count query per circuit on each BoardChanged for a listed board. That is fine for a small group, but it is the new hot path to watch.
  • Leftover class: column-filter-clear has no CSS any more but is harmless.

Everything else looks consistent:

  • Notifier subscriptions are unsubscribed in Dispose.
  • Undo on a move captures the old index before the move.
  • New strings are in both locales.
  • The docs are updated in the same PR.

🧠 claude-sonnet-5-5 · ⏱ 0m 5s · 2 turns · tokens: 73.4k in / 519 out (+12.2k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. I read the diff only. I did not run the build or the e2e suite. Of my earlier notes, the board-subtitle flash is fixed. `BoardPage.Subtitle` now returns just the card count while `_people` is empty on a non-open board, so "Only you" no longer shows before people load. Still open, none blocking: - **Single-column boards:** `IsDone` follows `IsDeck`. If a one-column board counts as a deck, its due dates never turn red. Please confirm that is intended. - **Nav count query:** `GetNavAsync` runs one count query per circuit on each `BoardChanged` for a listed board. That is fine for a small group, but it is the new hot path to watch. - **Leftover class:** `column-filter-clear` has no CSS any more but is harmless. Everything else looks consistent: - Notifier subscriptions are unsubscribed in `Dispose`. - Undo on a move captures the old index before the move. - New strings are in both locales. - The docs are updated in the same PR. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 5s · 2 turns · tokens: 73.4k in / 519 out (+12.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-699.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:5cbe095649805bac5ad6324186eba6753daf0f17 -->
opencode-reviewer approved these changes 2026-10-04 15:30:17 +00:00
Dismissed
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Good to merge. Re-review of the board-screen work: the earlier review's notes are all addressed in the head.

  • Subtitle flash — fixed: Subtitle returns the bare card count while _people is empty on a non-open board (BoardPage.razor:215), so "Only you" no longer appears before the grants load; an Everyone board with an empty list reads "Everyone", which is the intended word.
  • Single-column boards — non-issue: IsDeck is _columns is [_, .., var last] (BoardPage.razor:296), which requires two or more columns, so a one-column board never folds and its due dates keep their overdue/soon looks.
  • The leftover column-filter-clear class on the Clear filter row stays; evidently a test hook, harmless.

Also re-checked the newer surfaces: the NavBoard list carried through CarriedBoard and every _boards use updated, the BoardChanged listener guarded to boards already in the list and unsubscribed in Dispose, the [aria-expanded="true"]:has(+ .menu-backdrop) lift working at all three menu placements (the button's next sibling is the backdrop when open in each), board-pagination.js exporting shown() for FindShownColumnAsync with a clamp and a JSException catch, and the move-undo's old index taken among all of the column's cards, matching what MoveCardAsync resolves against. Both new locales get all new strings, including the .one plural. Nothing blocking.


⏱ 4m 21s · 11 steps · $0.0362 · tokens: 139.0k in / 1.6k out (+420.7k cache-read) · Go: 5h 0% · wk 12% · mo 89%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Good to merge. Re-review of the board-screen work: the earlier review's notes are all addressed in the head. - **Subtitle flash** — fixed: `Subtitle` returns the bare card count while `_people` is empty on a non-open board (BoardPage.razor:215), so "Only you" no longer appears before the grants load; an `Everyone` board with an empty list reads "Everyone", which is the intended word. - **Single-column boards** — non-issue: `IsDeck` is `_columns is [_, .., var last]` (BoardPage.razor:296), which requires two or more columns, so a one-column board never folds and its due dates keep their overdue/soon looks. - The leftover `column-filter-clear` class on the Clear filter row stays; evidently a test hook, harmless. Also re-checked the newer surfaces: the `NavBoard` list carried through `CarriedBoard` and every `_boards` use updated, the `BoardChanged` listener guarded to boards already in the list and unsubscribed in `Dispose`, the `[aria-expanded="true"]:has(+ .menu-backdrop)` lift working at all three menu placements (the button's next sibling is the backdrop when open in each), `board-pagination.js` exporting `shown()` for `FindShownColumnAsync` with a clamp and a `JSException` catch, and the move-undo's old index taken among all of the column's cards, matching what `MoveCardAsync` resolves against. Both new locales get all new strings, including the `.one` plural. Nothing blocking. --- ⏱ 4m 21s · 11 steps · $0.0362 · tokens: 139.0k in / 1.6k out (+420.7k cache-read) · Go: 5h 0% · wk 12% · mo 89% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-04T15-25-56-436Z.md) <!-- opencode-reviewed-head:5cbe095649805bac5ad6324186eba6753daf0f17 --> <!-- opencode-verdict:approve -->
Close the phone's card sheet by its Done in the board's phone spec
All checks were successful
CI / build (pull_request) Successful in 42s
60704fb96b
The inspector hides × on a phone; the spec predates it.

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

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/700); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-700.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

I read the diff only. I did not run the build or the e2e suite. The diff was truncated, so I could not check the later CSS or the specs.

My earlier notes: the "Only you" flash is fixed, as before. Subtitle returns just the card count while _people is empty on a non-open board.

Still open, none blocking:

  • Single-column boards: IsDone follows IsDeck. If a one-column board counts as a deck, its due dates never turn red. Please confirm that is intended.
  • Nav count query: GetNavAsync runs one count query per circuit on each BoardChanged for a listed board. That is fine for a small group, but it is the new hot path to watch.
  • Leftover class: column-filter-clear has no CSS any more. It is harmless.

Everything else looks consistent:

  • Notifier subscriptions are removed in Dispose.
  • Undo on a move captures the old index before the move.
  • New strings are in both locales.
  • The docs are updated in the same PR.

🧠 claude-sonnet-5-5 · ⏱ 0m 4s · 2 turns · tokens: 73.8k in / 436 out (+12.2k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. I read the diff only. I did not run the build or the e2e suite. The diff was truncated, so I could not check the later CSS or the specs. My earlier notes: the "Only you" flash is fixed, as before. `Subtitle` returns just the card count while `_people` is empty on a non-open board. Still open, none blocking: - **Single-column boards:** `IsDone` follows `IsDeck`. If a one-column board counts as a deck, its due dates never turn red. Please confirm that is intended. - **Nav count query:** `GetNavAsync` runs one count query per circuit on each `BoardChanged` for a listed board. That is fine for a small group, but it is the new hot path to watch. - **Leftover class:** `column-filter-clear` has no CSS any more. It is harmless. Everything else looks consistent: - Notifier subscriptions are removed in `Dispose`. - Undo on a move captures the old index before the move. - New strings are in both locales. - The docs are updated in the same PR. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 4s · 2 turns · tokens: 73.8k in / 436 out (+12.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-252/run-700.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:60704fb96ba78b4f2d104d339b619d560ee368d6 -->
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-04T15-41-00-725Z.md) — updating every ~5 minutes while the review runs.
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Good to merge. Re-review of the board-screen work: everything from the earlier passes is confirmed resolved in the head.

  • Prior notes, re-checked in the tree: the "Only you" subtitle flash is fixed (Subtitle returns the bare card count while _people is empty on a non-open board, BoardPage.razor:215). Single-column boards are a non-issue: IsDeck is _columns is [_, .., var last] (BoardPage.razor:296), which needs ≥2 columns, so a one-column board never marks its cards done. The column-filter-clear class is a test hook — filter.spec.js:135/246, board.spec.js:556, mobile.spec.js:397 all click it — so it stays despite having no CSS. The BoardChanged count-query hot path remains a watch-item, not a blocker, for a single-tenant deployment of this size.

  • Also verified for nothing being loaded in? the board.spec.js pins are all in the copy as shown, so nothing is loading as done. board-pagination.js exports shown() (line 137) for FindShownColumnAsync, with the clamp and a JSException catch on the C# side. modal-escape.js:31 redirects Escape into an open .menu before any modal backdrop, matching the new clear-filter path. The [aria-expanded="true"]:has(+ .menu-backdrop) lift works at all three placements (button is the previous sibling of the backdrop when open in column, phone-bar and title-bar menus), and Escape on the .column-filter-clear row still closes the parent menu via Menu.OnKeyDown after the row's blur lands on the catcher. Undo-on-move captures the old index before the move and restores through MoveCardAsync with the board id. Both locales carry every new string, including the board.people.one plural.

Nothing blocking.


⏱ 0m 44s · 14 steps · $0.0299 · tokens: 59.5k in / 1.2k out (+642.7k cache-read) · Go: 5h 0% · wk 12% · mo 89%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Good to merge. Re-review of the board-screen work: everything from the earlier passes is confirmed resolved in the head. - **Prior notes, re-checked in the tree:** the "Only you" subtitle flash is fixed (`Subtitle` returns the bare card count while `_people` is empty on a non-open board, `BoardPage.razor:215`). Single-column boards are a non-issue: `IsDeck` is `_columns is [_, .., var last]` (`BoardPage.razor:296`), which needs ≥2 columns, so a one-column board never marks its cards done. The `column-filter-clear` class is a test hook — `filter.spec.js:135/246`, `board.spec.js:556`, `mobile.spec.js:397` all click it — so it stays despite having no CSS. The `BoardChanged` count-query hot path remains a watch-item, not a blocker, for a single-tenant deployment of this size. - **Also verified** for nothing being loaded in? the `board.spec.js` pins are all in the copy as shown, so nothing is loading as done. `board-pagination.js` exports `shown()` (line 137) for `FindShownColumnAsync`, with the clamp and a `JSException` catch on the C# side. `modal-escape.js:31` redirects Escape into an open `.menu` before any modal backdrop, matching the new clear-filter path. The `[aria-expanded="true"]:has(+ .menu-backdrop)` lift works at all three placements (button is the previous sibling of the backdrop when open in column, phone-bar and title-bar menus), and Escape on the `.column-filter-clear` row still closes the parent menu via `Menu.OnKeyDown` after the row's blur lands on the catcher. Undo-on-move captures the old index before the move and restores through `MoveCardAsync` with the board id. Both locales carry every new string, including the `board.people.one` plural. Nothing blocking. --- ⏱ 0m 44s · 14 steps · $0.0299 · tokens: 59.5k in / 1.2k out (+642.7k cache-read) · Go: 5h 0% · wk 12% · mo 89% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-252/run-2026-10-04T15-41-00-725Z.md) <!-- opencode-reviewed-head:60704fb96ba78b4f2d104d339b619d560ee368d6 --> <!-- opencode-verdict:approve -->
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente!252
No description provided.