Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Architecture

Luc edited this page Nov 20, 2025 · 2 revisions

Understanding the codebase structure and how the Accessibility Widget works.

πŸ—οΈ Overview

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.

πŸ“ Architecture Principles

  • 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

πŸ“ File Structure

accessibility-plugin/
β”œβ”€β”€ accessibility-plugin.js # Main plugin (1618 lines)
β”œβ”€β”€ accessibility-plugin.css # Styles (885 lines)
└── accessibility-config.js # Configuration (67 lines)

πŸ”§ Core Components

1. Initialization

(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 = { ... };
})();

2. State Management

The plugin uses a centralized state object:

let currentState = {
 fontSize: 100,
 contrast: 'normal',
 colorBlindness: 'none',
 // ... more settings
};

State Flow:

  1. User changes setting β†’ Update currentState
  2. Call applySettings() β†’ Apply to DOM
  3. Call savePreferences() β†’ Save to localStorage

3. Widget Creation

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);
}

4. Settings Application

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
}

🎨 CSS Architecture

Scoping

All CSS is scoped to avoid conflicts:

/* Widget-specific classes */
.accessibility-widget { ... }
.accessibility-panel { ... }
.accessibility-toggle-btn { ... }

Isolation

Widget is isolated from page styles:

.accessibility-widget {
 isolation: isolate !important;
 contain: none !important;
 z-index: 10000 !important;
}

Responsive Design

Mobile-first approach:

/* Base styles */
.accessibility-panel {
 width: 260px;
}
/* Mobile adjustments */
@media (max-width: 768px) {
 .accessibility-panel {
 width: calc(100vw - 20px);
 }
}

πŸ”„ Feature Implementation

Text-to-Speech

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);
}

Color Blindness Filters

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)';
}

Reading Guide

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);
}

πŸ“¦ Module Organization

Settings Module

// Default settings
const defaultSettings = { ... };
// Current state
let currentState = { ... };
// Load preferences
function loadPreferences() { ... }
// Save preferences
function savePreferences() { ... }

UI Module

// Create widget
function createWidget() { ... }
// Create controls
function createControl() { ... }
// Toggle panel
function togglePanel() { ... }

Features Module

// Apply all settings
function applySettings() { ... }
// Individual feature functions
function applyFontSize() { ... }
function applyContrast() { ... }
function applyColorBlindnessFilter() { ... }

πŸ”Œ API Layer

The plugin exposes a simple API:

window.AccessibilityPlugin = {
 toggle: togglePanel,
 reset: resetSettings,
 getSettings: function() { return { ...currentState }; },
 setFontSize: function(size) { ... },
 setContrast: function(mode) { ... },
 // ... more methods
};

πŸ’Ύ Data Persistence

localStorage

Settings are saved to localStorage:

function savePreferences() {
 try {
 localStorage.setItem(
 'accessibilitySettings',
 JSON.stringify(currentState)
 );
 } catch (e) {
 console.error('Failed to save preferences:', e);
 }
}

Loading

function loadPreferences() {
 try {
 const saved = localStorage.getItem('accessibilitySettings');
 if (saved) {
 currentState = { ...currentState, ...JSON.parse(saved) };
 }
 } catch (e) {
 console.error('Failed to load preferences:', e);
 }
}

🎯 Design Patterns

IIFE Pattern

(function() {
 // Isolated scope
 // No global pollution
})();

Observer Pattern

// Watch for settings changes
function watchSettings() {
 let lastState = { ...currentState };
 setInterval(function() {
 if (stateChanged(lastState, currentState)) {
 onSettingsChange();
 lastState = { ...currentState };
 }
 }, 100);
}

Factory Pattern

// Create controls dynamically
function createControl(label, key, options, value) {
 const control = document.createElement('div');
 // ... build control
 return control;
}

πŸ”’ Security

XSS Prevention

  • No user input is directly inserted into DOM
  • All text is properly escaped
  • No eval() or similar dangerous functions

CSP Compatibility

Works with Content Security Policy:

  • No inline scripts required
  • All code in external files
  • No unsafe-eval

⚑ Performance

Optimization Techniques

  1. Lazy Initialization: Widget created on DOM ready
  2. Event Delegation: Efficient event handling
  3. Debouncing: For frequent events (mousemove)
  4. CSS Isolation: Prevents style recalculation
  5. Minimal DOM Manipulation: Batch updates

Performance Considerations

  • Color filters may impact large pages
  • TTS uses browser APIs (efficient)
  • localStorage is fast (synchronous)
  • No heavy computations

🧩 Extensibility

Adding New Features

  1. Add to defaultSettings

    const defaultSettings = {
     // ... existing
     myNewFeature: false
    };
  2. Add to currentState

    let currentState = {
     // ... existing
     myNewFeature: settings.myNewFeature
    };
  3. Create UI Control

    const control = createControl('My Feature', 'myNewFeature', [...], value);
  4. Implement Logic

    function applySettings() {
     // ... existing
     if (currentState.myNewFeature) {
     // Your logic
     }
    }
  5. Add to API (optional)

    window.AccessibilityPlugin = {
     // ... existing
     setMyNewFeature: function(value) { ... }
    };

πŸ“Š Data Flow

User Action
 ↓
Update currentState
 ↓
Call applySettings()
 ↓
Modify DOM
 ↓
Call savePreferences()
 ↓
Save to localStorage

πŸ” Code Organization

Function Order

  1. Constants and defaults
  2. State management
  3. Utility functions
  4. Feature implementations
  5. UI creation
  6. Event handlers
  7. Initialization
  8. API exports

Naming Conventions

  • Functions: camelCase (applySettings)
  • Variables: camelCase (currentState)
  • CSS Classes: kebab-case (.accessibility-widget)
  • Constants: UPPER_SNAKE_CASE (ACCESSIBILITY_NAMESPACE)

πŸ“š Related Pages

πŸ†˜ Questions?


Last Updated: November 2025

Getting Started

Documentation

Guides

Development

Support

Clone this wiki locally

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /