import { Elena, html, unsafeHTML } from '@elenajs/core'; export interface NavItem { label: string; href: string; } /** * * Top navigation bar with site title, nav links, and dark/light theme toggle. * Light DOM — styles scoped via @scope. * */ export class StarlightHeader extends Elena(HTMLElement) { static tagName = 'starlight-header'; static props = ['sitetitle', 'nav', 'currentpath', 'navopen', 'hassidebar', '_theme']; sitetitle = ''; nav: NavItem[] = []; currentpath = ''; navopen = false; hassidebar = false; _theme = 'light'; private _initialized = false; override connectedCallback(): void { super.connectedCallback(); if (!this._initialized && typeof localStorage !== 'undefined') { const stored = localStorage.getItem('sl-theme') ?? 'light'; this._theme = stored; if (typeof document !== 'undefined') { document.documentElement.setAttribute('data-theme', stored); } this._initialized = true; } // Elena renders plain HTML — wire up click events via delegation this.addEventListener('click', this._handleClick); } override disconnectedCallback(): void { super.disconnectedCallback(); this.removeEventListener('click', this._handleClick); } private _handleClick = (e: Event) => { const btn = (e.target as HTMLElement).closest('[data-action]') as HTMLElement | null; if (!btn) return; const action = btn.getAttribute('data-action'); if (action === 'toggle-theme') this.toggleTheme(); else if (action === 'toggle-nav') this.toggleNav(); }; toggleTheme() { const next = this._theme === 'light' ? 'dark' : 'light'; this._theme = next; if (typeof localStorage !== 'undefined') { localStorage.setItem('sl-theme', next); } if (typeof document !== 'undefined') { document.documentElement.setAttribute('data-theme', next); } } toggleNav() { this.dispatchEvent( new CustomEvent('sl-nav-toggle', { bubbles: true, composed: true }), ); } render() { const menuBtnClass = this.hassidebar ? `menu-btn${this.navopen ? ' nav-open' : ''}` : 'menu-btn menu-btn-hidden'; const navLinks = (this.nav || []).map(item => { const current = this.currentpath.startsWith(item.href) ? 'page' : 'false'; return `${item.label}`; }).join(''); const themeLabel = this._theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'; const themeIcon = this._theme === 'dark' ? '\u2600\uFE0F' : '\uD83C\uDF19'; return html`
${this.sitetitle}
`; } } StarlightHeader.define(); export default StarlightHeader;