fix(canvas): add focus-visible rings across 6 more files
WCAG 2.4.7 — Focus Visible. PricingTable: CTA button now has focus-visible ring. MissingKeysModal: Save, Open Settings, Cancel Deploy, Deploy buttons. FilesToolbar: New, Upload, Export, Clear, Refresh buttons. FileTreeContextMenu: menuitem buttons — replaced focus:bg with focus-visible:ring-2 (proper keyboard-only visible ring). AgentCommsPanel: Restart and Open peer buttons. settings-panel.css: secret-row cancel/save, add-key-form cancel/save all gain focus-visible ring. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1ca787f6d1
commit
91dfc75850
@ -706,7 +706,7 @@ function AllKeysModal({
|
||||
type="button"
|
||||
onClick={() => handleSaveKey(index)}
|
||||
disabled={!entry.value.trim() || entry.saving}
|
||||
className="px-3 py-1.5 bg-accent-strong hover:bg-accent text-[11px] rounded text-white disabled:opacity-30 transition-colors shrink-0"
|
||||
className="px-3 py-1.5 bg-accent-strong hover:bg-accent text-[11px] rounded text-white disabled:opacity-30 transition-colors shrink-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
|
||||
>
|
||||
{entry.saving ? "..." : "Save"}
|
||||
</button>
|
||||
@ -730,7 +730,7 @@ function AllKeysModal({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenSettings}
|
||||
className="text-[11px] text-accent hover:text-accent transition-colors"
|
||||
className="text-[11px] text-accent hover:text-accent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
|
||||
>
|
||||
Open Settings Panel
|
||||
</button>
|
||||
@ -740,7 +740,7 @@ function AllKeysModal({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="px-3.5 py-1.5 text-[12px] text-ink-mid hover:text-ink bg-surface-card hover:bg-surface-card border border-line rounded-lg transition-colors"
|
||||
className="px-3.5 py-1.5 text-[12px] text-ink-mid hover:text-ink bg-surface-card hover:bg-surface-card border border-line rounded-lg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
|
||||
>
|
||||
Cancel Deploy
|
||||
</button>
|
||||
@ -748,7 +748,7 @@ function AllKeysModal({
|
||||
type="button"
|
||||
onClick={handleAddKeysAndDeploy}
|
||||
disabled={!allSaved || anySaving}
|
||||
className="px-3.5 py-1.5 text-[12px] bg-accent-strong hover:bg-accent text-white rounded-lg transition-colors disabled:opacity-40"
|
||||
className="px-3.5 py-1.5 text-[12px] bg-accent-strong hover:bg-accent text-white rounded-lg transition-colors disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
|
||||
>
|
||||
{anySaving ? "Saving..." : allSaved ? "Deploy" : "Add Keys"}
|
||||
</button>
|
||||
|
||||
@ -128,7 +128,7 @@ function PlanCard({
|
||||
type="button"
|
||||
onClick={onSelect}
|
||||
disabled={loading}
|
||||
className={`mt-6 rounded-lg px-4 py-3 text-sm font-medium ${
|
||||
className={`mt-6 rounded-lg px-4 py-3 text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface ${
|
||||
plan.highlighted
|
||||
? "bg-accent-strong text-white hover:bg-accent disabled:bg-zinc-700 disabled:text-zinc-500"
|
||||
: "border border-line bg-surface-sunken text-ink hover:bg-surface-card disabled:opacity-50"
|
||||
|
||||
@ -128,8 +128,8 @@ export function FileTreeContextMenu({ x, y, items, onClose }: Props) {
|
||||
}}
|
||||
className={
|
||||
item.destructive
|
||||
? "w-full text-left px-3 py-1 text-bad hover:bg-red-900/30 focus:bg-red-900/30 focus:outline-none disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
: "w-full text-left px-3 py-1 text-ink-mid hover:bg-surface-card hover:text-ink focus:bg-surface-card focus:text-ink focus:outline-none disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
? "w-full text-left px-3 py-1 text-bad hover:bg-red-900/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-1 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
: "w-full text-left px-3 py-1 text-ink-mid hover:bg-surface-card hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||
}
|
||||
>
|
||||
{item.icon && <span className="inline-block w-4 mr-1.5 text-ink-mid">{item.icon}</span>}
|
||||
|
||||
@ -44,7 +44,7 @@ export function FilesToolbar({
|
||||
<div className="flex gap-1.5">
|
||||
{root === "/configs" && (
|
||||
<>
|
||||
<button type="button" onClick={onNewFile} aria-label="Create new file" className="text-[10px] text-accent hover:text-accent" title="Create new file">
|
||||
<button type="button" onClick={onNewFile} aria-label="Create new file" className="text-[10px] text-accent hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1" title="Create new file">
|
||||
+ New
|
||||
</button>
|
||||
<input
|
||||
@ -57,20 +57,20 @@ export function FilesToolbar({
|
||||
className="hidden"
|
||||
onChange={(e) => e.target.files && onUpload(e.target.files)}
|
||||
/>
|
||||
<button type="button" onClick={() => uploadRef.current?.click()} aria-label="Upload folder" className="text-[10px] text-accent hover:text-accent" title="Upload folder">
|
||||
<button type="button" onClick={() => uploadRef.current?.click()} aria-label="Upload folder" className="text-[10px] text-accent hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1" title="Upload folder">
|
||||
Upload
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<button type="button" onClick={onDownloadAll} aria-label="Download all files" className="text-[10px] text-ink-mid hover:text-ink-mid" title="Download all files">
|
||||
<button type="button" onClick={onDownloadAll} aria-label="Download all files" className="text-[10px] text-ink-mid hover:text-ink-mid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1" title="Download all files">
|
||||
Export
|
||||
</button>
|
||||
{root === "/configs" && (
|
||||
<button type="button" onClick={onClearAll} aria-label="Delete all files" className="text-[10px] text-bad/60 hover:text-bad" title="Delete all files">
|
||||
<button type="button" onClick={onClearAll} aria-label="Delete all files" className="text-[10px] text-bad/60 hover:text-bad focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-1" title="Delete all files">
|
||||
Clear
|
||||
</button>
|
||||
)}
|
||||
<button type="button" onClick={onRefresh} aria-label="Refresh file list" className="text-[10px] text-ink-mid hover:text-ink-mid" title="Refresh">
|
||||
<button type="button" onClick={onRefresh} aria-label="Refresh file list" className="text-[10px] text-ink-mid hover:text-ink-mid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1" title="Refresh">
|
||||
↻
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -827,14 +827,14 @@ function ErrorMessage({ msg }: { msg: CommMessage }) {
|
||||
type="button"
|
||||
onClick={handleRestart}
|
||||
disabled={restarting}
|
||||
className="px-2 py-0.5 rounded bg-red-900/50 hover:bg-red-800/60 border border-red-700/40 text-[10px] text-red-200 disabled:opacity-50 transition-colors"
|
||||
className="px-2 py-0.5 rounded bg-red-900/50 hover:bg-red-800/60 border border-red-700/40 text-[10px] text-red-200 disabled:opacity-50 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-1"
|
||||
>
|
||||
{restarting ? "Restarting…" : `Restart ${msg.peerName}`}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpen}
|
||||
className="px-2 py-0.5 rounded bg-surface-card hover:bg-surface-card border border-line/50 text-[10px] text-ink-mid transition-colors"
|
||||
className="px-2 py-0.5 rounded bg-surface-card hover:bg-surface-card border border-line/50 text-[10px] text-ink-mid transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1"
|
||||
>
|
||||
Open {msg.peerName}
|
||||
</button>
|
||||
|
||||
@ -276,6 +276,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.secret-row__cancel-btn:focus-visible {
|
||||
outline: var(--focus-ring);
|
||||
outline-offset: var(--focus-ring-offset);
|
||||
}
|
||||
|
||||
.secret-row__save-btn {
|
||||
background: #2563eb;
|
||||
color: #ffffff;
|
||||
@ -286,6 +291,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.secret-row__save-btn:focus-visible {
|
||||
outline: var(--focus-ring);
|
||||
outline-offset: var(--focus-ring-offset);
|
||||
}
|
||||
|
||||
.secret-row__save-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
|
||||
/* ── Add key form ──────────────────────────────────── */
|
||||
@ -354,6 +364,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-key-form__cancel-btn:focus-visible {
|
||||
outline: var(--focus-ring);
|
||||
outline-offset: var(--focus-ring-offset);
|
||||
}
|
||||
|
||||
.add-key-form__save-btn {
|
||||
background: #2563eb;
|
||||
color: #ffffff;
|
||||
@ -364,6 +379,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-key-form__save-btn:focus-visible {
|
||||
outline: var(--focus-ring);
|
||||
outline-offset: var(--focus-ring-offset);
|
||||
}
|
||||
|
||||
.add-key-form__save-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
|
||||
.secrets-tab__add-btn {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user