diff --git a/app/components/syntax/Navigation.tsx b/app/components/syntax/Navigation.tsx index f543071..1ae09f1 100644 --- a/app/components/syntax/Navigation.tsx +++ b/app/components/syntax/Navigation.tsx @@ -2,7 +2,7 @@ import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/solid"; import { usePageContext } from "vike-react/usePageContext"; import { Link } from "@/components/common/Link"; import { navigation } from "@/lib/navigation"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import clsx from "clsx"; type NavigationItemProps = { @@ -50,50 +50,101 @@ function NavigationItem(props: NavigationItemProps) { {isOpened && ( + )} + + ); +} + +type NavigationSubItemProps = { + link: (typeof navigation)[number]["links"][number]; + onLinkClick?: React.MouseEventHandler; + isOpened?: boolean; +}; + +function NavigationSubItem(props: NavigationSubItemProps) { + const [isOpened, setIsOpened] = useState(props.isOpened); + const { urlPathname } = usePageContext(); + + useEffect(() => { + setIsOpened( + props.link.href === urlPathname || props.link.subitems?.some((subitem) => subitem.href === urlPathname), + ); + }, [urlPathname, props.link]); + + return ( + <> + + {props.link.subitems.length > 0 && ( + { + if (e.key === "Enter" || e.key === " ") { + setIsOpened((prev) => !prev); + e.preventDefault(); + } + }} + onClick={() => setIsOpened((prev) => !prev)} + > + {isOpened ? ( + + ) : ( + + )} + {isOpened ? "Masquer" : "Afficher"} + + )} + + + {props.link.title} + {props.link.subitems.length > 0 && ( + ({props.link.subitems.length}) + )} + + + {props.link.subitems && isOpened && ( + diff --git a/app/lib/navigation.ts b/app/lib/navigation.ts index da9785d..3add153 100644 --- a/app/lib/navigation.ts +++ b/app/lib/navigation.ts @@ -11,9 +11,14 @@ export type NavigationSection = { links: NavigationLink[]; }; +export type NavigationOG = Partial<{ + image: string; +}>; + export type NavigationLink = { title: string; href: string; + og?: NavigationOG; subitems: NavigationSubItem[]; }; @@ -101,6 +106,7 @@ export const navigation: NavigationSection[] = [ { title: "Merise", href: "/docs/merise", + og: { image: "/merise/og.webp" }, subitems: [ { title: "Introduction", href: "/docs/merise" }, { title: "Dictionnaire de données", href: "/docs/merise/dictionnaire-de-donnees" }, @@ -112,3 +118,16 @@ export const navigation: NavigationSection[] = [ ], }, ]; + +export function findNavigationLink(namespace: string, href: string) { + const currentUrl = `/${namespace}/${href}`.replace(/\/+/g, "/").replace(/\/$/, ""); + + const links = navigation.flatMap((section) => section.links); + const subitems = links.flatMap((link) => link.subitems); + const allLinks = new Set([...links, ...subitems]); + const foundLink = Array.from(allLinks).find((link) => link.href === currentUrl); + + console.log({ allLinks, currentUrl }); + + return foundLink; +} diff --git a/app/pages/+Head.tsx b/app/pages/+Head.tsx index 429fd8a..48371af 100644 --- a/app/pages/+Head.tsx +++ b/app/pages/+Head.tsx @@ -1,4 +1,4 @@ -import logoUrl from "../assets/logo.svg"; +import logoUrl from "@/assets/logo.svg"; export default function HeadDefault() { return ( diff --git a/app/pages/+config.ts b/app/pages/+config.ts index 80c7eee..ac63eef 100644 --- a/app/pages/+config.ts +++ b/app/pages/+config.ts @@ -23,6 +23,8 @@ export default { class: "flex min-h-full bg-white dark:bg-slate-900", }, + image: null, + // prerender: true, prefetchStaticAssets: "hover", diff --git a/app/pages/docs/+data.ts b/app/pages/docs/+data.ts index 68da945..abfc020 100644 --- a/app/pages/docs/+data.ts +++ b/app/pages/docs/+data.ts @@ -1,6 +1,7 @@ import type { PageContext } from "vike/types"; import { snippetsService } from "@/services/SnippetsService"; +import { findNavigationLink } from "@/lib/navigation"; import { docsService } from "@/services/DocsService"; import { readingTime } from "reading-time-estimator"; import { useConfig } from "vike-react/useConfig"; @@ -15,6 +16,7 @@ export async function data(pageContext: PageContext) { const { key } = pageContext.routeParams; const doc = await docsService.getDoc("docs", key); + const link = findNavigationLink("docs", key); if (!doc) { throw render(404); @@ -25,6 +27,7 @@ export async function data(pageContext: PageContext) { config({ title: buildTitle(doc.title), description: doc.description, + image: link?.og?.image || "notfound", }); docsService.transform(doc); diff --git a/app/public/merise/og.webp b/app/public/merise/og.webp new file mode 100644 index 0000000..8dfbe5e Binary files /dev/null and b/app/public/merise/og.webp differ