Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@
## 2024-05-18 - Missing Focus Visible States on Custom Switches
**Learning:** Custom UI controls that mimic native inputs (like pill-shaped switches for Reverse or Melodic Mode) frequently omit `focus-visible` styles, rendering them completely invisible to keyboard users when tabbing through the interface. Furthermore, developers frequently mistakenly use `aria-pressed` with `role="button"` instead of the correct `role="switch"` with `aria-checked` for these pill-shaped components.
**Action:** Always verify that interactive custom switches not only have appropriate ARIA roles (`role="switch"`, `aria-checked`) but explicitly define `focus:outline-none focus-visible:ring-*` classes.
## 2026-04-09 - Standardize Modal Accessibility for Cloud Library
**Learning:** The `CloudLibrary` component functioned as a modal visually but lacked standard ARIA modal attributes (`role="dialog"`, `aria-modal="true"`, `aria-labelledby`), causing screen readers to announce it incorrectly or not at all.
**Action:** When implementing custom modals, always include `role="dialog"`, `aria-modal="true"`, an explicit `aria-labelledby` referencing a visually hidden or visible title element, and an `aria-hidden="true"` on the clickable background overlay.
15 changes: 14 additions & 1 deletion src/components/CloudLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,22 @@ export const CloudLibrary: React.FC<CloudLibraryProps> = ({

return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4">
<div ref={modalRef} className="w-full max-w-2xl bg-[#0f1215] border border-cyan-900/50 rounded-xl shadow-[0_0_50px_rgba(6,182,212,0.2)] overflow-hidden flex flex-col max-h-[80vh]">
<div
className="absolute inset-0 z-0"
onClick={onClose}
aria-hidden="true"
/>
<div
ref={modalRef}
className="w-full max-w-2xl z-10 bg-[#0f1215] border border-cyan-900/50 rounded-xl shadow-[0_0_50px_rgba(6,182,212,0.2)] overflow-hidden flex flex-col max-h-[80vh]"
role="dialog"
aria-modal="true"
aria-labelledby="cloud-library-title"
tabIndex={-1}
>

{/* Header Tabs */}
<h2 id="cloud-library-title" className="sr-only">Cloud Library</h2>
<div
className="flex border-b border-gray-800 bg-gray-900/50"
role="tablist"
Expand Down
15 changes: 9 additions & 6 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ export default defineConfig({
optimizeDeps: {
exclude: ['onnxruntime-web', 'emsdk'],
},
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
watch: {
ignored: ['**/emsdk/**']
}
},
build: {
sourcemap: true,
outDir: 'dist',
Expand All @@ -30,12 +39,6 @@ export default defineConfig({
topLevelAwait()
]
},
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
}
},
test: {
environment: 'happy-dom',
setupFiles: ['./vitest.setup.ts'],
Expand Down
Loading