fix(canvas): add WCAG 2.4.7 focus-visible to AgentCommsPanel tabs,

retry button, AttachmentChip download button, mobile tab buttons,
and the Remove button in AttachmentViews.

- AgentCommsPanel.tsx: tab buttons (roving tabindex) and loadError
  retry button now have focus-visible:ring-2
- AttachmentViews.tsx: download button (AttachmentChip) gains
  aria-label + focus-visible; Remove button gains focus-visible
- mobile/components.tsx: mobile tab buttons get className for
  CSS focus-visible (inline styles can't use :focus-visible)
- globals.css: .mobile-tab-btn:focus-visible outline using CSS var

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Molecule AI · core-uiux 2026-05-16 14:42:40 +00:00
parent 0da3e80e75
commit fd2f3c469c
4 changed files with 13 additions and 5 deletions

View File

@ -287,4 +287,11 @@ body {
outline: 2px solid var(--accent, #3b5bdb);
outline-offset: 2px;
}
/* Mobile tab buttons — WCAG 2.4.7 focus-visible */
.mobile-tab-btn:focus-visible {
outline: 2px solid var(--accent, #3b5bdb);
outline-offset: 2px;
border-radius: 6px;
}
}

View File

@ -133,6 +133,7 @@ export function TabBar({
aria-label={t.label}
onClick={() => onChange(t.id)}
onKeyDown={(e) => handleKeyDown(e, idx)}
className="mobile-tab-btn"
style={{
background: "none",
border: "none",

View File

@ -405,7 +405,7 @@ export function AgentCommsPanel({ workspaceId }: { workspaceId: string }) {
</p>
<button
onClick={loadInitial}
className="text-[10px] px-2 py-0.5 rounded bg-red-800/40 text-bad hover:bg-red-700/50 transition-colors"
className="text-[10px] px-2 py-0.5 rounded bg-red-800/40 text-bad hover:bg-red-700/50 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-1"
>
Retry
</button>
@ -610,7 +610,7 @@ function PeerTabButton({
aria-selected={active}
tabIndex={active ? 0 : -1}
onClick={onClick}
className={`shrink-0 px-3 py-1.5 text-[10px] font-medium transition-colors whitespace-nowrap ${
className={`shrink-0 px-3 py-1.5 text-[10px] font-medium transition-colors whitespace-nowrap focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 ${
active
? "border-b-2 border-cyan-500 text-cyan-200"
: "border-b-2 border-transparent text-ink-mid hover:text-ink-mid"

View File

@ -33,7 +33,7 @@ export function PendingAttachmentPill({
<button
onClick={onRemove}
aria-label={`Remove ${file.name}`}
className="ml-0.5 text-ink-mid hover:text-ink transition-colors shrink-0"
className="ml-0.5 text-ink-mid hover:text-ink transition-colors shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
>
<svg width="10" height="10" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
@ -62,8 +62,8 @@ export function AttachmentChip({
return (
<button
onClick={() => onDownload(attachment)}
title={`Download ${attachment.name}`}
className={`flex items-center gap-1.5 rounded-md border px-2 py-1 text-[10px] transition-colors max-w-full ${toneClasses}`}
aria-label={`Download ${attachment.name}`}
className={`flex items-center gap-1.5 rounded-md border px-2 py-1 text-[10px] transition-colors max-w-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 ${toneClasses}`}
>
<FileGlyph className="shrink-0 opacity-70" />
<span className="truncate">{attachment.name}</span>