a11y: keyboard-operable editor chrome + topbar aria-labels

Clickable <div> rows/tiles (page list, layer tree, template cards, asset
picker grid) now expose role="button", a tab stop, and Enter/Space
activation via a shared clickableProps() helper, matching their existing
onClick behavior. TopBar icon-only controls (device switcher, undo/redo,
save, publish, templates, code, preview, back) gain aria-label alongside
their existing title tooltips.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 14:50:50 -07:00
parent a036843728
commit 46ebd253f3
7 changed files with 100 additions and 12 deletions
+10 -6
View File
@@ -123,7 +123,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
<nav className="topbar">
<div className="topbar-left">
{isWHP && (
<a href={whpConfig!.backUrl} className="topbar-btn back-btn">
<a href={whpConfig!.backUrl} className="topbar-btn back-btn" aria-label="Back to Panel">
<i className="fa fa-arrow-left" /> Back to Panel
</a>
)}
@@ -141,6 +141,8 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
className={`device-btn ${device === d ? 'active' : ''}`}
onClick={() => onDeviceChange(d)}
title={d.charAt(0).toUpperCase() + d.slice(1)}
aria-label={d.charAt(0).toUpperCase() + d.slice(1)}
aria-pressed={device === d}
>
<i className={`fa ${d === 'desktop' ? 'fa-desktop' : d === 'tablet' ? 'fa-tablet' : 'fa-mobile'}`} />
</button>
@@ -149,20 +151,20 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
</div>
<div className="topbar-right">
<button className="topbar-btn" onClick={() => actions.history.undo()} disabled={!canUndo} title="Undo">
<button className="topbar-btn" onClick={() => actions.history.undo()} disabled={!canUndo} title="Undo" aria-label="Undo">
<i className="fa fa-undo" />
</button>
<button className="topbar-btn" onClick={() => actions.history.redo()} disabled={!canRedo} title="Redo">
<button className="topbar-btn" onClick={() => actions.history.redo()} disabled={!canRedo} title="Redo" aria-label="Redo">
<i className="fa fa-repeat" />
</button>
<span className="topbar-divider" />
<button className="topbar-btn" title="Templates" onClick={() => setTemplateModalOpen(true)}>
<button className="topbar-btn" title="Templates" aria-label="Templates" onClick={() => setTemplateModalOpen(true)}>
<i className="fa fa-th-large" /> Templates
</button>
<button className="topbar-btn" title="Custom Head Code" onClick={() => setHeadCodeModalOpen(true)}>
<button className="topbar-btn" title="Custom Head Code" aria-label="Custom Head Code" onClick={() => setHeadCodeModalOpen(true)}>
<i className="fa fa-code" /> Code
</button>
<button className="topbar-btn" title="Preview" onClick={() => {
<button className="topbar-btn" title="Preview" aria-label="Preview" onClick={() => {
try {
const serialized = query.serialize();
import('../../utils/html-export').then(({ exportToHtml, exportBodyHtml }) => {
@@ -255,6 +257,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
onClick={handleSave}
disabled={saveStatus === 'saving'}
title="Save Draft"
aria-label="Save Draft"
>
{saveStatus === 'saving' ? (
<><i className="fa fa-spinner fa-spin" /> Saving...</>
@@ -269,6 +272,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange }) => {
onClick={handlePublish}
disabled={publishStatus === 'publishing' || saveStatus === 'saving'}
title="Publish to live site"
aria-label="Publish to live site"
>
{publishStatus === 'publishing' ? (
<><i className="fa fa-spinner fa-spin" /> Publishing...</>