Football / src /components /SettingsPanel.js
Prataykarali's picture
Improve accessibility and quality guardrails
e016d0b
Raw
History Blame Contribute Delete
8.44 kB
/**
* Settings Panel — slide-out with toggle switches
*/
import { setHTML } from '../utils/dom.js';
export class SettingsPanel {
constructor(containerEl) {
this.containerEl = containerEl;
this.onChangeCallback = null;
}
render() {
if (!this.containerEl) return;
setHTML(this.containerEl, `
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-lg);">
<h2 id="settings-title" class="settings-title">Settings</h2>
<button id="btn-close-settings" class="icon-btn" aria-label="Close settings" style="width:28px;height:28px;">×</button>
</div>
<div class="setting-group">
<label class="setting-label" for="setting-lang">Language</label>
<select id="setting-lang" class="setting-select">
<option value="en" selected>English</option>
<option value="es">Español (Spanish)</option>
<option value="fr">Français (French)</option>
<option value="de">Deutsch (German)</option>
<option value="pt">Português (Portuguese)</option>
<option value="ar">العربية (Arabic)</option>
<option value="hi">हिन्दी (Hindi)</option>
<option value="bn">বাংলা (Bengali)</option>
<option value="zh">中文 (Chinese)</option>
<option value="ja">日本語 (Japanese)</option>
<option value="ko">한국어 (Korean)</option>
<option value="ta">தமிழ் (Tamil)</option>
<option value="ru">Русский (Russian)</option>
<option value="tr">Türkçe (Turkish)</option>
<option value="it">Italiano (Italian)</option>
<option value="te">తెలుగు (Telugu)</option>
<option value="mr">मराठी (Marathi)</option>
<option value="gu">ગુજરાતી (Gujarati)</option>
<option value="kn">ಕನ್ನಡ (Kannada)</option>
<option value="ml">മലയാളം (Malayalam)</option>
<option value="pa">ਪੰਜਾਬੀ (Punjabi)</option>
<option value="ur">اردو (Urdu)</option>
<option value="id">Bahasa Indonesia (Indonesian)</option>
<option value="vi">Tiếng Việt (Vietnamese)</option>
<option value="th">ไทย (Thai)</option>
<option value="ms">Bahasa Melayu (Malay)</option>
<option value="fil">Filipino</option>
<option value="uk">Українська (Ukrainian)</option>
<option value="he">עברית (Hebrew)</option>
<option value="fa">فارسی (Persian)</option>
<option value="el">Ελληνικά (Greek)</option>
<option value="ro">Română (Romanian)</option>
<option value="hu">Magyar (Hungarian)</option>
<option value="sk">Slovenčina (Slovak)</option>
<option value="bg">Български (Bulgarian)</option>
<option value="hr">Hrvatski (Croatian)</option>
<option value="sr">Српски (Serbian)</option>
<option value="sl">Slovenščina (Slovenian)</option>
<option value="et">Eesti (Estonian)</option>
<option value="lv">Latviešu (Latvian)</option>
<option value="lt">Lietuvių (Lithuanian)</option>
<option value="is">Íslenska (Icelandic)</option>
<option value="ga">Gaeilge (Irish)</option>
<option value="cy">Cymraeg (Welsh)</option>
<option value="sq">Shqip (Albanian)</option>
<option value="mk">Македонски (Macedonian)</option>
<option value="hy">Հայերեն (Armenian)</option>
<option value="ka">ქართული (Georgian)</option>
<option value="az">Azərbaycanca (Azerbaijani)</option>
<option value="kk">Қазақша (Kazakh)</option>
<option value="uz">Oʻzbekcha (Uzbek)</option>
<option value="nl">Nederlands (Dutch)</option>
<option value="sv">Svenska (Swedish)</option>
<option value="da">Dansk (Danish)</option>
<option value="no">Norsk (Norwegian)</option>
<option value="fi">Suomi (Finnish)</option>
<option value="cs">Čeština (Czech)</option>
<option value="pl">Polski (Polish)</option>
</select>
</div>
<div class="setting-group">
<label class="setting-label" for="setting-pace">Pace</label>
<select id="setting-pace" class="setting-select">
<option value="slow">Slow — Dramatic & Detailed</option>
<option value="medium" selected>Medium — Standard</option>
<option value="fast">Fast — Punchy & Rapid</option>
</select>
</div>
<div class="setting-group">
<label class="setting-label" for="setting-register">Style</label>
<select id="setting-register" class="setting-select">
<option value="casual" selected>Casual Fan</option>
<option value="tactical">Tactical Analyst</option>
</select>
</div>
<div class="setting-group">
<label class="setting-label" for="setting-theme">UI Theme</label>
<select id="setting-theme" class="setting-select">
<option value="neon" selected>Neon Athletic (Default)</option>
<option value="cyber">Midnight Cyber (Cyan)</option>
<option value="nightowl">Kolkata 2AM (Warm Amber)</option>
<option value="light">Classic Light (High Contrast)</option>
</select>
</div>
<hr style="border: none; border-top: 1px solid var(--border-subtle); margin: var(--space-lg) 0;" />
<h3 style="font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; margin-bottom: var(--space-md);">Accessibility</h3>
<div class="toggle-row">
<span class="toggle-label">Hearing-Impaired Mode</span>
<button id="toggle-hearing" class="toggle" type="button" role="switch" aria-checked="false" aria-label="Hearing-impaired mode"></button>
</div>
<div class="toggle-row">
<span class="toggle-label">Vision-Impaired (TTS)</span>
<button id="toggle-vision" class="toggle" type="button" role="switch" aria-checked="false" aria-label="Vision-impaired mode"></button>
</div>
<hr style="border: none; border-top: 1px solid var(--border-subtle); margin: var(--space-lg) 0;" />
<h3 style="font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; margin-bottom: var(--space-md);">Operations</h3>
<div class="toggle-row">
<span class="toggle-label">Staff / Organizer Mode</span>
<button id="toggle-staff" class="toggle" type="button" role="switch" aria-checked="false" aria-label="Staff / Organizer Mode"></button>
</div>
`);
this.containerEl.querySelector('#btn-close-settings')?.addEventListener('click', () => {
this.containerEl.dispatchEvent(new Event('vantage:settings-close'));
});
// Toggle switches
['toggle-hearing', 'toggle-vision', 'toggle-staff'].forEach(id => {
const el = this.containerEl.querySelector(`#${id}`);
if (!el) return;
const handler = () => {
el.classList.toggle('toggle--active');
const isActive = el.classList.contains('toggle--active');
el.setAttribute('aria-checked', isActive.toString());
this._emit();
};
el.addEventListener('click', handler);
});
// Select changes
this.containerEl.querySelectorAll('select').forEach(el => {
el.addEventListener('change', () => this._emit());
});
}
_emit() {
if (!this.onChangeCallback) return;
this.onChangeCallback({
language: this.containerEl.querySelector('#setting-lang')?.value || 'en',
pace: this.containerEl.querySelector('#setting-pace')?.value || 'medium',
register: this.containerEl.querySelector('#setting-register')?.value || 'casual',
theme: this.containerEl.querySelector('#setting-theme')?.value || 'neon',
hearingImpaired: this.containerEl.querySelector('#toggle-hearing')?.classList.contains('toggle--active') || false,
visionImpaired: this.containerEl.querySelector('#toggle-vision')?.classList.contains('toggle--active') || false,
staffMode: this.containerEl.querySelector('#toggle-staff')?.classList.contains('toggle--active') || false,
});
}
onSettingsChange(cb) {
this.onChangeCallback = cb;
}
}