From 14cdb96189fc13d538436f55f7bb16f4e545a2d6 Mon Sep 17 00:00:00 2001 From: gadgethd <111318106+gadgethd@users.noreply.github.com> Date: Thu, 6 Aug 2026 21:08:49 +0000 Subject: [PATCH] feat(owner): clickable identity cards replace node dropdown selector --- frontend/src/pages/OwnerPortalPage.tsx | 27 ++++++++++------------ frontend/src/pages/owner-portal.css | 31 +++++++++++--------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/frontend/src/pages/OwnerPortalPage.tsx b/frontend/src/pages/OwnerPortalPage.tsx index 2cc62a2..3d68362 100644 --- a/frontend/src/pages/OwnerPortalPage.tsx +++ b/frontend/src/pages/OwnerPortalPage.tsx @@ -304,21 +304,7 @@ export const OwnerPortalPage: React.FC = () => { {dashboard.nodes.length > 1 ? ( -
- - -
+

Select a repeater by clicking its identity card below.

) : null}
{dashboard.nodes.map((node) => ( @@ -326,6 +312,17 @@ export const OwnerPortalPage: React.FC = () => { key={node.canonicalId} className={`owner-node-identity${node.node_id === selectedNodeId ? ' owner-node-identity--selected' : ''}`} data-canonical-id={node.canonicalId} + onClick={() => setSelectedNodeId(node.node_id)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + setSelectedNodeId(node.node_id); + } + }} + role="button" + tabIndex={0} + aria-pressed={node.node_id === selectedNodeId} + title={dashboard.nodes.length > 1 ? `View ${node.name ?? 'this node'}` : undefined} >
{node.name ?? 'Unnamed node'} diff --git a/frontend/src/pages/owner-portal.css b/frontend/src/pages/owner-portal.css index e4e3f63..9fcdc5d 100644 --- a/frontend/src/pages/owner-portal.css +++ b/frontend/src/pages/owner-portal.css @@ -315,24 +315,6 @@ font-size: 11px; font-family: var(--font-mono); } -.owner-select { - margin: 12px 0 16px; - display: flex; - flex-direction: column; - gap: 6px; -} -.owner-select label { - color: var(--text-secondary); - font-size: 12px; -} -.owner-select__input { - max-width: 360px; - background: var(--bg-panel); - border: 1px solid var(--border); - border-radius: var(--radius); - color: var(--text-primary); - padding: 8px 10px; -} .owner-node-identities { display: grid; gap: 10px; @@ -343,9 +325,22 @@ border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-panel-alt); + cursor: pointer; + transition: border-color 120ms ease, background-color 120ms ease; +} +.owner-node-identity:hover { + border-color: var(--text-secondary); +} +.owner-node-identity:focus-visible { + outline: 2px solid rgba(0, 196, 255, 0.55); + outline-offset: 2px; } .owner-node-identity--selected { border-color: rgba(0, 196, 255, 0.55); + background: color-mix(in srgb, var(--bg-panel-alt) 80%, rgba(0, 196, 255, 0.06)); +} +.owner-node-identity--selected:hover { + border-color: rgba(0, 196, 255, 0.8); } .owner-node-identity__head { display: flex;