UNPKG

@casoon/dragonfly

Version:

Modular, lightweight CSS framework and design system for modern web projects. Optimized for Astro JS, LightningCSS and Container Queries with @layer-based architecture and comprehensive accessibility.

413 lines (346 loc) 13.5 kB
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Accessibility Demo - Casoon UI</title> <!-- Frühe Initialisierung des Accessibility-Status (vor CSS laden) --> <script> // Prüfe gespeicherte Accessibility-Einstellungen (function() { try { const highContrast = localStorage.getItem('casoon-dragonfly-high-contrast') === 'true'; const reducedMotion = localStorage.getItem('casoon-dragonfly-reduced-motion') === 'true'; // Anwenden der Klassen if (highContrast) { document.documentElement.classList.add('high-contrast-mode'); } if (reducedMotion) { document.documentElement.classList.add('reduced-motion'); } } catch (e) { console.warn('Konnte Accessibility-Einstellungen nicht laden', e); } })(); </script> <!-- UI-Lib CSS einbinden --> <link rel="stylesheet" href="../../core.css"> <!-- Zusätzliches CSS für die Demo --> <style> body { font-family: var(--font-family-sans); color: var(--color-text-primary); background-color: var(--color-background); padding: 2rem; transition: background-color 0.3s, color 0.3s; } .container { max-width: 1000px; margin: 0 auto; display: flex; flex-direction: column; gap: 2rem; } .header { text-align: center; margin-bottom: 2rem; } .demo-section { padding: 2rem; border-radius: var(--border-radius-lg); background-color: var(--color-surface); box-shadow: var(--shadow-md); } .controls { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1rem; } .btn { padding: 0.5rem 1rem; border-radius: var(--border-radius-md); background-color: var(--color-primary-500); color: white; border: none; cursor: pointer; font-weight: var(--font-weight-medium); transition: background-color 0.2s; min-height: 44px; } .btn:hover { background-color: var(--color-primary-600); } .btn.secondary { background-color: var(--color-secondary-500); } .animation-demo { width: 100px; height: 100px; background-color: var(--color-primary-500); margin: 2rem auto; border-radius: var(--border-radius-md); animation: pulse 2s infinite ease-in-out; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .tab-container { margin-top: 2rem; } .tabs { display: flex; border-bottom: 1px solid var(--color-border); } .tab { padding: 0.5rem 1rem; cursor: pointer; border-bottom: 2px solid transparent; } .tab[aria-selected="true"] { border-bottom-color: var(--color-primary-500); color: var(--color-primary-600); } .tabpanel { padding: 1rem; border: 1px solid var(--color-border); border-top: none; display: none; } .tabpanel[aria-hidden="false"] { display: block; } .form-group { margin-bottom: 1rem; } label { display: block; margin-bottom: 0.5rem; } input, select { width: 100%; padding: 0.5rem; border: 1px solid var(--color-border); border-radius: var(--border-radius-sm); } .status { padding: 1rem; margin-top: 1rem; border-radius: var(--border-radius-md); border-left: 4px solid var(--color-info); background-color: var(--color-surface-hover); } .alert { padding: 1rem; margin-top: 1rem; border-radius: var(--border-radius-md); border-left: 4px solid var(--color-error); background-color: var(--color-surface-hover); display: none; } </style> </head> <body> <!-- Skip-Link für Tastatur-Navigation --> <a href="#main-content" class="skip-link">Zum Hauptinhalt springen</a> <div class="container"> <header class="header"> <h1>Accessibility-Demo</h1> <p>Dieses Beispiel demonstriert die Accessibility-Funktionen der Casoon UI-Bibliothek.</p> </header> <main id="main-content"> <section class="demo-section"> <h2>Accessibility-Einstellungen</h2> <p>Passe die Accessibility-Einstellungen an deine Bedürfnisse an:</p> <div class="controls"> <button id="toggle-contrast" class="btn">Hochkontrast-Modus umschalten</button> <button id="toggle-motion" class="btn">Reduzierte Bewegung umschalten</button> </div> <div aria-live="polite" role="status" class="status"> Aktuelle Einstellungen: <span id="current-settings">Standard</span> </div> </section> <section class="demo-section"> <h2>Animations-Demo</h2> <p>Diese Animation wird deaktiviert, wenn reduzierte Bewegung aktiviert ist:</p> <div class="animation-demo"></div> <p class="reduced-motion-notice" style="text-align: center; display: none;"> Animation wurde aufgrund der Einstellung "Reduzierte Bewegung" deaktiviert. </p> </section> <section class="demo-section"> <h2>Keyboard-Navigation</h2> <p>Teste die Tastatur-Navigation durch die folgenden interaktiven Elemente:</p> <div class="tab-container" role="tablist" aria-label="Demo-Tabs"> <div class="tabs"> <button id="tab1" class="tab" role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button> <button id="tab2" class="tab" role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button> <button id="tab3" class="tab" role="tab" aria-selected="false" aria-controls="panel3">Tab 3</button> </div> <div id="panel1" class="tabpanel" role="tabpanel" aria-labelledby="tab1" aria-hidden="false"> <h3>Tab-Inhalt 1</h3> <p>Dies ist der Inhalt des ersten Tabs. Benutze die Pfeiltasten, um zwischen den Tabs zu navigieren.</p> <button class="btn">Aktionsbutton</button> </div> <div id="panel2" class="tabpanel" role="tabpanel" aria-labelledby="tab2" aria-hidden="true"> <h3>Tab-Inhalt 2</h3> <p>Dies ist der Inhalt des zweiten Tabs. Er enthält ein Formular:</p> <form> <div class="form-group"> <label for="name">Name:</label> <input type="text" id="name" aria-describedby="name-help"> <div id="name-help" class="sr-only">Gib deinen vollständigen Namen ein</div> </div> <div class="form-group"> <label for="email">E-Mail:</label> <input type="email" id="email" required> </div> <div class="form-group"> <label for="topic">Thema:</label> <select id="topic"> <option value="">Bitte wählen...</option> <option value="accessibility">Barrierefreiheit</option> <option value="design">Design</option> <option value="development">Entwicklung</option> </select> </div> <button type="button" class="btn" id="submit-form">Absenden</button> </form> </div> <div id="panel3" class="tabpanel" role="tabpanel" aria-labelledby="tab3" aria-hidden="true"> <h3>Tab-Inhalt 3</h3> <p>Dies ist der Inhalt des dritten Tabs.</p> <div class="controls"> <button class="btn">Button 1</button> <button class="btn secondary">Button 2</button> <button class="btn">Button 3</button> </div> </div> </div> </section> <section class="demo-section"> <h2>Screenreader-Support</h2> <p>Diese Sektion demonstriert Features für Screenreader:</p> <div class="controls"> <button id="show-alert" class="btn">Benachrichtigung anzeigen</button> </div> <div role="alert" class="alert" id="demo-alert"> Dies ist eine wichtige Benachrichtigung für Screenreader! </div> <p> <span class="sr-only">Diese Information ist nur für Screenreader gedacht.</span> Hier ist ein <a href="#" aria-label="Link mit zusätzlicher Beschreibung für Screenreader">Link</a> mit einem benutzerdefinierten aria-label. </p> </section> </main> </div> <!-- Accessibility-Helper-Script einbinden --> <script src="a11y-helper.js"></script> <!-- Demo-Script --> <script> document.addEventListener('DOMContentLoaded', () => { // Elemente const toggleContrastBtn = document.getElementById('toggle-contrast'); const toggleMotionBtn = document.getElementById('toggle-motion'); const currentSettings = document.getElementById('current-settings'); const tabs = document.querySelectorAll('[role="tab"]'); const tabpanels = document.querySelectorAll('[role="tabpanel"]'); const showAlertBtn = document.getElementById('show-alert'); const demoAlert = document.getElementById('demo-alert'); const submitFormBtn = document.getElementById('submit-form'); const reducedMotionNotice = document.querySelector('.reduced-motion-notice'); // Event-Listener für Kontrast-Toggle toggleContrastBtn.addEventListener('click', () => { window.CasoonUIAccessibility.toggleHighContrast(); updateSettingsDisplay(); }); // Event-Listener für Bewegungs-Toggle toggleMotionBtn.addEventListener('click', () => { window.CasoonUIAccessibility.toggleReducedMotion(); updateSettingsDisplay(); }); // Event-Listener für Tabs tabs.forEach(tab => { tab.addEventListener('click', () => { // Deaktiviere alle Tabs tabs.forEach(t => { t.setAttribute('aria-selected', 'false'); }); // Verstecke alle Panels tabpanels.forEach(panel => { panel.setAttribute('aria-hidden', 'true'); }); // Aktiviere ausgewählten Tab tab.setAttribute('aria-selected', 'true'); // Zeige zugehöriges Panel const panelId = tab.getAttribute('aria-controls'); const panel = document.getElementById(panelId); panel.setAttribute('aria-hidden', 'false'); }); // Keyboard-Navigation für Tabs tab.addEventListener('keydown', (event) => { let nextTab; if (event.key === 'ArrowRight') { nextTab = tab.nextElementSibling || tabs[0]; event.preventDefault(); } else if (event.key === 'ArrowLeft') { nextTab = tab.previousElementSibling || tabs[tabs.length - 1]; event.preventDefault(); } if (nextTab) { nextTab.click(); nextTab.focus(); } }); }); // Event-Listener für Alert-Demo showAlertBtn.addEventListener('click', () => { demoAlert.style.display = 'block'; // Verstecke die Benachrichtigung nach 5 Sekunden setTimeout(() => { demoAlert.style.display = 'none'; }, 5000); }); // Event-Listener für Formular-Demo submitFormBtn.addEventListener('click', () => { const nameInput = document.getElementById('name'); const emailInput = document.getElementById('email'); if (!nameInput.value || !emailInput.value) { alert('Bitte fülle alle Pflichtfelder aus.'); } else { // Status-Nachricht anzeigen const status = document.querySelector('[role="status"]'); status.textContent = `Formular für ${nameInput.value} wurde erfolgreich abgesendet.`; // Formular zurücksetzen nameInput.value = ''; emailInput.value = ''; } }); // Aktualisierung der Einstellungsanzeige function updateSettingsDisplay() { const isHighContrast = document.documentElement.classList.contains('high-contrast-mode'); const isReducedMotion = document.documentElement.classList.contains('reduced-motion'); let settingsText = []; if (isHighContrast) { settingsText.push('Hochkontrast aktiviert'); } if (isReducedMotion) { settingsText.push('Reduzierte Bewegung aktiviert'); reducedMotionNotice.style.display = 'block'; } else { reducedMotionNotice.style.display = 'none'; } if (settingsText.length === 0) { currentSettings.textContent = 'Standard'; } else { currentSettings.textContent = settingsText.join(', '); } } // Initialisierung updateSettingsDisplay(); }); </script> </body> </html>