Add WCAG 2.1 Level AA accessibility across all components

A break timer designed to prevent RSI should be usable by people who
already live with disabilities. This overhaul adds comprehensive
accessibility without changing the visual design.

Changes across 17 source files:
- Global focus-visible outlines, sr-only utility, forced-colors support
- prefers-reduced-motion kills all CSS animations AND JS Web Animations
- All text upgraded to 4.5:1+ contrast ratio (WCAG AA)
- Keyboard navigation for ColorPicker, Stepper, TimeSpinner
- Screen reader: aria-live status regions, progressbar roles, labeled
  controls, sr-only chart data table, focus management on view changes
- Focus trap on break screen, aria-hidden on decorative elements
- Descriptive labels on all 25+ toggle/stepper instances in Settings
- README updated with accessibility section and WCAG badge
This commit is contained in:
Your Name
2026-02-07 12:10:10 +02:00
parent f03425fa59
commit e757d4ee30
18 changed files with 459 additions and 226 deletions
+10 -4
View File
@@ -6,6 +6,7 @@
step?: number;
formatValue?: (v: number) => string;
onchange?: (value: number) => void;
label?: string;
}
let {
@@ -15,6 +16,7 @@
step = 1,
formatValue = (v: number) => String(v),
onchange,
label = "Value",
}: Props = $props();
let holdTimer: ReturnType<typeof setTimeout> | null = null;
@@ -55,32 +57,36 @@
}
</script>
<div class="flex items-center gap-1.5">
<div class="flex items-center gap-1.5" role="group" aria-label={label}>
<button
type="button"
aria-label="Decrease"
class="flex h-7 w-7 items-center justify-center rounded-lg
bg-[#141414] text-[#444] transition-colors
bg-[#141414] text-[#999] transition-colors
hover:bg-[#1c1c1c] hover:text-white
disabled:opacity-20"
onmousedown={() => startHold(decrement)}
onmouseup={stopHold}
onmouseleave={stopHold}
onclick={(e) => { if (e.detail === 0) decrement(); }}
disabled={value <= min}
>
&minus;
</button>
<span class="min-w-[38px] text-center text-[13px] tabular-nums text-white">
<span class="min-w-[38px] text-center text-[13px] tabular-nums text-white" aria-live="polite" aria-atomic="true">
{formatValue(value)}
</span>
<button
type="button"
aria-label="Increase"
class="flex h-7 w-7 items-center justify-center rounded-lg
bg-[#141414] text-[#444] transition-colors
bg-[#141414] text-[#999] transition-colors
hover:bg-[#1c1c1c] hover:text-white
disabled:opacity-20"
onmousedown={() => startHold(increment)}
onmouseup={stopHold}
onmouseleave={stopHold}
onclick={(e) => { if (e.detail === 0) increment(); }}
disabled={value >= max}
>
+