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`
`;
}
}
StarlightHeader.define();
export default StarlightHeader;