gamecult-site/quartz-site/quartz/components/GameCultMasthead.tsx
2026-04-21 02:13:10 +01:00

96 lines
2.5 KiB
TypeScript

import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
import { FullSlug, resolveRelative } from "../util/path"
import { GameCultPageContext } from "./gamecult"
type Route = {
label: string
slug: FullSlug
matches: string[]
}
const routes: Route[] = [
{
label: "Home",
slug: "index" as FullSlug,
matches: ["index"],
},
{
label: "Studio",
slug: "Studio/index" as FullSlug,
matches: ["Studio"],
},
{
label: "Projects",
slug: "Projects/index" as FullSlug,
matches: ["Projects"],
},
{
label: "Blog",
slug: "Blog/index" as FullSlug,
matches: ["Blog"],
},
{
label: "Docs",
slug: "Docs/index" as FullSlug,
matches: ["Docs"],
},
{
label: "Aetheria",
slug: "Aetheria/index" as FullSlug,
matches: ["Aetheria"],
},
]
function isMatch(currentSlug: string, prefix: string) {
return currentSlug === prefix || currentSlug.startsWith(`${prefix}/`)
}
function pickActiveRoute(currentSlug: string) {
return routes
.flatMap((route) =>
route.matches
.filter((prefix) => isMatch(currentSlug, prefix))
.map((prefix) => ({
route,
prefixLength: prefix.length,
})),
)
.sort((a, b) => b.prefixLength - a.prefixLength)[0]?.route
}
export default (() => {
const GameCultMasthead: QuartzComponent = ({
fileData,
gamecult,
}: QuartzComponentProps & { gamecult?: GameCultPageContext }) => {
const currentSlug = fileData.slug ?? ("index" as FullSlug)
const tagline = gamecult?.headerTagline
const activeRoute = pickActiveRoute(currentSlug)
return (
<section class="gamecult-titlebar">
<div class="gamecult-titlebar-copy">
<p class="gamecult-titlebar-title">
<a href={resolveRelative(currentSlug, "index" as FullSlug)}>GameCult</a>
</p>
{tagline && <p class="gamecult-titlebar-tagline">{tagline}</p>}
</div>
<nav class="gamecult-titlebar-nav" aria-label="GameCult sections">
{routes.map((route) => {
const active = activeRoute?.slug === route.slug
return (
<a
href={resolveRelative(currentSlug, route.slug)}
class={active ? "gamecult-nav-chip active" : "gamecult-nav-chip"}
>
{route.label}
</a>
)
})}
</nav>
</section>
)
}
return GameCultMasthead
}) satisfies QuartzComponentConstructor