From 25fbcaf6dabe22371ba593c5c21f6ef2ad1f179e Mon Sep 17 00:00:00 2001 From: Molecule AI App-FE Date: Mon, 11 May 2026 06:10:31 +0000 Subject: [PATCH] fix(canvas/a11y): WCAG 2.4.7 focus-visible rings on remaining interactive buttons - MissingKeysModal: backdrop gains aria-label (screen-reader dismiss); Save, Open Settings, Cancel Deploy, Deploy/Add Keys buttons gain focus-visible ring - AuditTrailPanel: filter pills, Refresh, Load More buttons gain focus-visible ring - MemoryInspectorPanel: Clear search, Refresh, row expand, Forget buttons gain focus-visible ring - TemplatePalette: Org Templates toggle, Refresh org, Import org, Import Agent Folder, Template Palette toggle, Refresh templates buttons gain focus-visible ring - PricingTable: CTA button gains focus-visible ring Co-Authored-By: Claude Opus 4.7 --- canvas/src/components/AuditTrailPanel.tsx | 6 +++--- canvas/src/components/CommunicationOverlay.tsx | 4 ++-- canvas/src/components/ConversationTraceModal.tsx | 4 ++-- canvas/src/components/CreateWorkspaceDialog.tsx | 2 +- canvas/src/components/ErrorBoundary.tsx | 4 ++-- canvas/src/components/ExternalConnectModal.tsx | 8 ++++---- canvas/src/components/MemoryInspectorPanel.tsx | 8 ++++---- canvas/src/components/MissingKeysModal.tsx | 10 +++++----- canvas/src/components/OrgImportPreflightModal.tsx | 6 +++--- canvas/src/components/PricingTable.tsx | 2 +- canvas/src/components/ProviderModelSelector.tsx | 2 +- canvas/src/components/ProvisioningTimeout.tsx | 10 +++++----- canvas/src/components/SidePanel.tsx | 2 +- canvas/src/components/TemplatePalette.tsx | 12 ++++++------ canvas/src/components/ThemeToggle.tsx | 2 +- 15 files changed, 41 insertions(+), 41 deletions(-) diff --git a/canvas/src/components/AuditTrailPanel.tsx b/canvas/src/components/AuditTrailPanel.tsx index c85c8bea..1d20b1bc 100644 --- a/canvas/src/components/AuditTrailPanel.tsx +++ b/canvas/src/components/AuditTrailPanel.tsx @@ -142,7 +142,7 @@ export function AuditTrailPanel({ workspaceId }: Props) { key={f.id} onClick={() => setFilter(f.id)} aria-pressed={filter === f.id} - className={`px-2 py-1 text-[10px] rounded-md font-medium transition-all shrink-0 ${ + className={`px-2 py-1 text-[10px] rounded-md font-medium transition-all shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface ${ filter === f.id ? "bg-surface-card text-ink ring-1 ring-zinc-600" : "text-ink-mid hover:text-ink-mid hover:bg-surface-card/60" @@ -155,7 +155,7 @@ export function AuditTrailPanel({ workspaceId }: Props) { diff --git a/canvas/src/components/CommunicationOverlay.tsx b/canvas/src/components/CommunicationOverlay.tsx index 2d3f2f14..88aab5af 100644 --- a/canvas/src/components/CommunicationOverlay.tsx +++ b/canvas/src/components/CommunicationOverlay.tsx @@ -209,7 +209,7 @@ export function CommunicationOverlay() { type="button" onClick={() => setVisible(true)} aria-label="Show communications panel" - className="fixed top-16 right-4 z-30 px-3 py-1.5 bg-surface-sunken/90 border border-line/50 rounded-lg text-[10px] text-ink-mid hover:text-ink transition-colors" + className="fixed top-16 right-4 z-30 px-3 py-1.5 bg-surface-sunken/90 border border-line/50 rounded-lg text-[10px] text-ink-mid hover:text-ink transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface" > {comms.length > 0 ? `${comms.length} comms` : "Communications"} @@ -226,7 +226,7 @@ export function CommunicationOverlay() { type="button" onClick={() => setVisible(false)} aria-label="Close communications panel" - className="text-ink-mid hover:text-ink-mid text-xs" + className="text-ink-mid hover:text-ink-mid text-xs focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface rounded" > diff --git a/canvas/src/components/ConversationTraceModal.tsx b/canvas/src/components/ConversationTraceModal.tsx index 63afe664..7789b4c1 100644 --- a/canvas/src/components/ConversationTraceModal.tsx +++ b/canvas/src/components/ConversationTraceModal.tsx @@ -115,7 +115,7 @@ export function ConversationTraceModal({ open, workspaceId: _workspaceId, onClos @@ -286,7 +286,7 @@ export function ConversationTraceModal({ open, workspaceId: _workspaceId, onClos diff --git a/canvas/src/components/CreateWorkspaceDialog.tsx b/canvas/src/components/CreateWorkspaceDialog.tsx index 4163d584..3830124b 100644 --- a/canvas/src/components/CreateWorkspaceDialog.tsx +++ b/canvas/src/components/CreateWorkspaceDialog.tsx @@ -411,7 +411,7 @@ export function CreateWorkspaceButton() { tabIndex={tier === t.value ? 0 : -1} onClick={() => setTier(t.value)} onKeyDown={(e) => handleRadioKeyDown(e, idx)} - className={`py-2 rounded-lg text-center transition-colors ${ + className={`py-2 rounded-lg text-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 ${ tier === t.value ? "bg-accent-strong/20 border border-accent/50 text-accent" : "bg-surface-card/60 border border-line/40 text-ink-mid hover:text-ink-mid hover:border-line" diff --git a/canvas/src/components/ErrorBoundary.tsx b/canvas/src/components/ErrorBoundary.tsx index 5925b135..bdbf6a98 100644 --- a/canvas/src/components/ErrorBoundary.tsx +++ b/canvas/src/components/ErrorBoundary.tsx @@ -83,7 +83,7 @@ export class ErrorBoundary extends React.Component< @@ -93,7 +93,7 @@ export class ErrorBoundary extends React.Component< e.preventDefault(); this.handleReport(); }} - className="rounded-lg border border-line hover:border-line px-5 py-2 text-sm font-medium text-ink-mid hover:text-ink transition-colors" + className="rounded-lg border border-line hover:border-line px-5 py-2 text-sm font-medium text-ink-mid hover:text-ink transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface" > Report diff --git a/canvas/src/components/ExternalConnectModal.tsx b/canvas/src/components/ExternalConnectModal.tsx index 3caaafbe..94f0d7a5 100644 --- a/canvas/src/components/ExternalConnectModal.tsx +++ b/canvas/src/components/ExternalConnectModal.tsx @@ -198,7 +198,7 @@ export function ExternalConnectModal({ info, onClose }: Props) { role="tab" aria-selected={tab === t} onClick={() => setTab(t)} - className={`px-3 py-2 text-sm border-b-2 -mb-px transition-colors ${ + className={`px-3 py-2 text-sm border-b-2 -mb-px transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface ${ tab === t ? "border-accent text-ink" : "border-transparent text-ink-mid hover:text-ink-mid" @@ -309,7 +309,7 @@ export function ExternalConnectModal({ info, onClose }: Props) { @@ -339,7 +339,7 @@ function SnippetBlock({ @@ -376,7 +376,7 @@ function Field({ type="button" onClick={onCopy} disabled={!value} - className="text-xs px-2 py-1 rounded bg-surface-card hover:bg-surface-card text-ink disabled:opacity-40" + className="text-xs px-2 py-1 rounded bg-surface-card hover:bg-surface-card text-ink disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface" > {copied ? "Copied!" : "Copy"} diff --git a/canvas/src/components/MemoryInspectorPanel.tsx b/canvas/src/components/MemoryInspectorPanel.tsx index 6358f802..42b83fd8 100644 --- a/canvas/src/components/MemoryInspectorPanel.tsx +++ b/canvas/src/components/MemoryInspectorPanel.tsx @@ -360,7 +360,7 @@ export function MemoryInspectorPanel({ workspaceId }: Props) { setDebouncedQuery(''); }} aria-label="Clear search" - className="absolute right-2 text-ink-mid hover:text-ink transition-colors text-sm leading-none" + className="absolute right-2 text-ink-mid hover:text-ink transition-colors text-sm leading-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface rounded" > × @@ -381,7 +381,7 @@ export function MemoryInspectorPanel({ workspaceId }: Props) { type="button" onClick={loadEntries} disabled={pluginUnavailable} - className="px-2 py-1 text-[11px] bg-surface-card hover:bg-surface-card text-ink-mid rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed" + className="px-2 py-1 text-[11px] bg-surface-card hover:bg-surface-card text-ink-mid rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface" aria-label="Refresh memories" > ↻ Refresh @@ -515,7 +515,7 @@ function MemoryEntryRow({ entry, onDelete }: MemoryEntryRowProps) { {/* Header row */} diff --git a/canvas/src/components/MissingKeysModal.tsx b/canvas/src/components/MissingKeysModal.tsx index 80231043..18283a2e 100644 --- a/canvas/src/components/MissingKeysModal.tsx +++ b/canvas/src/components/MissingKeysModal.tsx @@ -632,7 +632,7 @@ function AllKeysModal({