feat(widgets): v4 request-origin primitives (E1 · #181) - #189
Merged
Conversation
Add the v4-added `widgets.rs` vocabulary so no later view hand-rolls it, per the Implementer Contract in epic #179 ("reuse, never hand-roll"): - `key_cap(cap, armed, …)` — PLATFORM-AWARE (`⌘` on macOS, `Ctrl` elsewhere via `std::env::consts::OS`), the `⌘↵` chord as ONE cap; armed = amber border+text, no fill. Pure `primary_mod_label`/`key_cap_label` helpers are unit-tested. - `origin_header(origin, trust, theme)` — the request-origin rail: You (round mark, amber), Agent (cyan mark + handle), Dapp (neutral favicon + domain), each with an optional state-color trust badge. A dapp is a NEUTRAL identity + a state-color badge, never a third signal color. - `action_tag(kind, …)` — the SWAP/SHIELD/SEND/SUPPLY uppercase chip. - `status_glyph(state, theme)` — one status vocabulary (success check / danger x / amber+cyan loader ring for pending+live / muted minus). No `clock` icon ships → the ring carries pending; color separates awaiting-you (amber) from agent (cyan). - `kv_row`, `page_header`, `meta_rail`/`meta_section`/`meta_obj`, `balance_diff`, `stop_brake` — the DESIGN-referenced primitives the v4 views need. tokens.rs gains the object-size ladder (`MARK_MD`/`MARK_LG`), `ICON_MD`, `ALPHA_TINT`, and `RAIL_W`, each with its first consumer here. Composite widgets take `theme: &Theme` and resolve colors internally (the convention DESIGN §Build notes sanctions); atomic ones take explicit `Hsla` and stay pure/testable. Colors via `theme.*` + `theme::amber/agent` only (no raw hex); sizes via the tokens module; money via `money.rs`; reuses `identity_mark` / `section_label` / `divider`. E1 is scoped to `widgets.rs` + `tokens.rs` and must not touch the E2–E7 views that consume these, so each primitive carries a scoped `#[allow(dead_code)]` + a `// reason:` naming its consuming child (the `money::usd` precedent); E2–E7 drop the allow as they wire the real call site. DoD: `cargo fmt --all --check` clean; `just check` green (both feature configs); `cargo test --workspace` green (4 new widget unit tests). No dep changes. Refs #179. Closes #181.
This was referenced Jul 3, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements E1 · v4 widget foundation of the v4 request-origin epic. Adds the v4
widgets.rsvocabulary + supporting
tokens.rsso no later view (E2–E7) hand-rolls a primitive — the epic'sImplementer Contract rule "reuse, never hand-roll."
Closes #181. Refs #179. Golden ref:
designs/deckard-v4.html; spec:docs/research/13-v4-build-plan.md(E1).What's added (
widgets.rs)The v4 request-origin primitives the issue names, plus the DESIGN-referenced-but-missing ones:
key_cap(cap, armed, …)⌘on macOS,Ctrlelsewhere viastd::env::consts::OS; the⌘↵chord renders as one cap;armed= amber border + amber text, no fillorigin_header(origin, trust, theme)action_tag(kind, …)SWAP/SHIELD/SEND/SUPPLYuppercase chip (neutral, not a signal color)status_glyph(state, theme)kv_row·page_header·meta_rail/meta_section/meta_obj·balance_diff·stop_brakeagent_marktokens.rsgains the object-size ladder (MARK_MD/MARK_LG),ICON_MD,ALPHA_TINT, andRAIL_W, each landing with its first consumer here (an unusedpub constis a build error).Contract compliance
theme.*+theme::amber/agentonly — no raw hex.tokensmodule + gpui utilities — no magicpx()that duplicates a named token.money.rs(balance_diffrenders each signed amount throughmoney::money).identity_mark/section_label/divider; a sharedmonogram()helper backsidentity_mark+agent_mark.Hsla(pure, unit-tested); composite ones take&Theme(the convention DESIGN §Build notes sanctions).A note on "consumed by ≥1 view" vs "widgets.rs + tokens.rs only"
The AC asks each primitive be consumed by a view, but E1 is scoped to
widgets.rs+tokens.rsandmust not touch the E2–E7 views that consume these. I resolved this the way the codebase already
does (
money::usd): every primitive carries a scoped#[allow(dead_code)]+ a// reason:namingits consuming child, and the pure logic is unit-tested. Each E2–E7 PR drops the allow as it wires the
real call site. No view file was edited.
Adversarial review
Ran a multi-dimension review (fidelity / DESIGN-tokens / reuse / correctness / scope) + a codex
cross-model pass, then verified each finding. 2 real findings, both fixed in this branch:
the squircle. Fixed by adding
agent_mark: a handle-aware bordered cyan squircle (matches thegolden
.squircle; showsKforKyoto, not a fixedA)..12instead of theamber-only
.14(alpha-tint-warm). Fixed to usetheme::amber_tint.Definition of Done
cargo fmt --all --check— cleanjust check— green (workspace +--features tray+ signerddev-signerd-bin, all-D warnings)cargo test --workspace— green; 4 new widget unit tests incl.key_capassertingCtrlon a forced-Linux path and⌘on macOSCargo.toml/Cargo.lockuntouched)Screenshots
None — E1 is the widget layer, not a view (the issue's golden-ref fidelity note: "No view / see AC").
Nothing is wired into a running screen yet; the primitives become visually demoable as E2–E7 consume them.
Do not touch (honored)
No view files (
send/shield/swap/activity/settings/commit/transaction) touched — diff iswidgets.rs+tokens.rsonly.