From 9636545fb7efcb470e4210d0d3170405d1b9b9ea Mon Sep 17 00:00:00 2001 From: artheru Date: Wed, 10 Jun 2026 11:05:16 +0800 Subject: [PATCH] a11y/ux: modals close on Escape (0.75.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - the agent ClassModal and the booth 'instance created' modal could only be dismissed by clicking the backdrop or the X — no Escape, a standard keyboard/UX expectation - add a keydown(Escape) -> close to both (ClassModal listens while mounted; the booth modal attaches the listener only while newInst is set) - verified live: agent modal opens then closes on Escape --- index.html | 2 +- package.json | 2 +- src/AgentPlatform.jsx | 7 +++++++ src/Scene2D.jsx | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 444e615..f4d7906 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + diff --git a/package.json b/package.json index 00d6dab..dd43e29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amerc-site", - "version": "0.74.0-lean-dep", + "version": "0.75.0-esc", "private": true, "type": "module", "scripts": { diff --git a/src/AgentPlatform.jsx b/src/AgentPlatform.jsx index dc1b744..2040120 100644 --- a/src/AgentPlatform.jsx +++ b/src/AgentPlatform.jsx @@ -105,6 +105,7 @@ function ClassModal({ id, auth, onClose }) { const [err, setErr] = useState(''); const load = useCallback(() => api(`/agents/classes/${id}`).then(setData).catch((e) => setErr(e.message)), [id]); useEffect(() => { load(); }, [load]); + useEffect(() => { const onKey = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [onClose]); const subscribe = async () => { try { const r = await api(`/agents/classes/${id}/subscribe`, { method: 'POST' }); setSub(r.token); } catch (e) { setErr(e.message); } }; if (!data) return null; const c = data.class; @@ -232,6 +233,12 @@ export function BoothDashboard({ auth, setRoute }) { const [form, setForm] = useState({ name: '', tags: '', description: '', kind: 'codex', command: 'codex --yolo', visibility: 'public' }); const [newInst, setNewInst] = useState(null); const [loaded, setLoaded] = useState(false); + useEffect(() => { + if (!newInst) return; + const onKey = (e) => { if (e.key === 'Escape') setNewInst(null); }; + window.addEventListener('keydown', onKey); + return () => window.removeEventListener('keydown', onKey); + }, [newInst]); const load = useCallback(async () => { setErr(''); diff --git a/src/Scene2D.jsx b/src/Scene2D.jsx index 353a0bc..c2ce3c3 100644 --- a/src/Scene2D.jsx +++ b/src/Scene2D.jsx @@ -10,7 +10,7 @@ import { api } from './api.js'; const Menu = ({ size = 20 }) => (); const X = ({ size = 20 }) => (); -const RELEASE = '0.74.0-lean-dep'; +const RELEASE = '0.75.0-esc'; const NAV = [ { id: 'home', label: 'Tavern' },