Speak the v2 draft's one language on every page: one type scale, three button sizes, inspector dialogs #261

Merged
Grandiras merged 3 commits from ui-v2-consistency into main 2026-10-05 19:21:37 +00:00
Owner

The second half of the v2 polishing pass. I compared every screen with the Figma draft: the screens' structure matched, but the details did not. About 100 v1 rem font sizes survived beside the v2 scale, so the same role rendered at a different size on each page. Buttons came in 24.6 to 48px, with labels at 12 to 14.4px. What's new and Report a problem still had v1 dialog chrome. With a card docked, the inspector covered the board's last column.

What changes

  • One type scale, in px. Every font size outside Home is now on the draft's steps: 30/36 large titles (34/41 on a phone), 22, 17, 14, 13.5, 13, 12, 11. No rem font size is left in app.css. Distinct font sizes went from 21 to 13 across the audited pages.
  • Three button sizes. The shared rule is the draft's regular button (34px, Button type, 13.5/16 at weight 600). .btn-sm is 28px for inline actions in groups and rows, and the new .btn-lg is 44px for the auth panel and a phone's sheets. The per-page copies are gone (Add card, Add column/tag, the states' actions, comment buttons, the deleted-board banner, reconnect, the calendar's subscribe buttons, Show earlier, Clear, Move, the deck toggle, the modal footers): each now uses a class in the markup. On a phone a .btn-sm keeps its look and gets a 44px tap area through ::after, the same pattern .row-delete already uses. Button heights went from eleven to three.
  • Every dialog looks like the inspector. .modal-header, .modal-body and .modal-footer have no hairlines, a 17/22 title, a 32px round × (now one CloseButton component, where five dialogs drew it by hand) and actions at the foot on the right. What's new puts its timeline in one white group; the Report a problem text box is the card description's field; the calendar's day sheet and subscription panel match.
  • The board narrows beside the inspector. From 1100px, columns shrink to fit beside a docked card, as in the draft (248px each at 1440), down to 240px. Past that the board scrolls sideways. board.spec.js asserts it.
  • Smaller fixes:
    • Board settings labelled its Delete group and button "Delete card" (it reused modal.delete); they now say "Delete" (settings.delete.short).
    • A deleted board's title is 30/36 like every other large title.
    • The toast is the draft's 44px pill.
    • The tablet top bar's controls are all 34px.
    • The wordmark and the base avatar take the draft's sizes.
    • An invalid var(--border) is fixed.
    • Dead CSS removed (net −390 lines).
    • Home's New board and new-board form now use the shared button rule instead of copying its sizes.

Left as they are

  • Chips keep their heights (22/24/30): the 22 and 30 are the draft's tag chips.
  • The phone search's Cancel and the phone calendar's 40px head buttons, which line up with the title, as their comments say.

Changelog

No new line. All of this polishes unreleased v2 work that Changelog.Unreleased already describes ("every page redrawn", "a calmer card panel"), and members have not seen the inconsistent state.

Docs

  • frontend.md: the button sizes and the type scale as rules, and the v2 status line.
  • ui.md: every dialog speaks the inspector's language, and the inspector narrows the board.
  • calendar.md: its dialogs.

Verified

  • tools/verify.sh green (600 unit tests).
  • Full Playwright suite 162/162 on the agent's commit; the result for the head commit follows in a comment.
  • Before and after DOM audits across about 60 states (1440, 820 and 390, light and dark), plus screenshots.

🤖 Generated with Claude Code

The second half of the v2 polishing pass. I compared every screen with the Figma draft: the screens' structure matched, but the details did not. About 100 v1 `rem` font sizes survived beside the v2 scale, so the same role rendered at a different size on each page. Buttons came in 24.6 to 48px, with labels at 12 to 14.4px. *What's new* and *Report a problem* still had v1 dialog chrome. With a card docked, the inspector covered the board's last column. ## What changes - **One type scale, in px.** Every font size outside Home is now on the draft's steps: 30/36 large titles (34/41 on a phone), 22, 17, 14, 13.5, 13, 12, 11. No `rem` font size is left in `app.css`. Distinct font sizes went from 21 to 13 across the audited pages. - **Three button sizes.** The shared rule is the draft's regular button (34px, Button type, 13.5/16 at weight 600). `.btn-sm` is 28px for inline actions in groups and rows, and the new `.btn-lg` is 44px for the auth panel and a phone's sheets. The per-page copies are gone (Add card, Add column/tag, the states' actions, comment buttons, the deleted-board banner, reconnect, the calendar's subscribe buttons, Show earlier, Clear, Move, the deck toggle, the modal footers): each now uses a class in the markup. On a phone a `.btn-sm` keeps its look and gets a 44px tap area through `::after`, the same pattern `.row-delete` already uses. Button heights went from eleven to three. - **Every dialog looks like the inspector.** `.modal-header`, `.modal-body` and `.modal-footer` have no hairlines, a 17/22 title, a 32px round × (now one `CloseButton` component, where five dialogs drew it by hand) and actions at the foot on the right. *What's new* puts its timeline in one white group; the *Report a problem* text box is the card description's field; the calendar's day sheet and subscription panel match. - **The board narrows beside the inspector.** From 1100px, columns shrink to fit beside a docked card, as in the draft (248px each at 1440), down to 240px. Past that the board scrolls sideways. `board.spec.js` asserts it. - **Smaller fixes:** - Board settings labelled its Delete group and button "Delete card" (it reused `modal.delete`); they now say "Delete" (`settings.delete.short`). - A deleted board's title is 30/36 like every other large title. - The toast is the draft's 44px pill. - The tablet top bar's controls are all 34px. - The wordmark and the base avatar take the draft's sizes. - An invalid `var(--border)` is fixed. - Dead CSS removed (net −390 lines). - Home's New board and new-board form now use the shared button rule instead of copying its sizes. ## Left as they are - Chips keep their heights (22/24/30): the 22 and 30 are the draft's tag chips. - The phone search's Cancel and the phone calendar's 40px head buttons, which line up with the title, as their comments say. ## Changelog No new line. All of this polishes unreleased v2 work that `Changelog.Unreleased` already describes ("every page redrawn", "a calmer card panel"), and members have not seen the inconsistent state. ## Docs - `frontend.md`: the button sizes and the type scale as rules, and the v2 status line. - `ui.md`: every dialog speaks the inspector's language, and the inspector narrows the board. - `calendar.md`: its dialogs. ## Verified - `tools/verify.sh` green (600 unit tests). - Full Playwright suite 162/162 on the agent's commit; the result for the head commit follows in a comment. - Before and after DOM audits across about 60 states (1440, 820 and 390, light and dark), plus screenshots. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The screens matched the draft's structure but not its details: v1 rem sizes
survived beside the v2 scale, buttons came in six heights, and What's new,
Report a problem and the calendar's two dialogs kept their v1 chrome.

- Buttons are the draft's three sizes: regular 34px, .btn-sm 28px, .btn-lg
  44px. The base carries the regular size, so the per-page copies (Add card,
  the add buttons, empty states, comments, the deleted banner, reconnect,
  subscribe) and the dialog footer's own button rules are gone. A phone's
  small button keeps its look and takes a 44px target.
- Every dialog wears the inspector's language: no hairlines, a 17px title and
  a 32px round close, groups on the panel, actions at the foot.
- Type is the draft's scale in px everywhere outside Home: link cards, chips,
  faces, the assign menu, the auth pages, states, the tablet top bar and its
  flyout, toasts (the draft's 44px pill), the wordmark (15.5px).
- With a card docked, the columns narrow to fit beside the inspector (down to
  240px) instead of running under it.
- A deleted board's name is the 30px large title, where its title bar had it.
- Board settings' Delete group says Delete, not "Delete card".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Share the dialogs' ×, and let Home's buttons take the shared sizes
All checks were successful
CI / build (pull_request) Successful in 33s
627de7b45e
One CloseButton for the five dialogs that drew the same × by hand. Home's New
board and its form now ride the shared regular button instead of copying its
sizes, and the phone's large titles are in px like the rest of the scale.

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-261/run-2026-10-05T18-53-12-781Z.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/757); 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-261/run-757.md) — updating every ~5 minutes while the task runs.
claude-reviewer approved these changes 2026-10-05 18:53:43 +00:00
Dismissed
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

A coherent consolidation. The shared button sizes, the CloseButton component, the dialog chrome and the type scale all read consistently. I checked that the removed CSS has no remaining users in the markup: .modal-footer button, .calendar-subscribe-action, .calendar-day-sheet-close, .board-deleted-home, .login-action and .invite-link are all gone. Every modal footer button now carries an explicit class. The remaining .field wrappers sit inside the login or request cards, which have their own input styling.

Minor remarks, not blocking:

  • The phone .btn-sm::after tap area relies on position: relative, which the shared button rule sets. Any .btn-sm that doesn't also carry a shared button class would anchor its hit area to an ancestor. All the call sites I saw do carry one.
  • .column-deck-more hand-copies the small-button size because it isn't a .btn-sm. That is acceptable, and the comment explains it.
  • The new board e2e assertion only checks the last column against the panel when there are three or fewer columns. That is sensible.
  • I did not run the app or the test suite.

🧠 claude-sonnet-5-5 · ⏱ 0m 12s · 4 turns · tokens: 58.0k in / 1.1k out (+150.1k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. A coherent consolidation. The shared button sizes, the `CloseButton` component, the dialog chrome and the type scale all read consistently. I checked that the removed CSS has no remaining users in the markup: `.modal-footer button`, `.calendar-subscribe-action`, `.calendar-day-sheet-close`, `.board-deleted-home`, `.login-action` and `.invite-link` are all gone. Every modal footer button now carries an explicit class. The remaining `.field` wrappers sit inside the login or request cards, which have their own input styling. Minor remarks, not blocking: - The phone `.btn-sm::after` tap area relies on `position: relative`, which the shared button rule sets. Any `.btn-sm` that doesn't also carry a shared button class would anchor its hit area to an ancestor. All the call sites I saw do carry one. - `.column-deck-more` hand-copies the small-button size because it isn't a `.btn-sm`. That is acceptable, and the comment explains it. - The new board e2e assertion only checks the last column against the panel when there are three or fewer columns. That is sensible. - I did not run the app or the test suite. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 12s · 4 turns · tokens: 58.0k in / 1.1k out (+150.1k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-261/run-757.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:627de7b45e66cac2943a5cd4359f2ab8a517d688 -->
Author
Owner

Full Playwright suite on an isolated stack: 162/162 on the head, 627de7b.

🤖 Generated with Claude Code

Full Playwright suite on an isolated stack: **162/162** on the head, `627de7b`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
opencode-reviewer approved these changes 2026-10-05 19:11:48 +00:00
Dismissed
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

A careful, coherent pass: the three-size button system is real (base rule plus .btn-sm/.btn-lg, all per-page copies now class-driven in markup), the inspector dialog language is applied to What's new, Report a problem and both calendar panels, and the locale key (settings.delete.short) is added in both en and de. I checked the risky spots: every modal-footer/modal-header button has a class, the five former hand-drawn × are all CloseButton, no markup or e2e spec still references a deleted class (invite-created, composer-error, changelog-body, calendar-day-sheet-close, login-action are all gone from markup too), the leftover .field wrappers all sit inside .login-card, which still styles its own inputs, and the inspector column-narrowing composes correctly with the ≥960px flex: 1 1 320px / min-width: 320px rule — the 240px floor only bites past three columns, where the board scrolls, exactly what the new board.spec.js assertions pin. The phone .btn-sm::after target math (28 + 2×8 = 44) matches the mobile test. Docs read as accurate to the CSS. Two non-blocking notes: the deck toggle's hover is now the ungated .btn-flat:hover (it was previously inside @media (hover: hover) because a tap leaves :hover stuck on touch — the comment above .column-deck-more:hover still says so), and prose says 247px in ui.md vs 248px in the PR text. Neither blocks.


⏱ 18m 35s · 66 steps · $0.1798 · tokens: 524.1k in / 3.5k out (+3105.9k cache-read) · Go: 5h 1% · wk 3% · mo 92%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. A careful, coherent pass: the three-size button system is real (base rule plus `.btn-sm`/`.btn-lg`, all per-page copies now class-driven in markup), the inspector dialog language is applied to What's new, Report a problem and both calendar panels, and the locale key (`settings.delete.short`) is added in both en and de. I checked the risky spots: every `modal-footer`/`modal-header` button has a class, the five former hand-drawn × are all `CloseButton`, no markup or e2e spec still references a deleted class (`invite-created`, `composer-error`, `changelog-body`, `calendar-day-sheet-close`, `login-action` are all gone from markup too), the leftover `.field` wrappers all sit inside `.login-card`, which still styles its own inputs, and the inspector column-narrowing composes correctly with the ≥960px `flex: 1 1 320px / min-width: 320px` rule — the 240px floor only bites past three columns, where the board scrolls, exactly what the new `board.spec.js` assertions pin. The phone `.btn-sm::after` target math (28 + 2×8 = 44) matches the mobile test. Docs read as accurate to the CSS. Two non-blocking notes: the deck toggle's hover is now the ungated `.btn-flat:hover` (it was previously inside `@media (hover: hover)` because a tap leaves `:hover` stuck on touch — the comment above `.column-deck-more:hover` still says so), and prose says 247px in `ui.md` vs 248px in the PR text. Neither blocks. --- ⏱ 18m 35s · 66 steps · $0.1798 · tokens: 524.1k in / 3.5k out (+3105.9k cache-read) · Go: 5h 1% · wk 3% · mo 92% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-261/run-2026-10-05T18-53-12-781Z.md) <!-- opencode-reviewed-head:627de7b45e66cac2943a5cd4359f2ab8a517d688 --> <!-- opencode-verdict:approve -->
@ -303,0 +316,4 @@
color: var(--brand-ink);
}
.btn-flat:hover:not(:disabled) { background: var(--brand-glow); }
Collaborator

Minor: this hover is now ungated, and it absorbed .column-deck-toggle:hover, which was previously inside @media (hover: hover) precisely because a tap leaves :hover stuck on touch (the comment above .column-deck-more:hover still documents that). On a phone, tapping a .btn-flat — the deck toggle, the due Clear, Show earlier — will leave the brand-glow tint on it until the next tap. Pre-existing pattern for other .btn-flats, so not a blocker, but wrapping this one hover (or the two it inherited) in the same (hover: hover) guard would keep the behaviour the old code deliberately had.

Minor: this hover is now ungated, and it absorbed `.column-deck-toggle:hover`, which was previously inside `@media (hover: hover)` precisely because a tap leaves `:hover` stuck on touch (the comment above `.column-deck-more:hover` still documents that). On a phone, tapping a `.btn-flat` — the deck toggle, the due Clear, Show earlier — will leave the brand-glow tint on it until the next tap. Pre-existing pattern for other `.btn-flat`s, so not a blocker, but wrapping this one hover (or the two it inherited) in the same `(hover: hover)` guard would keep the behaviour the old code deliberately had.
Keep a flat button's hover tint off touch, where a tap leaves it on
All checks were successful
CI / build (pull_request) Successful in 40s
8dec109015
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-261/run-2026-10-05T19-13-42-241Z.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/758); 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-261/run-758.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

This is a re-review. My earlier pass approved with only non-blocking remarks, so nothing blocking was outstanding. I did not run the app or the tests; I read the diff only.

  • The shared button sizes, the CloseButton component, the unified dialog chrome and the px type scale are applied consistently.
  • Every modal footer button now carries an explicit class, which the removal of .modal-footer button requires.
  • The new board e2e assertion and the .board:has(~ .modal-backdrop-dockable) > .column floor look sound.
  • Docs are updated alongside the code.

Non-blocking notes: a .btn-sm needs one of the shared button classes for its phone ::after tap area to anchor to it (it relies on position: relative). .column-deck-more hand-copies the small-button size, and a comment explains why.


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

✅ **Verdict: approve** — no blocking issues found. This is a re-review. My earlier pass approved with only non-blocking remarks, so nothing blocking was outstanding. I did not run the app or the tests; I read the diff only. - The shared button sizes, the `CloseButton` component, the unified dialog chrome and the px type scale are applied consistently. - Every modal footer button now carries an explicit class, which the removal of `.modal-footer button` requires. - The new board e2e assertion and the `.board:has(~ .modal-backdrop-dockable) > .column` floor look sound. - Docs are updated alongside the code. Non-blocking notes: a `.btn-sm` needs one of the shared button classes for its phone `::after` tap area to anchor to it (it relies on `position: relative`). `.column-deck-more` hand-copies the small-button size, and a comment explains why. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 4s · 2 turns · tokens: 56.8k in / 376 out (+12.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-261/run-758.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:8dec109015020d4422215611f8e07d68dca75b0b -->
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Good to merge. Re-review: my one inline note from the last pass is resolved — .btn-flat:hover is now inside @media (hover: hover) with the comment, so taps on touch no longer leave the tint stuck (and .column-deck-more:hover remains guarded the same way). The other spot-checked risks still hold: all 21 .btn-sm call sites carry a shared base class so the phone ::after tap area anchors correctly; no markup or spec references the deleted classes (composer-error, calendar-day-sheet-close, board-deleted-home, login-action, invite-created...); the remaining .field wrappers all sit inside .login-card, which retains its own field rules; the invalid var(--border) use is fixed (--border-2); --scrim is a defined token. The new e2e assertions (viewport pinned to 1440×900, column floor at 239.5px, last column beside the panel when ≤3 columns) match the CSS behavior. Docs (frontend.md, ui.md, calendar.md) accurately describe the button sizes, type scale and inspector narrowing. Non-blocking nit: docs/ui.md says 247px where the PR text says 248px for the draft's column width at 1440 — a rounding of the same figure, not a code issue.


⏱ 0m 28s · 12 steps · $0.0224 · tokens: 52.4k in / 1.9k out (+431.2k cache-read) · Go: 5h 1% · wk 3% · mo 92%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Good to merge. Re-review: my one inline note from the last pass is resolved — `.btn-flat:hover` is now inside `@media (hover: hover)` with the comment, so taps on touch no longer leave the tint stuck (and `.column-deck-more:hover` remains guarded the same way). The other spot-checked risks still hold: all 21 `.btn-sm` call sites carry a shared base class so the phone `::after` tap area anchors correctly; no markup or spec references the deleted classes (`composer-error`, `calendar-day-sheet-close`, `board-deleted-home`, `login-action`, `invite-created`...); the remaining `.field` wrappers all sit inside `.login-card`, which retains its own field rules; the invalid `var(--border)` use is fixed (`--border-2`); `--scrim` is a defined token. The new e2e assertions (viewport pinned to 1440×900, column floor at 239.5px, last column beside the panel when ≤3 columns) match the CSS behavior. Docs (frontend.md, ui.md, calendar.md) accurately describe the button sizes, type scale and inspector narrowing. Non-blocking nit: `docs/ui.md` says 247px where the PR text says 248px for the draft's column width at 1440 — a rounding of the same figure, not a code issue. --- ⏱ 0m 28s · 12 steps · $0.0224 · tokens: 52.4k in / 1.9k out (+431.2k cache-read) · Go: 5h 1% · wk 3% · mo 92% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-261/run-2026-10-05T19-13-42-241Z.md) <!-- opencode-reviewed-head:8dec109015020d4422215611f8e07d68dca75b0b --> <!-- opencode-verdict:approve -->
Grandiras deleted branch ui-v2-consistency 2026-10-05 19:21:37 +00:00
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!261
No description provided.