diff --git a/CHANGELOG.md b/CHANGELOG.md index 42bb381..e796091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ Sicherheit, Datenintegrität, echtes XP/Achievement-System, Navigations-Umbau, Docker/CI-Härtung und erste Tests. ### Responsive Darstellung & Barrierefreiheit +- **Globales Accessibility-Widget:** Ein schwebender Rollstuhl-Button öffnet auf jeder Seite + ein tastaturbedienbares Panel. Einstellungen werden ausschließlich lokal im Browser gespeichert. +- Enthalten sind vier Textgrößen, Hochkontrast, farbenblindfreundliche Statusfarben, Monochrom, + eine dyslexiefreundliche Schriftalternative, unterstrichene Links, reduzierte Animationen, + großer Cursor und ein zentraler Reset. +- Das Panel besitzt Dialogsemantik, sichtbaren Tastaturfokus, Escape-Schließen und verständliche + Aktivzustände; Spielzustände oder Benutzerkonten werden dabei nicht verändert. - **DevLab-Spielansicht nutzt große Bildschirme aus:** Die bisherige starre Begrenzung auf 1100 px wurde durch ein fluides, bis 2200 px breites Viewport-Layout ersetzt. Hauptbereich, Seitenpanel, Abstände und Grundschrift skalieren mit der verfügbaren Bildschirmgröße. diff --git a/mindfluxfuture.md b/mindfluxfuture.md index f0f8f68..c04074a 100644 --- a/mindfluxfuture.md +++ b/mindfluxfuture.md @@ -98,13 +98,16 @@ Jedes neue Spiel folgt exakt dem Muster der vorhandenen Spiele (bester Bauplan: ## Teil 1: Spieldesigns -### Plattformweite Barrierefreiheit (nächster Querschnittsschritt) +### Plattformweite Barrierefreiheit ✅ Grundwidget umgesetzt -- Globales, per Tastatur erreichbares Accessibility-Panel statt einzelner Insellösungen. +- Globales, per Tastatur erreichbares Accessibility-Panel über einen schwebenden Rollstuhl-Button. - Schriftgröße in vier nachvollziehbaren Stufen (100 %, 115 %, 130 %, 150 %), lokal gespeichert und auf Dashboard, Lernseiten sowie allen Spielen identisch angewendet. -- Zusätzlich: erhöhter Kontrast, reduzierte Bewegungen, gut sichtbare Fokusmarkierungen und - Prüfung aller Spielmechaniken auf vollständige Tastaturbedienbarkeit. +- Enthalten: erhöhter Kontrast, farbenblindfreundliches Statusfarbprofil, Monochrommodus, + dyslexiefreundliche Schriftalternative, unterstrichene Links, reduzierte Bewegungen, großer + Cursor, gut sichtbare Fokusmarkierungen und zentraler Reset. +- Noch offen bleibt die systematische Prüfung aller Spielmechaniken auf vollständige + Tastaturbedienbarkeit sowie ein WCAG-Audit mit Kontrastmessung und Screenreader-Tests. - Layouts dürfen bei Textvergrößerung weder Inhalte abschneiden noch horizontales Scrollen der gesamten Seite erzwingen; Codebereiche dürfen weiterhin gezielt horizontal scrollen. - Das Panel ergänzt semantisches HTML und WCAG-Prüfungen, ersetzt diese aber nicht. diff --git a/src/main/resources/static/css/accessibility.css b/src/main/resources/static/css/accessibility.css new file mode 100644 index 0000000..70e0e44 --- /dev/null +++ b/src/main/resources/static/css/accessibility.css @@ -0,0 +1,9 @@ +html[data-mf-font="115"]{font-size:115%!important}html[data-mf-font="130"]{font-size:130%!important}html[data-mf-font="150"]{font-size:150%!important} +html[data-mf-readable="true"] body,html[data-mf-readable="true"] button,html[data-mf-readable="true"] input,html[data-mf-readable="true"] select,html[data-mf-readable="true"] textarea{font-family:Verdana,Arial,sans-serif!important;letter-spacing:.025em;word-spacing:.08em;line-height:1.65} +html[data-mf-contrast="true"]{--bg:#000;--panel:#050505;--surface:#090909;--surface-2:#111;--text:#fff;--heading:#fff;--muted:#e7e7e7;--border:#fff;--border-accent:#ffd21a;--accent:#ffd21a;--accent-2:#fff} +html[data-mf-color="safe"]{--success:#2f9bff;--danger:#ff8a3d;--secondary:#c58cff;--esc-accent:#ffd166} +html[data-mf-mono="true"] body{filter:grayscale(1)}html[data-mf-links="true"] a{text-decoration:underline!important;text-underline-offset:.18em;text-decoration-thickness:.12em} +html[data-mf-motion="false"] *,html[data-mf-motion="false"] *::before,html[data-mf-motion="false"] *::after{animation-duration:.001ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.001ms!important} +html[data-mf-cursor="true"],html[data-mf-cursor="true"] *{cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cpath d='M2 1v25l7-7 5 11 5-2-5-10h10z' fill='white' stroke='black' stroke-width='2'/%3E%3C/svg%3E") 2 1,auto!important} +.mf-a11y-trigger{position:fixed;left:18px;bottom:18px;z-index:1800;width:56px;height:56px;border:2px solid #fff;border-radius:50%;display:grid;place-items:center;background:#07121f;color:#fff;box-shadow:0 5px 24px rgba(0,0,0,.4);cursor:pointer}.mf-a11y-trigger svg{width:31px;height:31px}.mf-a11y-trigger:focus-visible,.mf-a11y-panel button:focus-visible{outline:3px solid var(--accent);outline-offset:3px} +.mf-a11y-panel{position:fixed;left:18px;bottom:84px;z-index:1801;width:min(450px,calc(100vw - 24px));max-height:min(720px,calc(100dvh - 110px));overflow:auto;border:1px solid var(--border);border-radius:10px;background:var(--panel);color:var(--text);box-shadow:0 12px 45px rgba(0,0,0,.55)}.mf-a11y-panel[hidden]{display:none}.mf-a11y-head{position:sticky;top:0;display:flex;align-items:center;gap:1rem;padding:.65rem;background:#07121f;color:#fff;z-index:1}.mf-a11y-head h2{font:800 1.05rem Arial,sans-serif;margin:0 auto}.mf-a11y-close{width:44px;height:44px;border:0;border-radius:6px;background:#fff;color:#07121f;font-size:1.8rem;cursor:pointer}.mf-a11y-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:10px;background:var(--surface)}.mf-a11y-option{min-height:88px;border:1px solid var(--border);border-radius:6px;background:var(--surface-2);color:var(--text);padding:.65rem;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;font:inherit;cursor:pointer}.mf-a11y-option strong{font-size:1.35rem}.mf-a11y-option[aria-pressed="true"]{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 18%,var(--surface));box-shadow:inset 0 0 0 2px var(--accent)}.mf-a11y-option small{color:var(--muted)}@media(max-width:520px){.mf-a11y-trigger{left:10px;bottom:10px}.mf-a11y-panel{left:6px;bottom:74px}.mf-a11y-grid{grid-template-columns:1fr 1fr}.mf-a11y-option{min-height:78px;font-size:.82rem}} diff --git a/src/main/resources/static/js/accessibility.js b/src/main/resources/static/js/accessibility.js new file mode 100644 index 0000000..d7cd3ec --- /dev/null +++ b/src/main/resources/static/js/accessibility.js @@ -0,0 +1,10 @@ +(function(){'use strict';var KEY='mf-accessibility',levels=[100,115,130,150],defaults={font:100,readable:false,contrast:false,color:false,mono:false,links:false,motion:true,cursor:false}; +function load(){try{return Object.assign({},defaults,JSON.parse(localStorage.getItem(KEY)||'{}'));}catch(e){return Object.assign({},defaults);}}var state=load(); +function apply(){var h=document.documentElement;h.setAttribute('data-mf-font',String(state.font));h.setAttribute('data-mf-readable',state.readable);h.setAttribute('data-mf-contrast',state.contrast);h.setAttribute('data-mf-color',state.color?'safe':'standard');h.setAttribute('data-mf-mono',state.mono);h.setAttribute('data-mf-links',state.links);h.setAttribute('data-mf-motion',state.motion);h.setAttribute('data-mf-cursor',state.cursor);try{localStorage.setItem(KEY,JSON.stringify(state));}catch(e){}} +apply(); +function button(id,icon,label,detail){return '';} +function init(){if(document.querySelector('.mf-a11y-trigger'))return;var trigger=document.createElement('button');trigger.type='button';trigger.className='mf-a11y-trigger';trigger.setAttribute('aria-label','Barrierefreiheit öffnen');trigger.setAttribute('aria-expanded','false');trigger.setAttribute('aria-controls','mf-a11y-panel');trigger.innerHTML=''; +var panel=document.createElement('section');panel.id='mf-a11y-panel';panel.className='mf-a11y-panel';panel.hidden=true;panel.setAttribute('role','dialog');panel.setAttribute('aria-modal','false');panel.setAttribute('aria-labelledby','mf-a11y-title');panel.innerHTML='
- Theme-Auswahl und FluxTimer-Einstellungen werden ausschließlich im lokalen Browserspeicher
- (localStorage) des verwendeten Geräts abgelegt. Dazu gehören Aktivierungsstatus,
+ Theme-Auswahl, Barrierefreiheitsoptionen und FluxTimer-Einstellungen werden ausschließlich im
+ lokalen Browserspeicher (localStorage) des verwendeten Geräts abgelegt. Dazu gehören
+ gewählte Textgröße, Kontrast-, Farb-, Schrift-, Bewegungs- und Cursorhilfen sowie Aktivierungsstatus,
Intervall, ausgewählte Erinnerungsarten, optionaler eigener Erinnerungstext sowie der nächste
und letzte Auslösezeitpunkt. Diese Angaben werden nicht an den Mindflux-Server übertragen und
können durch Löschen der Website-Daten im Browser entfernt werden. Browser-Benachrichtigungen