Files
design-system/components/BaseLayout.astro

95 lines
2.8 KiB
Plaintext

---
/**
* BaseLayout — coquille HTML commune à tous les sites.
*
* Props :
* - title (string, requis) : <title> + og:title
* - description (string) : meta description + og:description
* - lang (string, 'fr') : attribut lang du <html>
* - ogImage (string) : URL absolue de l'image OG
* - canonical (string) : URL canonique
*
* Slots : default (contenu du <main>), header, footer, head (metas en plus).
*
* Le THÈME n'est pas importé ici : le site importe son theme/*.css dans son
* propre layout, à côté de <BaseLayout> (cf. README).
* Gestion clair/sombre : data-theme posé avant le premier paint depuis
* localStorage('tf-theme') ; helper global window.tfSetTheme('dark'|'light'|'auto').
*/
import '../tokens.css';
import '../reset.css';
interface Props {
title: string;
description?: string;
lang?: string;
ogImage?: string;
canonical?: string;
}
const { title, description, lang = 'fr', ogImage, canonical } = Astro.props;
---
<html lang={lang}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{title}</title>
{description && <meta name="description" content={description} />}
{canonical && <link rel="canonical" href={canonical} />}
<meta property="og:title" content={title} />
{description && <meta property="og:description" content={description} />}
<meta property="og:type" content="website" />
{ogImage && <meta property="og:image" content={ogImage} />}
<script is:inline>
(() => {
try {
const t = localStorage.getItem("tf-theme");
if (t === "dark" || t === "light") document.documentElement.dataset.theme = t;
} catch {}
document.documentElement.dataset.js = "";
})();
</script>
<slot name="head" />
</head>
<body>
<a class="tf-skip-link" href="#main">Aller au contenu</a>
<slot name="header" />
<main id="main"><slot /></main>
<slot name="footer" />
<script is:inline>
window.tfSetTheme = (mode) => {
const root = document.documentElement;
try {
if (mode === "auto") {
delete root.dataset.theme;
localStorage.removeItem("tf-theme");
} else {
root.dataset.theme = mode;
localStorage.setItem("tf-theme", mode);
}
} catch {}
};
</script>
</body>
</html>
<style>
.tf-skip-link {
position: absolute;
inset-inline-start: var(--space-md);
inset-block-start: var(--space-md);
z-index: var(--z-toast);
padding: var(--space-xs) var(--space-md);
background: var(--primary);
color: var(--on-primary);
border-radius: var(--radius-md);
text-decoration: none;
transform: translateY(-200%);
}
.tf-skip-link:focus-visible {
transform: none;
}
</style>