-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Luc edited this page Nov 20, 2025
·
2 revisions
Understanding the codebase structure and how the Accessibility Widget works.
The Accessibility Widget is a self-contained, client-side plugin built with vanilla JavaScript and CSS. It has no dependencies and works on any modern web browser.
- Self-Contained: No external dependencies (except Boxicons for icons)
- Isolated: Uses namespacing to avoid conflicts
- Modular: Features are organized into logical functions
- Performant: Optimized for speed and efficiency
- Accessible: Follows WCAG guidelines
accessibility-plugin/
βββ accessibility-plugin.js # Main plugin (1618 lines)
βββ accessibility-plugin.css # Styles (885 lines)
βββ accessibility-config.js # Configuration (67 lines)
(function() {
'use strict';
// Namespace isolation
const ACCESSIBILITY_NAMESPACE = 'accessibilityPlugin';
// Default settings
const defaultSettings = { ... };
// State management
let currentState = { ... };
// Initialize on DOM ready
function init() { ... }
init();
// Expose API
window.AccessibilityPlugin = { ... };
})();The plugin uses a centralized state object:
let currentState = {
fontSize: 100,
contrast: 'normal',
colorBlindness: 'none',
// ... more settings
};State Flow:
- User changes setting β Update
currentState - Call
applySettings()β Apply to DOM - Call
savePreferences()β Save to localStorage
The widget is created dynamically:
function createWidget() {
// Create container
const widget = document.createElement('div');
widget.className = 'accessibility-widget';
// Create toggle button
const button = createToggleButton();
// Create panel
const panel = createPanel();
// Append to body
document.body.appendChild(widget);
}Settings are applied to the DOM:
function applySettings() {
// Apply font size
document.body.style.fontSize = currentState.fontSize + '%';
// Apply contrast
if (currentState.contrast === 'high') {
document.body.classList.add('accessibility-contrast-high');
}
// Apply color blindness filter
applyColorBlindnessFilter();
// ... more settings
}All CSS is scoped to avoid conflicts:
/* Widget-specific classes */
.accessibility-widget { ... }
.accessibility-panel { ... }
.accessibility-toggle-btn { ... }Widget is isolated from page styles:
.accessibility-widget {
isolation: isolate !important;
contain: none !important;
z-index: 10000 !important;
}Mobile-first approach:
/* Base styles */
.accessibility-panel {
width: 260px;
}
/* Mobile adjustments */
@media (max-width: 768px) {
.accessibility-panel {
width: calc(100vw - 20px);
}
}function speakText(text) {
if (!speechSynthesis) return;
const utterance = new SpeechSynthesisUtterance(text);
utterance.rate = currentState.ttsRate;
utterance.pitch = currentState.ttsPitch;
utterance.volume = currentState.ttsVolume;
speechSynthesis.speak(utterance);
}function applyColorBlindnessFilter() {
if (currentState.colorBlindness === 'none') {
document.body.style.filter = '';
return;
}
// Create SVG filter
const svg = createSVGFilter();
document.body.appendChild(svg);
// Apply filter
document.body.style.filter = 'url(#colorblind-filter)';
}function enableReadingGuide() {
const guide = document.createElement('div');
guide.className = 'accessibility-reading-guide';
document.addEventListener('mousemove', function(e) {
guide.style.top = e.clientY + 'px';
});
document.body.appendChild(guide);
}// Default settings
const defaultSettings = { ... };
// Current state
let currentState = { ... };
// Load preferences
function loadPreferences() { ... }
// Save preferences
function savePreferences() { ... }// Create widget
function createWidget() { ... }
// Create controls
function createControl() { ... }
// Toggle panel
function togglePanel() { ... }// Apply all settings
function applySettings() { ... }
// Individual feature functions
function applyFontSize() { ... }
function applyContrast() { ... }
function applyColorBlindnessFilter() { ... }The plugin exposes a simple API:
window.AccessibilityPlugin = {
toggle: togglePanel,
reset: resetSettings,
getSettings: function() { return { ...currentState }; },
setFontSize: function(size) { ... },
setContrast: function(mode) { ... },
// ... more methods
};Settings are saved to localStorage:
function savePreferences() {
try {
localStorage.setItem(
'accessibilitySettings',
JSON.stringify(currentState)
);
} catch (e) {
console.error('Failed to save preferences:', e);
}
}function loadPreferences() {
try {
const saved = localStorage.getItem('accessibilitySettings');
if (saved) {
currentState = { ...currentState, ...JSON.parse(saved) };
}
} catch (e) {
console.error('Failed to load preferences:', e);
}
}(function() {
// Isolated scope
// No global pollution
})();// Watch for settings changes
function watchSettings() {
let lastState = { ...currentState };
setInterval(function() {
if (stateChanged(lastState, currentState)) {
onSettingsChange();
lastState = { ...currentState };
}
}, 100);
}// Create controls dynamically
function createControl(label, key, options, value) {
const control = document.createElement('div');
// ... build control
return control;
}- No user input is directly inserted into DOM
- All text is properly escaped
- No eval() or similar dangerous functions
Works with Content Security Policy:
- No inline scripts required
- All code in external files
- No unsafe-eval
- Lazy Initialization: Widget created on DOM ready
- Event Delegation: Efficient event handling
- Debouncing: For frequent events (mousemove)
- CSS Isolation: Prevents style recalculation
- Minimal DOM Manipulation: Batch updates
- Color filters may impact large pages
- TTS uses browser APIs (efficient)
- localStorage is fast (synchronous)
- No heavy computations
-
Add to defaultSettings
const defaultSettings = { // ... existing myNewFeature: false };
-
Add to currentState
let currentState = { // ... existing myNewFeature: settings.myNewFeature };
-
Create UI Control
const control = createControl('My Feature', 'myNewFeature', [...], value);
-
Implement Logic
function applySettings() { // ... existing if (currentState.myNewFeature) { // Your logic } }
-
Add to API (optional)
window.AccessibilityPlugin = { // ... existing setMyNewFeature: function(value) { ... } };
User Action
β
Update currentState
β
Call applySettings()
β
Modify DOM
β
Call savePreferences()
β
Save to localStorage
- Constants and defaults
- State management
- Utility functions
- Feature implementations
- UI creation
- Event handlers
- Initialization
- API exports
-
Functions: camelCase (
applySettings) -
Variables: camelCase (
currentState) -
CSS Classes: kebab-case (
.accessibility-widget) -
Constants: UPPER_SNAKE_CASE (
ACCESSIBILITY_NAMESPACE)
- Check Development Setup
- Review Contributing guide
- Open an issue on GitHub
Last Updated: November 2025
- Installation Guide - Step-by-step installation instructions
- Quick Start Guide - Get up and running in 5 minutes
- Configuration Guide - Customize the plugin to your needs
- Features Overview - Complete list of all features
- JavaScript API - Programmatic control documentation
- Browser Compatibility - Supported browsers and features
- WordPress Integration - How to integrate with WordPress
- Customization Guide - Styling and theming
- Advanced Usage - Tips and tricks for power users
- Contributing - How to contribute to the project
- Development Setup - Set up your development environment
- Architecture - Understanding the codebase
- Troubleshooting - Common issues and solutions
- FAQ - Frequently asked questions
- Known Issues - Current limitations and workarounds