Files
ResumeSite/site/src/scripts/theme.ts
T
cesnimda 1fce1b3cec feat: core layout, UI atoms, homepage + behaviour modules
- UI atoms: Chip, Button, SplitCvButton, LangSwitch, ThemeToggle, Card,
  SectionLabel, TraceMotif, FramedImage
- core: Base/Seo/Header/MobileNav/Footer/HintBar/SkipLink/ThemeScript
- homepage sections: Hero, ProofStrip, SkillsGrid, ProjectCards,
  ExperienceTimeline, AboutTeaser, ContactBand + Homepage composition (EN/NO)
- behaviour modules: theme, nav (overlay/hint/copy/header), observer (reveal/spy),
  lightbox, form — progressive enhancement, fail-silent
- SEO head component: meta, hreflang from slug map, JSON-LD, OG references
- move content data to src/data (avoid Astro reserved content-collection folder)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 01:20:46 +02:00

29 lines
891 B
TypeScript

/*
Theme toggle (A6). The no-flash init in ThemeScript already set data-theme before
paint; this only wires the button, persists the choice, and keeps the aria-label
describing the *next* action. Fail-silent if the button is absent.
*/
const html = document.documentElement;
const btn = document.getElementById('theme-toggle');
function labelFor(theme: string): string {
if (!btn) return '';
return theme === 'dark'
? (btn.dataset.toLight ?? '')
: (btn.dataset.toDark ?? '');
}
if (btn) {
btn.setAttribute('aria-label', labelFor(html.dataset.theme ?? 'dark'));
btn.addEventListener('click', () => {
const next = html.dataset.theme === 'light' ? 'dark' : 'light';
html.dataset.theme = next;
try {
localStorage.setItem('theme', next);
} catch {
/* private mode — ignore */
}
btn.setAttribute('aria-label', labelFor(next));
});
}