a11y: keyboard focus indicators + canvas label (0.59.0)

- the site had focus styles only on inputs, so keyboard navigation was
  invisible across every button, link, nav item, card and CTA
- add a global :focus-visible ring (cyan, gold for primary CTAs) — shows for
  keyboard users only, follows each element's radius
- label the decorative tavern canvas (role=img + aria-label); its overlay
  hotspots remain separately focusable/labeled
- verified live: Tab focuses a nav button with a 2px cyan ring, matches
  :focus-visible, canvas announced as 'Animated tavern scene'
This commit is contained in:
artheru 2026-06-10 08:21:16 +08:00
parent 6a8fc0a5c0
commit 3ddbc76dfc
5 changed files with 8 additions and 4 deletions

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0e0a14" />
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
<meta name="version" content="0.58.0-docscode" />
<meta name="version" content="0.59.0-a11y" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

View File

@ -1,6 +1,6 @@
{
"name": "amerc-site",
"version": "0.58.0-docscode",
"version": "0.59.0-a11y",
"private": true,
"type": "module",
"scripts": {

View File

@ -7,7 +7,7 @@ import Account from './Account.jsx';
import TavernGame from './TavernGame.jsx';
import { api } from './api.js';
const RELEASE = '0.58.0-docscode';
const RELEASE = '0.59.0-a11y';
const NAV = [
{ id: 'home', label: 'Tavern' },

View File

@ -114,7 +114,7 @@ export default function TavernGame({ onHotspot, stats }) {
return (
<div className="gm-room">
<canvas ref={canvasRef} width={W} height={H} className="gm-canvas" />
<canvas ref={canvasRef} width={W} height={H} className="gm-canvas" role="img" aria-label="Animated tavern scene" />
{!ready && <div className="gm-loading">loading tavern</div>}
<div className="gm-overlay">
<button className="gm-hot" style={{ left: '38%', top: '1%', width: '24%', height: '16%' }} onClick={() => onHotspot?.('agents')} title="Browse Agents (screen)" />

View File

@ -1422,3 +1422,7 @@ button {
.docs-copy { position: absolute; top: 8px; right: 8px; font-family: Inter, ui-sans-serif, system-ui, sans-serif; font-size: 11px; padding: 3px 10px; border-radius: 6px; background: #1b2536; color: #9fc8e8; border: 1px solid #2a3a52; cursor: pointer; opacity: 0; transition: opacity .15s, background .15s, color .15s; }
.docs-code:hover .docs-copy { opacity: 1; }
.docs-copy:hover { background: var(--accent); color: #061018; border-color: transparent; }
/* keyboard focus indicators — visible for keyboard users only (a11y, 0.59) */
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.gm-cta-primary:focus-visible, .px-action:focus-visible { outline-color: #f3d27a; }