Tutorial: Integrating @weable/a11y-color-utils with MUI Themes
4/19/2025
Tutorial: Integrating @weable/a11y-color-utils with MUI Themes
Material UI (MUI) provides a powerful theming system for building consistent and visually appealing React applications. Our own @weable/a11y-color-utils library offers advanced tools for ensuring color accessibility, including WCAG/APCA contrast checking and palette fixing. Combining these two can help you create UIs that are both beautiful and accessible.
This tutorial will guide you through integrating @weable/a11y-color-utils into your MUI theme setup.
Prerequisites
- A React project set up with MUI (v5+ recommended).
- The
@weable-tools/a11y-color-utilspackage installed and configured (see Getting Started Guide and README). Remember to initialize the library with your license key!
import { initLicense } from '@weable-tools/a11y-color-utils';
// Initialize early in your app setup
initLicense('YOUR_LICENSE_KEY');
Scenario: Validating Theme Colors
A common use case is validating your MUI theme's palette colors to ensure they meet accessibility contrast standards before they are even used in components.
Let's say you have a theme defined like this:
// src/theme.ts
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2', // Standard MUI Blue
contrastText: '#ffffff',
},
secondary: {
main: '#dc004e', // Standard MUI Pink
contrastText: '#ffffff',
},
background: {
default: '#ffffff',
paper: '#f5f5f5',
},
text: {
primary: 'rgba(0, 0, 0, 0.87)',
secondary: 'rgba(0, 0, 0, 0.6)',
},
// ... other colors (error, warning, info, success)
},
});
export default theme;
We want to check if the contrastText defined for primary and secondary actually provides sufficient contrast against their respective main colors.
Integration Steps
Import Utility Functions: Import the necessary functions from
@weable/a11y-color-utils. We'll usecheckContrast(for WCAG) andcalculateAPCA(for the more modern APCA standard).import { checkContrast, calculateAPCA } from '@weable-tools/a11y-color-utils';Create a Validation Helper: It's useful to create a helper function or script that takes your theme object and performs the checks.
// src/utils/validateThemeColors.ts (or similar) import { createTheme } from '@mui/material/styles'; import { checkContrast, calculateAPCA } from '@weable-tools/a11y-color-utils'; import themeConfig from '../theme'; // Import your theme configuration // Define minimum acceptable contrast levels (adjust as needed) const MIN_WCAG_RATIO_AA = 4.5; const MIN_APCA_LC_SCORE = 75; // Target for body text readability export function validateThemePalette(theme) { const palette = theme.palette; const results = {}; Object.keys(palette).forEach(key => { const colorObj = palette[key]; // Check only objects with 'main' and 'contrastText' if (typeof colorObj === 'object' && colorObj.main && colorObj.contrastText) { const mainColor = colorObj.main; const contrastTextColor = colorObj.contrastText; try { const wcagResult = checkContrast(contrastTextColor, mainColor); const apcaScore = calculateAPCA(contrastTextColor, mainColor); results[key] = { main: mainColor, contrastText: contrastTextColor, wcagRatio: wcagResult.ratio, wcagPassAA: wcagResult.ratio >= MIN_WCAG_RATIO_AA, apcaScore: apcaScore, apcaPassTarget: Math.abs(apcaScore) >= MIN_APCA_LC_SCORE, notes: [], }; if (!results[key].wcagPassAA) { results[key].notes.push(`WCAG AA (${MIN_WCAG_RATIO_AA}:1) FAILED!`); } if (!results[key].apcaPassTarget) { results[key].notes.push(`APCA Target (Lc ${MIN_APCA_LC_SCORE}) FAILED!`); } } catch (error) { console.error(`Error validating color key "${key}":`, error); results[key] = { main: mainColor, contrastText: contrastTextColor, error: `Validation failed: ${error.message}`, }; } } // Add checks for other palette properties like background/text if needed // e.g., check palette.text.primary against palette.background.default }); return results; } // Example Usage (can be run in a script or test) const validationResults = validateThemePalette(themeConfig); console.log('Theme Color Validation Results:'); console.table(validationResults); // Optional: Assertions for automated testing Object.keys(validationResults).forEach(key => { if (validationResults[key].notes && validationResults[key].notes.length > 0) { console.warn(`Validation issues found for palette color: ${key}`, validationResults[key].notes); // Potentially throw an error in CI/CD pipeline // throw new Error(`Theme validation failed for ${key}`); } });Run the Validation: You can run this validation logic:
- As part of your build process.
- Within your automated tests (e.g., using Jest).
- Manually during development.
Running the example above with the standard MUI theme colors would likely show that the default
contrastTextvalues pass standard WCAG AA checks. APCA scores might vary and indicate areas for potential improvement, especially for smaller text sizes.
Advanced Integration: Fixing Contrast Issues
What if the validation fails? @weable/a11y-color-utils includes the fixWorstContrastPair function (and related helpers) that can suggest or automatically generate alternative colors.
Integrating this directly into MUI's createTheme can be complex because theme creation is typically synchronous. However, you could:
- Use the Validator Output: Manually adjust the
contrastTextin yourtheme.tsbased on the warnings from the validation script. - Pre-process Colors: Create a separate script that takes your base palette colors, runs them through
fixWorstContrastPairor similar functions, and generates thetheme.tsfile with accessiblecontrastTextvalues already populated. - Dynamic Theming (More Complex): For highly dynamic scenarios (e.g., user-generated themes), you might build a UI component that uses the validation and fixing functions in real-time, allowing users to adjust colors until they meet accessibility standards before applying them to the MUI theme provider.
Conclusion
By integrating @weable/a11y-color-utils with your MUI theme setup, you can proactively validate and improve the accessibility of your color palettes. Running checks early in the development process helps catch potential issues before they impact users, leading to more inclusive and robust applications. Remember to consult both WCAG and APCA results for a comprehensive understanding of your theme's color accessibility.