import { css, html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { tailwind } from '../styles/tailwind.js';
interface NavLink {
readonly href: string;
readonly label: string;
}
const LINKS: readonly NavLink[] = [
{ href: '/', label: 'Home' },
{ href: '/about', label: 'About' },
];
/**
* Site navigation.
*
* The router intercepts these clicks, so these are ordinary anchors. Keeping
* them as real `` elements means middle-click, ctrl-click, "open in
* new tab" and screen-reader link navigation all keep working.
*/
@customElement('app-nav')
export class AppNav extends LitElement {
static override styles = [
tailwind,
css`
:host {
display: block;
}
a {
/*
* Tailwind's preflight strips the default underline, but preflight is
* document-level and is not adopted into shadow roots, so links reset
* themselves here instead.
*/
text-decoration: none;
color: inherit;
}
`,
];
@state()
private currentPath = window.location.pathname;
override connectedCallback(): void {
super.connectedCallback();
// The router pushes state on link clicks, which does not fire popstate,
// so listen for both that and real back/forward navigation.
window.addEventListener('popstate', this.#syncPath);
window.addEventListener('click', this.#syncPathSoon);
}
override disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener('popstate', this.#syncPath);
window.removeEventListener('click', this.#syncPathSoon);
}
override render() {
return html`
`;
}
#syncPath = (): void => {
this.currentPath = window.location.pathname;
};
// Runs after the router's own click handler has pushed the new URL.
#syncPathSoon = (): void => {
queueMicrotask(this.#syncPath);
};
}
declare global {
interface HTMLElementTagNameMap {
'app-nav': AppNav;
}
}