From 92b9e6732785758e2900f7124494fe9edfeb821d Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 12 Aug 2026 17:25:38 +0200 Subject: [PATCH] frontend: unify pill/chip/badge shape into shared CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per mara's steer on #3053 ("chip/pill/badge is the same if you squint ... theme unification is part of the goal ... make it common css instead of component, thats fine. but make them look unified"): shared CSS, not a JS component. New @hive/shared/pill.css defines the shape (border/border-radius/ padding/font-size/letter-spacing — color stays per-site, that's the meaningful semantic part) in two tiers matching what was already organically in use: `.hive-pill` (primary state chips) and `.hive-pill-sm` (secondary meta chips). Every pre-existing classname that drew its own copy of this shape (dashboard's `.badge` family, agent's `.status-badge`/`.state-badge`/`.header-pill`/`.ctx-badge`/ `.model-chip`/`.effort-chip`) is folded straight into the same selector groups, so no markup or JS changes were needed anywhere — every render call site keeps constructing the exact same classnames it always did. Most visible consequence: dashboard's `.badge` family moves from its own shape (2px square corners, uppercase, tighter padding) onto the shared rounded-pill shape + agent's "sm" tier sizing, matching the "look unified" ask directly. `npm run build` clean across all three packages. --- frontend/packages/agent/src/agent.css | 37 +++++---------- frontend/packages/dashboard/src/common.css | 14 +++--- frontend/packages/shared/package.json | 1 + frontend/packages/shared/src/pill.css | 53 ++++++++++++++++++++++ 4 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 frontend/packages/shared/src/pill.css diff --git a/frontend/packages/agent/src/agent.css b/frontend/packages/agent/src/agent.css index 411ed31a..c9770ec5 100644 --- a/frontend/packages/agent/src/agent.css +++ b/frontend/packages/agent/src/agent.css @@ -6,6 +6,10 @@ agent SUB-pages (stats, screen) the same back-link nav the dashboard's standalone pages use. The live terminal page keeps its own header. */ @import "@hive/shared/chrome.css"; +/* Shared pill/chip/badge shape (the "extract pill component" issue, + resolved as shared CSS rather than a JS component) — see pill.css + itself for the classnames it covers. */ +@import "@hive/shared/pill.css"; /* Themed dialog/toast component CSS (modal.js) now lives in each component's own shadow root (adoptedStyleSheets), not a global stylesheet — nothing to @import here any more. */ @@ -302,14 +306,11 @@ h2, h3 { /* Header pill — inbox / loose-ends triggers. Compact, count-prominent. */ .header-pill { + /* border/radius/padding/font-size/letter-spacing: shared pill.css */ background: transparent; - border: 1px solid var(--purple-dim); + border-color: var(--purple-dim); color: var(--fg); font-family: inherit; - font-size: 0.85em; - letter-spacing: 0.04em; - border-radius: 999px; - padding: 0.25em 0.7em; display: inline-flex; align-items: center; gap: 0.4em; @@ -604,12 +605,9 @@ pre.diff { } .model-chip, .effort-chip { + /* border/radius/padding/font-size/letter-spacing: shared pill.css */ display: inline-block; - padding: 0.1em 0.6em; - border: 1px solid var(--purple-dim); - border-radius: 999px; - font-size: 0.78em; - letter-spacing: 0.04em; + border-color: var(--purple-dim); } .model-chip { color: var(--cyan); } .effort-chip { color: var(--amber); } @@ -618,13 +616,10 @@ pre.diff { breakdown on hover. Sized/coloured like a peer of model-chip so the state row reads as one row of chrome. */ .ctx-badge { + /* border/radius/padding/font-size/letter-spacing: shared pill.css */ display: inline-block; - padding: 0.1em 0.6em; - border: 1px solid var(--purple-dim); - border-radius: 999px; + border-color: var(--purple-dim); color: var(--green); - font-size: 0.78em; - letter-spacing: 0.04em; cursor: default; white-space: pre-line; } @@ -633,12 +628,8 @@ pre.diff { `.state-badge` / `.model-chip` so the state row stays visually uniform; colour communicates the actual reachability state. */ .status-badge { + /* border/radius/padding/font-size/letter-spacing: shared pill.css */ display: inline-block; - padding: 0.25em 0.8em; - border: 1px solid; - border-radius: 999px; - font-size: 0.85em; - letter-spacing: 0.05em; } .status-badge.status-loading { color: var(--muted); border-color: var(--purple-dim); } .status-badge.status-online { color: var(--green); border-color: var(--green); @@ -672,12 +663,8 @@ pre.diff { `:disabled` opacity treatment lives on the shared `.overflow-item:disabled` rule). */ .state-badge { + /* border/radius/padding/font-size/letter-spacing: shared pill.css */ display: inline-block; - padding: 0.25em 0.8em; - border: 1px solid; - border-radius: 999px; - font-size: 0.85em; - letter-spacing: 0.05em; transition: color 280ms ease, border-color 280ms ease, box-shadow 280ms ease, background 280ms ease; } diff --git a/frontend/packages/dashboard/src/common.css b/frontend/packages/dashboard/src/common.css index d8746d73..4d026641 100644 --- a/frontend/packages/dashboard/src/common.css +++ b/frontend/packages/dashboard/src/common.css @@ -4,6 +4,10 @@ @import "@hive/shared/terminal.css"; @import "@hive/shared/tabs.css"; @import "@hive/shared/chrome.css"; +/* Shared pill/chip/badge shape (the "extract pill component" issue, + resolved as shared CSS rather than a JS component) — see pill.css + itself for the classnames it covers. */ +@import "@hive/shared/pill.css"; /* ─── global typography ───────────────────────────────────────────── Element-level rules shared across all three pages (index, flow, @@ -54,15 +58,11 @@ code { /* ─── status badges ───────────────────────────────────────────────── .badge base + semantic colour variants. Used on container rows - (tabs.js) and build-log rows (logs.js). */ + (tabs.js) and build-log rows (logs.js). Shape (border/radius/padding/ + font-size/letter-spacing) is shared with the agent UI's pill/chip + family — see @hive/shared/pill.css. */ .badge { display: inline-block; - padding: 0.05em 0.5em; - border: 1px solid; - border-radius: 2px; - font-size: 0.75em; - letter-spacing: 0.08em; - text-transform: uppercase; } .badge-warn { color: var(--amber); border-color: var(--amber); diff --git a/frontend/packages/shared/package.json b/frontend/packages/shared/package.json index 478a1cf2..5dc89c8d 100644 --- a/frontend/packages/shared/package.json +++ b/frontend/packages/shared/package.json @@ -16,6 +16,7 @@ "./base.css": "./src/base.css", "./terminal.css": "./src/terminal/terminal.css", "./chrome.css": "./src/chrome.css", + "./pill.css": "./src/pill.css", "./forms.js": "./src/forms.js", "./prefs.js": "./src/prefs.js", "./dom.js": "./src/dom.js", diff --git a/frontend/packages/shared/src/pill.css b/frontend/packages/shared/src/pill.css new file mode 100644 index 00000000..de1254d7 --- /dev/null +++ b/frontend/packages/shared/src/pill.css @@ -0,0 +1,53 @@ +/* Shared pill/chip/badge shape — the "extract pill component" issue, + resolved as shared CSS rather than a JS component. Every inline + status/count chip across the dashboard + per-agent UI shares its + structural shape (border, radius, padding, font-size, letter- + spacing) from here instead of re-declaring the same values per + site; only the per-semantic COLOR (ok/fail/warn/…) stays local to + each page's own CSS — this file is shape only. + + Two size tiers, matching what was already organically in use rather + than inventing a third: + .hive-pill — primary state chips (agent status/state/header pills) + .hive-pill-sm — secondary meta chips (agent model/effort/ctx chips, + the dashboard's whole `.badge` family) + + Every pre-existing classname that drew its own copy of this shape + (`.status-badge`/`.state-badge`/`.header-pill`/`.ctx-badge`/ + `.model-chip`/`.effort-chip`/`.badge`) is folded into the same + selector groups below, so no markup changes were needed anywhere to + pick this up — `display` stays per-site (inline-block for plain + text, inline-flex for header-pill's icon+label+count layout), since + that's a layout concern, not part of the pill's shape identity. */ + +.hive-pill, +.hive-pill-sm, +.status-badge, +.state-badge, +.header-pill, +.ctx-badge, +.model-chip, +.effort-chip, +.badge { + border: 1px solid; + border-radius: 999px; +} + +.hive-pill, +.status-badge, +.state-badge, +.header-pill { + padding: 0.25em 0.8em; + font-size: 0.85em; + letter-spacing: 0.05em; +} + +.hive-pill-sm, +.ctx-badge, +.model-chip, +.effort-chip, +.badge { + padding: 0.1em 0.6em; + font-size: 0.78em; + letter-spacing: 0.04em; +}