diff --git a/app/layout.tsx b/app/layout.tsx index 161da56..bc0ee62 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -116,7 +116,13 @@ export default function LocaleLayout(props: LocaleLayoutProps): ReactNode { diff --git a/app/works/[category]/[work]/page.tsx b/app/works/[category]/[work]/page.tsx index fbd50ae..4266b08 100644 --- a/app/works/[category]/[work]/page.tsx +++ b/app/works/[category]/[work]/page.tsx @@ -2,9 +2,7 @@ import { useTranslations } from "next-intl"; -import { AppNavLink } from "@/components/app-nav-link"; import { SimpleListing } from "@/components/simple-listing"; -import { otherCategories, proseCategories } from "@/lib/model"; interface WorksPageProps { params?: { @@ -17,46 +15,15 @@ export default function WorksPage(props: WorksPageProps) { const catt = useTranslations("BernhardCategories"); const _t = useTranslations("WorkPage"); return ( -
-
- {otherCategories.map((c) => { - return ( - - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - catt(c as any) - } - - ); - })} -
-
- {props.params?.category === "prose" || - (proseCategories as unknown as Array).includes( - props.params?.category as unknown as string, - ) - ? proseCategories.map((c) => { - return ( - - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - catt(c as any) - } - - ); - }) - : null} -
- -
+ ); } diff --git a/components/app-header-nav-menu.tsx b/components/app-header-nav-menu.tsx new file mode 100644 index 0000000..205a389 --- /dev/null +++ b/components/app-header-nav-menu.tsx @@ -0,0 +1,114 @@ +"use client"; +import { useTranslations } from "next-intl"; +import { type ReactNode, useId, useState } from "react"; + +import { AppNavLink } from "@/components/app-nav-link"; +import type { LinkProps } from "@/components/link"; +import { createHref } from "@/lib/create-href"; +import { otherCategories, proseCategories } from "@/lib/model"; +import { usePathname } from "@/lib/navigation"; + +import { DisclosureButton } from "./disclosure-button"; + +export function AppHeaderNavMenu(): ReactNode { + const t = useTranslations("AppHeader"); + const catt = useTranslations("BernhardCategories"); + + const links = { + home: { href: createHref({ pathname: "/" }), label: t("links.home") }, + languages: { + href: createHref({ pathname: "/languages" }), + label: t("links.languages"), + }, + translators: { + href: createHref({ pathname: "/translators" }), + label: t("links.translators"), + }, + search: { + href: createHref({ pathname: "/search" }), + label: t("links.search"), + }, + } satisfies Record; + + const worksMenu = useId(); + const proseMenu = useId(); + + // disclosures might start off open if we first land on a work page + const pathname = usePathname(); + const [proseMenuOpen, setProseMenuOpen] = useState( + proseCategories.some((c) => { + return pathname.startsWith(`/works/${c}`); + }), + ); + const [worksMenuOpen, setWorksMenuOpen] = useState( + proseMenuOpen || + otherCategories.some((c) => { + return pathname.startsWith(`/works/${c}`); + }), + ); + + return ( + + ); +} diff --git a/components/app-header.tsx b/components/app-header.tsx index a762953..f76a084 100644 --- a/components/app-header.tsx +++ b/components/app-header.tsx @@ -1,34 +1,11 @@ -import { useTranslations } from "next-intl"; import type { ReactNode } from "react"; -import { AppNavLink } from "@/components/app-nav-link"; import { ColorSchemeSwitcher } from "@/components/color-scheme-switcher"; -import { Link, type LinkProps } from "@/components/link"; -import { createHref } from "@/lib/create-href"; +import { Link } from "@/components/link"; -export function AppHeader(): ReactNode { - const t = useTranslations("AppHeader"); - - const links = { - home: { href: createHref({ pathname: "/" }), label: t("links.home") }, - works: { - href: createHref({ pathname: "/works/novels" }), - label: t("links.works"), - }, - languages: { - href: createHref({ pathname: "/languages" }), - label: t("links.languages"), - }, - translators: { - href: createHref({ pathname: "/translators" }), - label: t("links.translators"), - }, - search: { - href: createHref({ pathname: "/search" }), - label: t("links.search"), - }, - } satisfies Record; +import { AppHeaderNavMenu } from "./app-header-nav-menu"; +export function AppHeader(): ReactNode { return (
@@ -37,17 +14,7 @@ export function AppHeader(): ReactNode { thomas bernhard in translation
- +
diff --git a/components/disclosure-button.tsx b/components/disclosure-button.tsx new file mode 100644 index 0000000..6285aed --- /dev/null +++ b/components/disclosure-button.tsx @@ -0,0 +1,25 @@ +import type { ReactNode } from "react"; + +interface DisclosureButtonProps { + controls: string; + label: string; + state: boolean; + // eslint-disable-next-line @typescript-eslint/ban-types + setState: Function; +} + +export function DisclosureButton(props: DisclosureButtonProps): ReactNode { + const toggleState = () => { + props.setState(!props.state); + }; + return ( + + ); +}