You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(client): the pickers' colours come from the tokens, not from literals (UI/UX v3 P4f) (#99)
P4e recorded this and held it back one PR so a colour change and a type change
would not land together. It is the last of G11 in `picker.rs`.
The macro picker's purple (a `[0.7, 0.3, 1.0, 1.0]` stripe, a `[0.35, 0.15,
0.50, 1.0]` selected fill and two label greys) and the host manager's green did
not answer to the colour scheme at all — nine built-in schemes, one fixed
purple. None of them had been through P5 either: a fixed fill plus a fixed
label is a fixed contrast ratio, which no scheme can rescue.
- Identity stripes: `accent_primary` (macros) and `semantic_success` (SSH).
- Titles: `text_on(S2).accent` / `.success` — a hue used *as text* goes through
the corrected set, never the flat token.
- Selected row fill: `semantic_fill(tokens, hue, 0.85)`, the recipe the dialogs
use, which walks the blend back toward the surface until the label
`on_surface_text` picks clears 4.5:1. The label is that pair by construction.
- Unselected labels: `text_on(SurfaceLevel::S2).secondary` — the panel
background is `surface_2`, so that is the ground to name.
- The palette's and macro picker's query rows were literal white; they are
`text_on(S2).primary` now.
The purple is dropped on purpose: there is no purple token, and inventing a hue
per overlay is the G11 defect rather than a casualty of fixing it. The host
manager keeps a green identity because the scheme has one, so the old comment
calling that stripe "intentional branding" survives in substance without its
literal.
A test fails on any rgba literal returning to the file. `semantic_fill` became
`pub(super)` to be callable from the pickers; nothing about it changed.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
0.50, 1.0]` selected fill, two label greys) and the host manager's green
508
+
(`[0.2, 0.8, 0.5, 1.0]` and friends) **did not answer to the colour scheme**.
509
+
Nine built-in schemes, one fixed purple.
510
+
- None of them had been through P5. A fixed fill plus a fixed label is a fixed
511
+
contrast ratio, which no scheme can rescue.
512
+
513
+
The mapping:
514
+
515
+
| Was | Now |
516
+
|---|---|
517
+
| macro stripe / title |`accent_primary` / `text_on(S2).accent`|
518
+
| host stripe / title |`semantic_success` / `text_on(S2).success`|
519
+
| selected row fill |`semantic_fill(tokens, hue, 0.85)` — the recipe the dialogs use, which walks the blend back toward the surface until its label clears 4.5:1 |
Copy file name to clipboardExpand all lines: nexterm-client-gpu/CLAUDE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ Guidance for working inside the GPU client crate. The repo-wide rules — langua
19
19
-`settings/hover.rs` — `HoverDwell`, the pointer-dwell timer that gates tooltips (500 ms).
20
20
-`renderer/overlay/settings/footer.rs` — the footer's two links, `↗ Open config.toml` and `↺ Reset category` (UI/UX v3 P4c). Their labels, ramp step, measurement and rects live here and nowhere else: `footer_links` is the one call both `settings/mod.rs` (draws it) and `event_handler/settings_panel_hit.rs` (tests against it) make, so the click target cannot drift from the glyphs. The pure `place_links` takes measured widths, in the shape `place_tooltip` established. Adding a footer link means an entry here, not a formula in the hit-test — that mirrored formula is exactly what kept these two on the cell path until P4c. `accessibility.rs` announces them from the same module (P4d): `Role::Button` at `SETTINGS_FOOTER_OPEN_ID` / `SETTINGS_FOOTER_RESET_ID`, labelled with `footer::open_text()` / `reset_text()` — the link text without its decorative glyph — and the reset node is present only while `category_resettable()`. Before P4d neither link was in the tree at all.
21
21
- `renderer/overlay/infobar.rs` — the InfoBar stack (UI/UX v3 P6): every non-blocking status message — update notice, offline, server error — as one `InfoBarKind` queued on `ClientState.info_bars`, one slot per kind. `bar_rects` is the only function that computes a bar's `y`, and `stack_order` the only one that decides which bar is on top; a new message type is an enum arm, not a fourth builder, and it must not gain stacking arithmetic of its own. Drawn by `ui_verts::build_info_bar_verts` below the tab bar, capped at two visible bars, with `StackLayout::more_label` reporting the rest on the bottom bar. Accessibility is driven from the same enum (P6c): `accessibility::build_info_bar_nodes` emits one `Role::Alert` per queued bar — including bars past the drawn cap — at the stable id `info_bar_node_id(slot)`, so a new slot cannot be added without a node. Motion is per bar (P6d): each carries its own entrance and exit `Timed`, so one bar can fade out while the one under it is still arriving, and `apply_surface_fade` is therefore called *inside* the builder's loop rather than around it. Dismissal never deletes — `ClientState::dismiss_info_bar` starts the exit, `retire_info_bars` drops the bar once it finishes, and `expire_info_bars` applies the info severity's 20 s deadline (`INFO_BAR_TTL`); both are called from the tick in `lifecycle.rs`. A dismissed bar is out of everything but the renderer at once: it takes no key, holds no slot, and leaves the AccessKit tree immediately.
22
-
-`renderer/overlay/picker.rs` — the three list pickers (command palette, host manager, macro picker) plus the SFTP transfer dialog. Rows draw through `draw_picker_run` (UI/UX v3 P4e): one measurement shared by the truncation and the draw, vertically centred in a cell-high row. Two-column rows take their name column from `name_column_width` — measured, not `{:<20}`-padded, because character padding only aligns in a monospace font. The selection marker is its own run so selected and unselected labels start at the same x. Panel sizes and row pitch stay in cells; none of the three pickers is mouse-hit-tested. Their row fills and text colours are still hard-coded literals (G11 residue), so a colour change there is a separate concern from the typography.
22
+
-`renderer/overlay/picker.rs` — the three list pickers (command palette, host manager, macro picker) plus the SFTP transfer dialog. Rows draw through `draw_picker_run` (UI/UX v3 P4e): one measurement shared by the truncation and the draw, vertically centred in a cell-high row. Two-column rows take their name column from `name_column_width` — measured, not `{:<20}`-padded, because character padding only aligns in a monospace font. The selection marker is its own run so selected and unselected labels start at the same x. Panel sizes and row pitch stay in cells; none of the three pickers is mouse-hit-tested. Colour comes from the tokens (P4f): the identity stripe from `accent_primary` / `semantic_success`, the selected row fill from `overlay::util::semantic_fill` (which walks the blend back until `on_surface_text` clears 4.5:1 against it), labels from `text_on(SurfaceLevel::S2)` or `on_surface_text(fill)`. A test fails on any rgba literal returning to the file.
23
23
-`palette.rs` — Command palette (`Ctrl+Shift+P`). Fuzzy search via `SkimMatcherV2`. Sprint 5-7 / Phase 3-3 covers all 25 actions in `execute_action` (Quit, ClosePane, NewWindow, QuickSelect, SetBroadcastOn/Off, …) and persists usage history at `~/.local/state/nexterm/palette_history.json` (atomic write, mode 0600). The pure `rank_actions` function orders by history when the query is empty (last_used desc → use_count desc) and combines fuzzy score with a `history_bonus` (use_count×10 capped at 100, +100 within 1 day, +50 within 1 week) when a query is present. `record_use` records the selection.
24
24
-`host_manager.rs` — SSH host manager UI. `load_history()` / `save_history()` persist connection frequency to `host_history.json`. The `PasswordModal` struct handles the password prompt for `auth_type="password"` hosts.
25
25
-`update_checker.rs` — Polls the GitHub Releases API five seconds after startup. Disabled by `auto_check_update = false`. Results are queued onto `ClientState.info_bars` as `InfoBarKind::UpdateAvailable`; `Esc` dismisses, `Enter` opens the release page while it is the top bar.
0 commit comments