Frontend: structured error handling, state fixes, accessibility, i18n
- Enhance fetchWithAuth with auto-401, retry w/ exponential backoff, timeout - Remove ~40 manual 401 checks across 10 feature files - Fix state: brightness cache setter, manual edit flag resets, static import - Add ARIA: role=dialog/tablist, aria-modal, aria-labelledby, aria-selected - Add focus trapping in Modal base class, aria-expanded on hint toggles - Fix WCAG AA color contrast with --primary-text-color variable - Add i18n pluralization (CLDR rules for en/ru), getCurrentLocale export - Replace hardcoded strings in dashboard.js and profiles.js - Add data-i18n-aria-label support, 20 new keys in en.json and ru.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
--text-color: #e0e0e0;
|
||||
--border-color: #404040;
|
||||
--display-badge-bg: rgba(0, 0, 0, 0.4);
|
||||
--primary-text-color: #66bb6a;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@@ -28,6 +29,7 @@
|
||||
--text-color: #333333;
|
||||
--border-color: #e0e0e0;
|
||||
--display-badge-bg: rgba(255, 255, 255, 0.85);
|
||||
--primary-text-color: #3d8b40;
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ section {
|
||||
}
|
||||
|
||||
.add-device-card:hover .add-device-icon {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.add-device-label {
|
||||
@@ -86,7 +86,7 @@ section {
|
||||
|
||||
.card-tutorial-btn:hover {
|
||||
border-color: var(--primary-color);
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ section {
|
||||
}
|
||||
|
||||
.card-power-btn:hover {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ section {
|
||||
}
|
||||
|
||||
.primary-star {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ section {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 4px;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
font-size: 1.5rem;
|
||||
line-height: 1;
|
||||
text-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
|
||||
@@ -511,7 +511,7 @@ ul.section-tip li {
|
||||
.metric-value {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
@@ -535,7 +535,7 @@ ul.section-tip li {
|
||||
|
||||
.timing-total {
|
||||
font-size: 0.8rem;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.timing-bar {
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
.dashboard-metric-value {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ header {
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -103,7 +103,7 @@ h2 {
|
||||
.health-latency {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 400;
|
||||
color: #4CAF50;
|
||||
color: var(--primary-text-color);
|
||||
margin-left: auto;
|
||||
padding-left: 8px;
|
||||
opacity: 0.85;
|
||||
@@ -140,7 +140,7 @@ h2 {
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
border-bottom-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ h2 {
|
||||
}
|
||||
|
||||
.footer-content a {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
text-decoration: none;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
|
||||
.hint-toggle.active {
|
||||
opacity: 1;
|
||||
color: var(--primary-color, #4CAF50);
|
||||
color: var(--primary-text-color, #4CAF50);
|
||||
border-color: var(--primary-color, #4CAF50);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
}
|
||||
|
||||
.add-template-card:hover .add-template-icon {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.add-template-label {
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
.template-config-details summary {
|
||||
cursor: pointer;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
font-weight: 500;
|
||||
padding: 4px 0;
|
||||
}
|
||||
@@ -138,7 +138,7 @@
|
||||
.template-no-config {
|
||||
margin: 12px 0;
|
||||
font-size: 13px;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
font-weight: 500;
|
||||
padding: 4px 0;
|
||||
}
|
||||
@@ -558,7 +558,7 @@
|
||||
}
|
||||
|
||||
.stream-tab-btn.active {
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
border-bottom-color: var(--primary-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--primary-color);
|
||||
background: transparent;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
@@ -95,7 +95,7 @@
|
||||
.tutorial-step-counter {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.tutorial-close-btn {
|
||||
|
||||
Reference in New Issue
Block a user