fix(desktop): titlebar icon-row baseline + native cursor convention - #79
Conversation
The macOS window has a single titlebar row (traffic-light center), but the three top icon clusters each hardcoded their own vertical geometry in different containers, so the row jumped ~8px when the sidebar collapsed/ expanded and the left/right clusters never lined up. Add --maka-titlebar-control-safe-top (vertical companion to --maka-titlebar-control-safe-left, = traffic-light center) and --maka-detail-panel-inset-top, then anchor the sidebar header strip, the collapsed strip, and the workspace top-actions to that single baseline. The shared variable is the single source of truth, so the clusters can no longer drift apart. Also refresh the stale desktop-icon contract assertion to the actual PR #75 padded 1024x1024 icon (it still asserted the pre-#75 1254x1254 / >1.4MB edge-filled icon, failing on main). localized-main-shell-contract.test.ts now requires the shared-baseline vars instead of the old per-strip magic numbers. Claude-Session: https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t
… on links) Native macOS/Windows reserve the pointing-hand cursor for hyperlinks; buttons, rows, tabs, toggles, and other controls use the default arrow. The renderer had drifted: ~66 controls set `cursor: pointer` ad hoc while the titlebar icons kept the arrow, so hover was inconsistent (the sidebar showed a hand, the titlebar an arrow). Remove `cursor: pointer` from every control in styles.css (59) and maka-tokens.css (7); keep it only on .maka-markdown-link-internal (a link-styled in-app nav button). External links stay <a> with the UA pointer; the broken/non-clickable variant has none. Matches Apple HIG for the macOS-native feel: hand = link, arrow = control. Claude-Session: https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t
The cursor sweep removed ~66 ad-hoc `cursor: pointer` from controls but left no guard — the original inconsistency came from exactly this kind of unwatched drift. Add a static-analysis contract: every `cursor: pointer` must sit on a link selector (name contains `link`); controls may not reintroduce the hand. Mirrors the app-region-hygiene contract style. The live look-and-feel (arrow on controls, hand on links) is verified in a real Electron window. Claude-Session: https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t
Review (P3) flagged the titlebar baseline as over-engineered: a second explanatory variable (--maka-detail-panel-inset-top) plus per-cluster calc algebra (`- 5px - 12px` / `- 6px - 12px`), with the contract test pinning the full calc strings. That widens the drift surface the single baseline was meant to remove. - Drop --maka-detail-panel-inset-top; keep only the one baseline --maka-titlebar-control-safe-top. Each of the three clusters now references that baseline minus a single per-container correction constant (17/17/18px), documented inline. - Loosen the contract assertions from the exact calc string to the invariant that matters: each cluster references var(--maka-titlebar-control-safe-top). The correction constant is geometry, free to tune without a test edit. No behavioral change — all three clusters still center at y=20px. Full desktop suite green (1529). Claude-Session: https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t
Real-window smoke (PR-DESKTOP-SMOKE-0)Report: Human native-behavior checks — all 12 PASS, manually verified by the author (macOS): clean launch / no crash, resize from all 4 edges + 4 corners, titlebar drag moves the window, rows/buttons/inputs/modal controls do not drag the window, Search modal closes via close button + backdrop + Esc, focus trap + return-to-trigger, resize still works with the modal open, and switching sidebar modules shows no ErrorBoundary / React hook error. These were recorded via Programmatic layer: window visible + resizable + movable, renderer mounted, no ErrorBoundary — all PASS. 2 programmatic checks FAIL — pre-existing, NOT introduced by this PR: The script's overall 🤖 Recorded with Claude Code — https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t |
… comments
Address two non-blocking review notes on the titlebar/cursor PR:
- cursor-convention-contract: replace the `/link/` name match — which let any
selector whose name merely contains "link" (e.g. `.fake-link-button`)
reintroduce `cursor: pointer` — with an exact allowlist. Only
`.maka-markdown-link-internal` may carry the hand cursor; maka-tokens.css must
carry none. Drop the 98-line hand-rolled depth parser for a small regex that
walks each `cursor: pointer` back to its selector (still catches at-rule
nesting).
- styles.css: keep the `--maka-titlebar-control-safe-top` baseline and the three
`calc(...)` placements, but compress their multi-line explanatory comments to
one line each. No new Layout.tsx / module.
Verified: `npm -w @maka/desktop test` (1528 pass); an injected
`.fake-link-button { cursor: pointer }` now fails the gate while
`.maka-markdown-link-internal` passes.
Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
) Reshape the desktop titlebar/cursor UI: - align the titlebar icon clusters (sidebar header, collapsed strip, workspace top-actions) to one vertical baseline via a single source-of-truth var - adopt the native cursor convention: arrow on controls, hand only on links, guarded by a static contract test with an exact `.maka-markdown-link-internal` allowlist - trim the baseline's explanatory comments to one line each Claude-Session: https://claude.ai/code/session_01VWXzHoyncpGYuwbaDEDizD
What & why
Two small, independent titlebar / control polish fixes (one commit each).
1. Titlebar icon row jumps when the sidebar toggles (
3776ad1a)The macOS window has a single titlebar row (traffic-light center), but the three top icon clusters each hardcoded their own vertical geometry in different containers, so the row jumped ~8px when the sidebar collapsed/expanded and the left vs right clusters never lined up.
--maka-titlebar-control-safe-top(vertical companion to the existing--maka-titlebar-control-safe-left, = traffic-light center, mirroring main'sMAIN_WINDOW_TRAFFIC_LIGHT_POSITION.y) and--maka-detail-panel-inset-top.main).2. Native cursor convention (
7c2eb633)Native macOS/Windows reserve the pointing-hand cursor for hyperlinks; buttons, rows, tabs, and toggles use the default arrow. The renderer had drifted — ~66 controls set
cursor: pointerad hoc while the titlebar icons used the arrow, so hover was inconsistent (sidebar showed a hand, titlebar an arrow).cursor: pointerfrom every control (styles.css59 +maka-tokens.css7); keep it only on.maka-markdown-link-internal(a link-styled in-app nav button). External links stay<a>with the UA pointer.Testing
npm -w @maka/desktop test→ 1526/1526 green (including the now-fixed icon contract).getBoundingClientRect): all three titlebar icon clusters center at exactly y=20px (the traffic-light center) in both sidebar states — left cluster20 → 20across collapse/expand (no jump), left/right aligned20 = 20. Computed cursor: in-DOM controls reportdefault(arrow), links (a[href], external markdown link) reportpointer(hand).cursor-convention-contract.test.tsassertscursor: pointeronly ever sits on a link selector, so a control can't silently reclaim the hand.-webkit-app-regiondrag declarations (the app-region-hygiene contract still passes). The humansmoke:real-windowgate (native drag/resize + modal focus perapps/desktop/tests/smoke.md) is still recommended before merge — those behaviors are unchanged by this PR but the gate is a hard project requirement.Notes
main.tsxmarkup change, so the localized-main-shell markup contract is untouched.main(d7e21957); clean.Layout.tsxshell band that lifts the titlebar into one full-width frame row (would absorb the tab bar + chat header onto the same baseline), and removing the now-confirmed dead.maka-nav-window/.maka-window-drag-stripCSS.https://claude.ai/code/session_01KtNufPddivogjCYaQijf5t