96 lines
2.5 KiB
TypeScript
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
|