From 98c253ec7888a87402a2b3fc381621438c98ce17 Mon Sep 17 00:00:00 2001 From: Hitakshi Arora Date: Fri, 10 Jul 2026 16:17:42 +0530 Subject: [PATCH 1/2] =?UTF-8?q?polish(console):=20a11y=20sweep=20=E2=80=94?= =?UTF-8?q?=20keyboard=20rows,=20focus=20rings,=20non-color=20status,=20do?= =?UTF-8?q?uble-submit=20guards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/console/src/app/NetworkMenu.tsx | 2 +- apps/console/src/app/Shell.tsx | 7 ++++--- apps/console/src/screens/AuditLog.tsx | 4 ++-- apps/console/src/screens/Contractors.tsx | 2 +- apps/console/src/screens/Grants.tsx | 2 +- apps/console/src/screens/Pay.tsx | 4 ++-- apps/console/src/screens/Payroll.tsx | 6 +++--- apps/console/src/screens/Treasury.tsx | 4 ++-- apps/console/src/ui/controls.tsx | 25 ++++++++++++++++++++++-- apps/console/src/ui/onchain.tsx | 8 ++++---- 10 files changed, 43 insertions(+), 21 deletions(-) diff --git a/apps/console/src/app/NetworkMenu.tsx b/apps/console/src/app/NetworkMenu.tsx index 9266e42..2d6af0e 100644 --- a/apps/console/src/app/NetworkMenu.tsx +++ b/apps/console/src/app/NetworkMenu.tsx @@ -174,7 +174,7 @@ function InfoRow({ k, v, href, truncate, title }: { k: string; v: string; href?:
{k} {href ? ( - + {v} ) : ( diff --git a/apps/console/src/app/Shell.tsx b/apps/console/src/app/Shell.tsx index ecdf3d5..5afea23 100644 --- a/apps/console/src/app/Shell.tsx +++ b/apps/console/src/app/Shell.tsx @@ -132,7 +132,7 @@ export function Shell() {
{session?.member.name ?? "Signed in"}
-
@@ -151,7 +151,8 @@ export function Shell() {
} diff --git a/apps/console/src/screens/Contractors.tsx b/apps/console/src/screens/Contractors.tsx index e53761c..3d24853 100644 --- a/apps/console/src/screens/Contractors.tsx +++ b/apps/console/src/screens/Contractors.tsx @@ -432,7 +432,7 @@ export function Contractors() { {e.period} {e.txHash ? ( - on-chain receipt + on-chain receipt ) : null}
diff --git a/apps/console/src/screens/Grants.tsx b/apps/console/src/screens/Grants.tsx index 65213eb..3e1ad2e 100644 --- a/apps/console/src/screens/Grants.tsx +++ b/apps/console/src/screens/Grants.tsx @@ -337,7 +337,7 @@ export function Grants() {
setPeriod(e.target.value)} data-testid="att-period" />
-
diff --git a/apps/console/src/screens/Pay.tsx b/apps/console/src/screens/Pay.tsx index 36def37..c7a3207 100644 --- a/apps/console/src/screens/Pay.tsx +++ b/apps/console/src/screens/Pay.tsx @@ -246,11 +246,11 @@ export function Pay() { : "Payment created."} {result.status === "needs_approval" ? ( - ) : result.unpayable ? ( - ) : null} diff --git a/apps/console/src/screens/Payroll.tsx b/apps/console/src/screens/Payroll.tsx index d940ded..3d53a74 100644 --- a/apps/console/src/screens/Payroll.tsx +++ b/apps/console/src/screens/Payroll.tsx @@ -454,10 +454,10 @@ export function Payroll() { ) : null}
- -
@@ -506,7 +506,7 @@ export function Payroll() {
{l.status === "paid" && !l.onChain ? not on-chain : } {l.txHash ? ( - receipt + receipt ) : null}
diff --git a/apps/console/src/screens/Treasury.tsx b/apps/console/src/screens/Treasury.tsx index 589def2..5345acf 100644 --- a/apps/console/src/screens/Treasury.tsx +++ b/apps/console/src/screens/Treasury.tsx @@ -592,7 +592,7 @@ export function Treasury() { Sent on-chain {sendResult.txHash ? ( - + View on explorer ) : null} @@ -675,7 +675,7 @@ function FundReceipt({ txHash }: { txHash?: string }) {
It's now part of your dual-controlled private balance — hidden from the public blockchain.
{txHash ? ( - + View on {NETWORK_LABEL} explorer ) : null} diff --git a/apps/console/src/ui/controls.tsx b/apps/console/src/ui/controls.tsx index 04a4653..b522b1a 100644 --- a/apps/console/src/ui/controls.tsx +++ b/apps/console/src/ui/controls.tsx @@ -134,7 +134,28 @@ export function Td({ children, align = "left", className = "" }: { children?: Re return {children}; } export function Tr({ children, onClick, className = "", ...rest }: { children: ReactNode; onClick?: () => void; className?: string } & Omit, "onClick">) { - return {children}; + // A clickable row is keyboard-operable: focusable, Enter/Space activate it, and it + // shows an inset focus ring. Non-interactive rows stay out of the tab order. + return ( + { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + onClick(); + } + } + : undefined + } + className={`${onClick ? "cursor-pointer outline-none hover:bg-border/30 focus-visible:bg-border/30 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/40" : ""} ${className}`} + {...rest} + > + {children} + + ); } // ---------------------------------------------------------------- tabs @@ -209,7 +230,7 @@ export function CopyButton({ value }: { value: string }) { void copyTextToClipboard(value).then((ok) => setDone(ok ? "copied" : "blocked")); setTimeout(() => setDone("idle"), 1200); }} - className="rounded p-1 text-muted outline-none transition hover:bg-border/50 focus-visible:ring-2 focus-visible:ring-primary/40" + className="inline-flex h-6 w-6 items-center justify-center rounded text-muted outline-none transition hover:bg-border/50 focus-visible:ring-2 focus-visible:ring-primary/40" aria-label={done === "blocked" ? "Copy blocked" : done === "copied" ? "Copied" : "Copy"} title={done === "blocked" ? "Copy blocked. Select the value manually." : done === "copied" ? "Copied" : "Copy"} > diff --git a/apps/console/src/ui/onchain.tsx b/apps/console/src/ui/onchain.tsx index 3942b76..5511b99 100644 --- a/apps/console/src/ui/onchain.tsx +++ b/apps/console/src/ui/onchain.tsx @@ -59,7 +59,7 @@ export function OnChainDetail({ refData, label = "View on-chain" }: { refData: O +
@@ -97,10 +97,10 @@ export function OnChainDetail({ refData, label = "View on-chain" }: { refData: O {refData.root ? : null} {refData.composeHash ? : null} {refData.verified && refData.verifier ? ( - {formatAddress(refData.verifier, 6, 4)} } /> + {formatAddress(refData.verifier, 6, 4)} } /> ) : null} {refData.verified && refData.txHash ? ( - {formatAddress(refData.txHash, 6, 4)} } /> + {formatAddress(refData.txHash, 6, 4)} } /> ) : null}

From 8c92e5a33212e008d1d35f65468d54e7b3a58732 Mon Sep 17 00:00:00 2001 From: Hitakshi Arora Date: Fri, 10 Jul 2026 16:28:28 +0530 Subject: [PATCH 2/2] =?UTF-8?q?fix(console):=20address=20Greptile/CodeRabb?= =?UTF-8?q?it=20on=20the=20a11y=20PR=20=E2=80=94=20clickable=20Tr=20gets?= =?UTF-8?q?=20role=3Dbutton=20(accessible=20name=20from=20cell=20text)=20a?= =?UTF-8?q?nd=20ignores=20clicks/keys=20from=20nested=20controls=20(button?= =?UTF-8?q?s/links/fields=20keep=20their=20own=20action);=20bump=20inline?= =?UTF-8?q?=20copy=20control=20to=20a=2028px=20target?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/console/src/ui/controls.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/console/src/ui/controls.tsx b/apps/console/src/ui/controls.tsx index b522b1a..e8f4941 100644 --- a/apps/console/src/ui/controls.tsx +++ b/apps/console/src/ui/controls.tsx @@ -138,11 +138,24 @@ export function Tr({ children, onClick, className = "", ...rest }: { children: R // shows an inset focus ring. Non-interactive rows stay out of the tab order. return ( { + // Don't hijack a click that landed on a nested control (a button, link, or + // field inside a cell) — let that control run its own action. + if (!(e.target as HTMLElement).closest("button, a, input, select, textarea, label")) onClick(); + } + : undefined + } + // `role=button` gives the clickable row an accessible name from its cell text + // (callers can still override with an explicit aria-label via ...rest). + role={onClick ? "button" : undefined} tabIndex={onClick ? 0 : undefined} onKeyDown={ onClick ? (e) => { + // Only the row itself activates — a focused nested control keeps its keys. + if (e.target !== e.currentTarget) return; if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); @@ -230,7 +243,7 @@ export function CopyButton({ value }: { value: string }) { void copyTextToClipboard(value).then((ok) => setDone(ok ? "copied" : "blocked")); setTimeout(() => setDone("idle"), 1200); }} - className="inline-flex h-6 w-6 items-center justify-center rounded text-muted outline-none transition hover:bg-border/50 focus-visible:ring-2 focus-visible:ring-primary/40" + className="inline-flex h-7 w-7 items-center justify-center rounded text-muted outline-none transition hover:bg-border/50 focus-visible:ring-2 focus-visible:ring-primary/40" aria-label={done === "blocked" ? "Copy blocked" : done === "copied" ? "Copied" : "Copy"} title={done === "blocked" ? "Copy blocked. Select the value manually." : done === "copied" ? "Copied" : "Copy"} >