feat: Phase 0 - Audit-Fixes + Glass-Token-Layer
Accessibility fixes (WCAG 2.2): - K1: Entferne user-scalable=no aus viewport (WCAG 1.4.4) - K2: Korrigiere var(--color-background) → var(--color-bg) in settings.css - H1: --color-text-tertiary #737370 → #6B6B68 (WCAG AA: 4.52:1) - H2: --color-info #54AEFF → #0969DA (WCAG AA: 4.6:1 auf weiß) - H4+H5: Korrigiere nicht-existente Token-Referenzen in settings.css (--color-surface-raised → --color-surface-2, --duration-fast → --transition-fast) - H7: aria-label + role=presentation auf Modal-Overlay - N1: theme-color Meta-Tags auf tatsächliche Design-Tokens angleichen - N2: var(--color-text) → var(--color-text-primary) in notes.css - N3: Hardcoded #1E5CB3 → var(--color-accent-deep) in dashboard.css - N4: Hardcoded padding 2px 8px → Token-Referenzen in meals.css Neue Tokens: - --color-accent-deep: tiefer Akzent für Gradienten - Glass-Token-Layer (Section 16) mit 7 Kategorien: Hintergründe, Blur-Stufen, Opazitäten, Highlights, Schatten, Radien, Übergänge - Dark-Mode-Varianten für alle Glass-Tokens - prefers-reduced-transparency: opake Fallbacks - prefers-contrast: more: Kontrast-Fallbacks ohne Blur i18n: modal.overlayLabel in allen 9 Sprachen ergänzt
This commit is contained in:
@@ -195,7 +195,7 @@ export function openModal({ title, content, onSave, onDelete, size = 'md' } = {}
|
||||
const sizeClass = size !== 'md' ? ` modal-panel--${size}` : '';
|
||||
|
||||
const html = `
|
||||
<div class="modal-overlay" id="shared-modal-overlay">
|
||||
<div class="modal-overlay" id="shared-modal-overlay" aria-label="${t('modal.overlayLabel')}" role="presentation">
|
||||
<div class="modal-panel${sizeClass}" role="dialog" aria-modal="true"
|
||||
aria-labelledby="shared-modal-title">
|
||||
<div class="modal-panel__header">
|
||||
|
||||
+3
-3
@@ -3,11 +3,11 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- Viewport: edge-to-edge, kein Zoom (PWA-native feel) -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no, maximum-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=5" />
|
||||
|
||||
<!-- PWA / Theme -->
|
||||
<meta name="theme-color" content="#007AFF" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#1C1C1E" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#2563EB" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#222220" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
|
||||
<!-- iOS-spezifisch -->
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Schließen"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Schließen"
|
||||
"closeLabel": "Schließen",
|
||||
"overlayLabel": "Modaler Dialog-Hintergrund"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Keine Wiederholung",
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Κλείσιμο"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Κλείσιμο"
|
||||
"closeLabel": "Κλείσιμο",
|
||||
"overlayLabel": "Φόντο αναδυόμενου παραθύρου"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Χωρίς επανάληψη",
|
||||
@@ -588,4 +589,4 @@
|
||||
"unitMonth": "μήνα",
|
||||
"unitMonths": "μήνες"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Close"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Close"
|
||||
"closeLabel": "Close",
|
||||
"overlayLabel": "Modal dialog background"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "No recurrence",
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Cerrar"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Cerrar"
|
||||
"closeLabel": "Cerrar",
|
||||
"overlayLabel": "Fondo del cuadro de diálogo modal"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Sin repetición",
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Fermer"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Fermer"
|
||||
"closeLabel": "Fermer",
|
||||
"overlayLabel": "Arrière-plan de la boîte de dialogue modale"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Pas de répétition",
|
||||
@@ -588,4 +589,4 @@
|
||||
"unitMonth": "mois",
|
||||
"unitMonths": "mois"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Chiudi"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Chiudi"
|
||||
"closeLabel": "Chiudi",
|
||||
"overlayLabel": "Sfondo del dialogo modale"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Nessuna ripetizione",
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Закрыть"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Закрыть"
|
||||
"closeLabel": "Закрыть",
|
||||
"overlayLabel": "Фон модального диалога"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Без повтора",
|
||||
@@ -588,4 +589,4 @@
|
||||
"unitMonth": "месяц",
|
||||
"unitMonths": "месяцев"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Stäng"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Stäng"
|
||||
"closeLabel": "Stäng",
|
||||
"overlayLabel": "Bakgrund för modal dialog"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Ingen upprepning",
|
||||
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "Kapat"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "Kapat"
|
||||
"closeLabel": "Kapat",
|
||||
"overlayLabel": "Modal iletişim kutusu arka planı"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "Tekrar yok",
|
||||
@@ -588,4 +589,4 @@
|
||||
"unitMonth": "ay",
|
||||
"unitMonths": "ay"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -563,7 +563,8 @@
|
||||
"dismissLabel": "关闭"
|
||||
},
|
||||
"modal": {
|
||||
"closeLabel": "关闭"
|
||||
"closeLabel": "关闭",
|
||||
"overlayLabel": "模态对话框背景"
|
||||
},
|
||||
"rrule": {
|
||||
"freqNone": "不重复",
|
||||
@@ -588,4 +589,4 @@
|
||||
"unitMonth": "个月",
|
||||
"unitMonths": "个月"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,7 +641,7 @@
|
||||
* -------------------------------------------------------- */
|
||||
.weather-widget {
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, var(--color-accent) 0%, #1E5CB3 100%);
|
||||
background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-deep) 100%);
|
||||
color: var(--color-text-on-accent);
|
||||
}
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@
|
||||
gap: var(--space-1);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: var(--font-weight-medium);
|
||||
padding: 2px 8px;
|
||||
padding: var(--space-0h) var(--space-2);
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--text-md);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
margin-bottom: var(--space-6);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: var(--color-background);
|
||||
background: var(--color-bg);
|
||||
z-index: 10;
|
||||
padding-top: var(--space-1);
|
||||
}
|
||||
@@ -430,11 +430,11 @@
|
||||
gap: var(--space-2);
|
||||
padding: var(--space-2) var(--space-1);
|
||||
border-radius: var(--radius-sm);
|
||||
transition: background var(--duration-fast);
|
||||
transition: background var(--transition-fast);
|
||||
}
|
||||
|
||||
.cat-row:hover {
|
||||
background: var(--color-surface-raised);
|
||||
background: var(--color-surface-2);
|
||||
}
|
||||
|
||||
.cat-row__icon {
|
||||
|
||||
+126
-3
@@ -52,7 +52,7 @@
|
||||
--color-border-subtle: var(--neutral-150);
|
||||
--color-text-primary: var(--neutral-900);
|
||||
--color-text-secondary: var(--neutral-600); /* WCAG AA: ~5.0:1 auf weiß */
|
||||
--color-text-tertiary: #737370;
|
||||
--color-text-tertiary: #6B6B68; /* WCAG AA: ~4.52:1 auf --color-bg */
|
||||
--color-text-disabled: var(--neutral-300);
|
||||
--color-text-on-accent: #ffffff; /* Weißer Text auf farbigen Hintergründen (Buttons, Badges, FAB) */
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
--color-accent: #2563EB;
|
||||
--color-accent-hover: #1D4ED8;
|
||||
--color-accent-active: #1E40AF;
|
||||
--color-accent-deep: #1E5CB3; /* Tiefer Akzent für Gradienten, Wetter-Widget */
|
||||
--color-accent-light: #EFF6FF;
|
||||
--color-accent-subtle: #DBEAFE;
|
||||
--color-btn-primary: #2554C7; /* WCAG AA: 6.62:1 auf weiß (weißer Text) */
|
||||
@@ -80,8 +81,8 @@
|
||||
--color-danger: #DC2626;
|
||||
--color-danger-hover: #B91C1C;
|
||||
--color-danger-light: #FFE2E0;
|
||||
--color-info: #54AEFF;
|
||||
--color-info-hover: #3A94E5;
|
||||
--color-info: #0969DA; /* WCAG AA: ~4.6:1 auf weiß */
|
||||
--color-info-hover: #0550AE;
|
||||
--color-info-light: #DDF4FF;
|
||||
|
||||
/* --------------------------------------------------------
|
||||
@@ -254,6 +255,59 @@
|
||||
--z-nav: 100;
|
||||
--z-modal: 200;
|
||||
--z-toast: 300;
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* 16. Glass-Design-System (Liquid Glass Layer)
|
||||
* Additive Tokens – bestehende Tokens werden nicht verändert.
|
||||
* Aktivierung per @supports (backdrop-filter) in Komponenten.
|
||||
*
|
||||
* Aufbau:
|
||||
* a) Glass-Hintergründe
|
||||
* b) Blur-Stufen
|
||||
* c) Opazitäten
|
||||
* d) Highlights / Specular
|
||||
* e) Glass-Schatten
|
||||
* f) Glass-Radien
|
||||
* g) Glass-Übergänge
|
||||
* -------------------------------------------------------- */
|
||||
|
||||
/* a) Glass-Hintergründe */
|
||||
--glass-bg: rgba(255, 255, 255, 0.72);
|
||||
--glass-bg-hover: rgba(255, 255, 255, 0.82);
|
||||
--glass-bg-elevated: rgba(255, 255, 255, 0.88);
|
||||
--glass-border: rgba(255, 255, 255, 0.60);
|
||||
--glass-border-subtle: rgba(255, 255, 255, 0.35);
|
||||
|
||||
/* b) Blur-Stufen */
|
||||
--blur-xs: blur(4px);
|
||||
--blur-sm: blur(8px);
|
||||
--blur-md: blur(16px);
|
||||
--blur-lg: blur(28px);
|
||||
--blur-xl: blur(48px);
|
||||
|
||||
/* c) Opazitäten */
|
||||
--opacity-glass-subtle: 0.65;
|
||||
--opacity-glass-base: 0.80;
|
||||
--opacity-glass-elevated: 0.92;
|
||||
|
||||
/* d) Highlights / Specular */
|
||||
--glass-highlight: rgba(255, 255, 255, 0.70);
|
||||
--glass-highlight-subtle: rgba(255, 255, 255, 0.35);
|
||||
|
||||
/* e) Glass-Schatten */
|
||||
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(255, 255, 255, 0.55);
|
||||
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(255, 255, 255, 0.50);
|
||||
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.14), 0 0 0 1px rgba(255, 255, 255, 0.45);
|
||||
|
||||
/* f) Glass-Radien */
|
||||
--radius-glass-card: 20px;
|
||||
--radius-glass-inner: 14px;
|
||||
--radius-glass-chip: var(--radius-full);
|
||||
--radius-glass-button: var(--radius-full);
|
||||
|
||||
/* g) Glass-Übergänge */
|
||||
--ease-glass: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
--transition-glass: 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
@@ -346,6 +400,18 @@
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
|
||||
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||
|
||||
/* Glass - Dark Mode */
|
||||
--glass-bg: rgba(40, 40, 38, 0.75);
|
||||
--glass-bg-hover: rgba(50, 50, 48, 0.82);
|
||||
--glass-bg-elevated: rgba(58, 58, 55, 0.90);
|
||||
--glass-border: rgba(255, 255, 255, 0.12);
|
||||
--glass-border-subtle: rgba(255, 255, 255, 0.07);
|
||||
--glass-highlight: rgba(255, 255, 255, 0.10);
|
||||
--glass-highlight-subtle: rgba(255, 255, 255, 0.06);
|
||||
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.30), 0 0 0 1px rgba(255, 255, 255, 0.08);
|
||||
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(255, 255, 255, 0.07);
|
||||
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,4 +491,61 @@
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
|
||||
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||
|
||||
/* Glass - Dark Mode */
|
||||
--glass-bg: rgba(40, 40, 38, 0.75);
|
||||
--glass-bg-hover: rgba(50, 50, 48, 0.82);
|
||||
--glass-bg-elevated: rgba(58, 58, 55, 0.90);
|
||||
--glass-border: rgba(255, 255, 255, 0.12);
|
||||
--glass-border-subtle: rgba(255, 255, 255, 0.07);
|
||||
--glass-highlight: rgba(255, 255, 255, 0.10);
|
||||
--glass-highlight-subtle: rgba(255, 255, 255, 0.06);
|
||||
--glass-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.30), 0 0 0 1px rgba(255, 255, 255, 0.08);
|
||||
--glass-shadow-md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(255, 255, 255, 0.07);
|
||||
--glass-shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Accessibility: prefers-reduced-transparency
|
||||
* Glass-Effekte abschalten - opake Fallbacks.
|
||||
* ================================================================ */
|
||||
@media (prefers-reduced-transparency: reduce) {
|
||||
:root {
|
||||
--glass-bg: var(--color-surface);
|
||||
--glass-bg-hover: var(--color-surface-2);
|
||||
--glass-bg-elevated: var(--color-surface);
|
||||
--glass-border: var(--color-border);
|
||||
--glass-border-subtle: var(--color-border-subtle);
|
||||
--glass-highlight: transparent;
|
||||
--glass-highlight-subtle: transparent;
|
||||
--blur-xs: blur(0px);
|
||||
--blur-sm: blur(0px);
|
||||
--blur-md: blur(0px);
|
||||
--blur-lg: blur(0px);
|
||||
--blur-xl: blur(0px);
|
||||
--opacity-glass-subtle: 1;
|
||||
--opacity-glass-base: 1;
|
||||
--opacity-glass-elevated: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Accessibility: prefers-contrast: more
|
||||
* Kontrast erhöhen, Blur reduzieren.
|
||||
* ================================================================ */
|
||||
@media (prefers-contrast: more) {
|
||||
:root {
|
||||
--glass-bg: rgba(255, 255, 255, 0.97);
|
||||
--glass-bg-hover: #ffffff;
|
||||
--glass-bg-elevated: #ffffff;
|
||||
--glass-border: var(--color-text-primary);
|
||||
--glass-border-subtle: var(--color-text-secondary);
|
||||
--glass-highlight: transparent;
|
||||
--glass-highlight-subtle: transparent;
|
||||
--blur-xs: blur(0px);
|
||||
--blur-sm: blur(0px);
|
||||
--blur-md: blur(0px);
|
||||
--blur-lg: blur(0px);
|
||||
--blur-xl: blur(0px);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user