From b56696d89866adc81887c574665d2145bdf06a37 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 28 Aug 2026 17:55:12 +0200 Subject: [PATCH] =?UTF-8?q?agent:=20LoginFlow=20=E2=80=94=20one=20card,=20?= =?UTF-8?q?matching=20Dropdown's=20popup=20visual=20language?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mara: "reuse the popup component for the login, the floating separate panels should be one card" — the old markup's .agent-status-overlay > * rule boxed every direct-child

/

separately, a faithful port of app.js's el().append()-per-line but not what a hand-authored component should do. Wraps each state's content in one .login-card div instead, styled to match Dropdown's .ui-dropdown (@hive/shared) background/border/radius/shadow values exactly, so this reads as the same popup family as every other floating surface in the app rather than a one-off. Not the Dropdown component itself — its options.map render is menu-item-shaped, not a fit for a login form + output pane. agent.css's .agent-status-overlay > * rule is untouched (app.js's still-live markup depends on it verbatim until the index.html cutover) — .login-card coexists with it rather than editing it, correctly overriding on equal specificity since main.css loads after agent.css. --- .../agent/src/components/LoginFlow.css | 25 ++++++++++++++++++ .../agent/src/components/LoginFlow.tsx | 26 +++++++++++++------ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 frontend/packages/agent/src/components/LoginFlow.css diff --git a/frontend/packages/agent/src/components/LoginFlow.css b/frontend/packages/agent/src/components/LoginFlow.css new file mode 100644 index 00000000..c2ce6018 --- /dev/null +++ b/frontend/packages/agent/src/components/LoginFlow.css @@ -0,0 +1,25 @@ +/* .login-card — one elevated-surface card for the whole login-recovery + overlay, replacing the old markup's per-`

`/`` boxing + (`agent.css`'s `.agent-status-overlay > *`, still needed there + verbatim since app.js's still-live markup depends on it until the + index.html cutover — this file coexists with it rather than editing + it). Same visual language as `Dropdown`'s `.ui-dropdown` + (`@hive/shared/dropdown/Dropdown.css`) — background/border/radius/ + shadow values match exactly, so this reads as the same "popup" family + as every other floating surface in the app, just laid out as a static + block instead of an anchored, position:absolute menu (that part of + `Dropdown` is specific to hanging under a trigger and doesn't apply + here — `.agent-status-overlay` already centres this card itself). */ +.login-card { + display: flex; + flex-direction: column; + gap: 0.6em; + background: var(--bg-elev); + border: 1px solid var(--border); + border-radius: 0.5em; + box-shadow: 0 0.4em 1em rgba(0, 0, 0, 0.35); + padding: 1em 1.2em; +} +.login-card > * { + margin: 0; +} diff --git a/frontend/packages/agent/src/components/LoginFlow.tsx b/frontend/packages/agent/src/components/LoginFlow.tsx index 83fe45a7..c74c3c1b 100644 --- a/frontend/packages/agent/src/components/LoginFlow.tsx +++ b/frontend/packages/agent/src/components/LoginFlow.tsx @@ -3,13 +3,23 @@ // as real functional UI, not just a status label: an agent whose // credentials got rotated (or hit `/logout`) has NO other way back // online, so this is load-bearing, not cosmetic. Reuses agent.css's -// existing `.agent-status-overlay`/`.status-needs-login`/`.btn-login`/ -// `.loginform`/`.loginform-reveal` rules verbatim (same class names as -// the old markup) — no component-local CSS needed, matching Header.tsx's -// same reuse pattern. +// `.status-needs-login`/`.btn-login`/`.loginform`/`.loginform-reveal` +// rules verbatim (same class names as the old markup). +// +// mara (screenshot review): "reuse the popup component for the login, +// the floating separate panels should be one card." The old markup's +// `.agent-status-overlay > *` rule boxed every direct-child `

`/ +// `` separately (a fine translation of `el().append()`-per-line, +// but not what a hand-authored component should do) — this renders one +// `.login-card` instead, styled with the same "elevated surface" look +// `Dropdown`'s `.ui-dropdown` already established (`@hive/shared/ +// dropdown/Dropdown.css`), not `Dropdown` itself (its `options.map` +// render is menu-item-shaped, not a generic content container — not a +// fit for a login form + output pane). import { useState } from 'preact/hooks'; import type { SessionView } from '../types.js'; import { postLoginStart, postLoginCode, postLoginCancel } from '../lib/loginAction.js'; +import './LoginFlow.css'; function LoginIdle({ onStarted }: { onStarted: () => void }) { const [busy, setBusy] = useState(false); @@ -27,7 +37,7 @@ function LoginIdle({ onStarted }: { onStarted: () => void }) { } return ( - <> +

); } @@ -79,7 +89,7 @@ function LoginInProgress({ session, onDone }: { session: SessionView | null; onD } return ( - <> + ); }