71 lines
2 KiB
Text
71 lines
2 KiB
Text
---
|
|
import type { ImageMetadata } from 'astro';
|
|
import type { CollectionEntry } from 'astro:content';
|
|
import { ClientRouter } from 'astro:transitions';
|
|
import BaseHead from '~/components/BaseHead.astro';
|
|
import Footer from '~/components/Footer.astro';
|
|
import Header from '~/components/Header.astro';
|
|
import { DEFAULT_LOCALE, type Locale } from '~/consts';
|
|
import { getLocaleFromUrl } from '~/i18n/ui';
|
|
|
|
interface Props {
|
|
title: string;
|
|
description: string;
|
|
locale?: Locale;
|
|
image?: ImageMetadata;
|
|
/** Current content entry, used for the language switcher's translation lookup. */
|
|
entry?: CollectionEntry<'posts' | 'categories'>;
|
|
/** Optional extra class on `<body>` for per-page styling hooks. */
|
|
bodyClass?: string;
|
|
}
|
|
|
|
const {
|
|
title,
|
|
description,
|
|
image,
|
|
entry,
|
|
bodyClass,
|
|
locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE,
|
|
} = Astro.props;
|
|
---
|
|
|
|
<!doctype html>
|
|
<html lang={locale}>
|
|
<head>
|
|
<BaseHead title={title} description={description} image={image} locale={locale} />
|
|
<script is:inline>
|
|
(() => {
|
|
const root = document.documentElement;
|
|
const apply = () => {
|
|
const stored = localStorage.getItem('theme');
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
const theme = stored === 'dark' || stored === 'light' ? stored : prefersDark ? 'dark' : 'light';
|
|
root.dataset.theme = theme;
|
|
};
|
|
apply();
|
|
const enableTransitions = () => {
|
|
requestAnimationFrame(() =>
|
|
requestAnimationFrame(() => root.setAttribute('data-theme-ready', '')),
|
|
);
|
|
};
|
|
enableTransitions();
|
|
document.addEventListener('astro:before-swap', () => {
|
|
root.removeAttribute('data-theme-ready');
|
|
});
|
|
document.addEventListener('astro:after-swap', () => {
|
|
apply();
|
|
enableTransitions();
|
|
});
|
|
})();
|
|
</script>
|
|
<ClientRouter />
|
|
<slot name="head" />
|
|
</head>
|
|
<body class={bodyClass}>
|
|
<Header locale={locale} entry={entry} />
|
|
<main transition:animate="fade">
|
|
<slot />
|
|
</main>
|
|
<Footer locale={locale} transition:persist />
|
|
</body>
|
|
</html>
|