Sourceful Energy

Accessibility

Built-in accessibility modes for users with different needs, fully compliant with EU regulations.

User Accessibility Settings

These options are designed to be offered to end users. Preferences are automatically persisted to localStorage.

Reading

Uses Lexend, designed for improved readability

WCAG 1.4.12 compliant spacing

Vision

Adjusts status colors for better visibility

Keyboard Navigation

High-contrast 3px focus rings

Live Preview
Success
Warning
Error
Energy

Sample text to preview font and spacing changes.

EU Compliance

European Accessibility Act (EAA)

The European Accessibility Act (Directive 2019/882) requires digital products and services to be accessible to people with disabilities. Enforcement began June 28, 2025.

RequirementStandardStatus
Text contrast ratioWCAG 1.4.3 (4.5:1)
Pass
UI component contrastWCAG 1.4.11 (3:1)
Pass
Focus indicators visibleWCAG 2.4.7
Pass
Text spacing adjustableWCAG 1.4.12
Pass
Keyboard accessibleWCAG 2.1.1
Pass
Reduced motion supportWCAG 2.3.3
Pass
Touch targets (mobile)WCAG 2.5.8 (44px)
Pass
Windows High Contrastforced-colors
Pass

Automatic System Support

The design system automatically respects user system preferences:

  • prefers-reduced-motion - All animations disabled when enabled
  • prefers-contrast: more - Increased border contrast
  • forced-colors - Windows High Contrast mode support
  • Browser zoom - All sizes use rem units for proper scaling

Implementation

Use the useAccessibility hook to build settings interfaces:

import { useAccessibility } from "@sourceful-energy/ui"

function AccessibilitySettings() {
  const {
    fontMode, setFontMode,
    colorMode, setColorMode,
    spacingMode, setSpacingMode,
    focusMode, setFocusMode,
  } = useAccessibility()

  return (
    <div className="space-y-4">
      {/* Dyslexia-friendly font */}
      <Switch
        checked={fontMode === "dyslexic"}
        onCheckedChange={(v) => setFontMode(v ? "dyslexic" : "default")}
      />

      {/* Color blind modes */}
      <Select value={colorMode} onValueChange={setColorMode}>
        <SelectItem value="default">Default colors</SelectItem>
        <SelectItem value="deuteranopia">Red-green color blind</SelectItem>
        <SelectItem value="protanopia">Red color blind</SelectItem>
        <SelectItem value="tritanopia">Blue-yellow color blind</SelectItem>
        <SelectItem value="achromatopsia">Grayscale</SelectItem>
      </Select>

      {/* Text spacing (WCAG 1.4.12) */}
      <Switch
        checked={spacingMode === "comfortable"}
        onCheckedChange={(v) => setSpacingMode(v ? "comfortable" : "default")}
      />

      {/* Enhanced focus (WCAG 2.4.7) */}
      <Switch
        checked={focusMode === "enhanced"}
        onCheckedChange={(v) => setFocusMode(v ? "enhanced" : "default")}
      />
    </div>
  )
}

Data Attributes

The provider sets these attributes on <html>:

AttributeValuesPurpose
data-font-modedyslexicSwitches to Lexend font
data-color-modedeuteranopia, protanopia, tritanopia, achromatopsiaColor blind palettes
data-spacingcomfortableWCAG 1.4.12 text spacing
data-focus-modeenhancedHigh-visibility focus rings

Individual Hooks

For granular control, use individual hooks:

import {
  useFontMode,
  useColorMode,
  useSpacingMode,
  useFocusMode,
  useDesignSystem,
} from "@sourceful-energy/ui"

// Individual settings
const { fontMode, setFontMode } = useFontMode()
const { colorMode, setColorMode } = useColorMode()
const { spacingMode, setSpacingMode } = useSpacingMode()
const { focusMode, setFocusMode } = useFocusMode()

// Full context (theme + all accessibility)
const ctx = useDesignSystem()

Best Practices

Offer settings in your app

Add an accessibility settings panel using the hooks above. Users expect to find these in Settings or Profile pages.

Don't rely on color alone

Always combine color with icons or text labels for status indicators. Our Alert and Badge components support icons.

Test with keyboard navigation

All interactive elements should be reachable via Tab and operable with Enter/Space. Our Radix-based components handle this automatically.

Use semantic HTML

Use heading levels (h1-h6) correctly, label form inputs, and use landmark regions (main, nav, aside). Screen readers depend on semantic structure.