diff --git a/package.json b/package.json index ab39267ca6..0869824cd4 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,8 @@ "next-query-params": "^5.0.1", "next-sitemap": "^4.2.3", "next-with-less": "^3.0.1", - "nextra": "^3", - "nextra-theme-docs": "^3", + "nextra": "3.3.1", + "nextra-theme-docs": "3.3.1", "numbro": "2.5.0", "p-limit": "^4.0.0", "parser-front-matter": "1.6.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3770393c41..fb8006eaa9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,10 +98,10 @@ importers: specifier: ^3.0.1 version: 3.0.1(less-loader@12.2.0(less@4.2.1))(less@4.2.1)(next@14.2.29(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) nextra: - specifier: ^3 + specifier: 3.3.1 version: 3.3.1(patch_hash=ytqsrocfyxyupt7yg3khzgrhfe)(@types/react@18.3.23)(next@14.2.29(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) nextra-theme-docs: - specifier: ^3 + specifier: 3.3.1 version: 3.3.1(next@14.2.29(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.3.1(patch_hash=ytqsrocfyxyupt7yg3khzgrhfe)(@types/react@18.3.23)(next@14.2.29(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) numbro: specifier: 2.5.0 diff --git a/src/components/index-page/hero.tsx b/src/components/index-page/hero.tsx index 4d8588556a..5e5b709c7d 100644 --- a/src/components/index-page/hero.tsx +++ b/src/components/index-page/hero.tsx @@ -7,7 +7,7 @@ import logoBlurred from "./hero/logo-blurred.png" export function Hero() { return ( -
+

@@ -44,7 +44,7 @@ function HeroStripes() {
void +}): ReactElement { + const routes = Object.fromEntries( + (menu.children || []).map(route => [route.name, route]), + ) + return ( + + + {({ focus, open }) => { + // I'm sorry, I know this is so cursed. + // I need to migrate out of HeadlessUI to something with change handlers. + onSubmenuOpen(open) + + return ( + + ) + }} + + + // eslint-disable-next-line tailwindcss/no-custom-classname + clsx( + "gql-navbar-menu-items", + "motion-reduce:transition-none", + "focus-visible:outline-none", + open ? "opacity-100" : "opacity-0", + "nextra-scrollbar overflow-visible transition-opacity", + "z-20 rounded-md py-1 text-sm", + // headlessui adds max-height as style, use !important to override + "!max-h-[min(calc(100vh-5rem),256px)]", + ) + } + anchor={{ to: "top start", gap: 21, padding: 16, offset: -8 }} + > + {Object.entries(menu.items || {}).map(([key, item]) => ( + + + + {item.title} + + + + ))} + + + ) +} + +export function Navbar({ items }: NavBarProps): ReactElement { + const themeConfig = useThemeConfig() + + const activeRoute = useFSRoute() + const { menu, setMenu } = useMenu() + const [submenuOpen, setSubmenuOpen] = useState(false) + + return ( +
+ + + +
+ ) +} + +function BackdropBlur() { + const mask = "linear-gradient(to bottom, #000 0% 50%, transparent 50% 100%)" + const thickness = "1px" + return ( + <> +
+
+ + ) +} + +export function NavbarPlaceholder({ + className, + ...rest +}: React.HTMLAttributes) { + return ( +
+ ) +} + +function SubmenuBackdrop({ className }: { className: string }) { + return ( +
+ ) +} diff --git a/src/components/utils.tsx b/src/components/utils.tsx new file mode 100644 index 0000000000..9074a85647 --- /dev/null +++ b/src/components/utils.tsx @@ -0,0 +1,8 @@ +export function renderComponent( + ComponentOrNode: React.FC | React.ReactNode, + props?: T, +) { + if (!ComponentOrNode) return null + if (typeof ComponentOrNode !== "function") return ComponentOrNode + return +} diff --git a/src/globals.css b/src/globals.css index 4dbefd6e5c..962c829ce7 100644 --- a/src/globals.css +++ b/src/globals.css @@ -3,12 +3,6 @@ @import "tailwindcss/utilities"; @import "tailwindcss/components"; -/* #region nextra tweaks (preferably removed later, replaced with components) */ -.nextra-nav-container > nav > div:nth-child(2) { - margin-right: auto; -} -/* #endregion nextra tweaks */ - :root { --foreground-rgb: 0, 0, 0; --background-start-rgb: 214, 219, 220; @@ -517,10 +511,15 @@ div[id^="headlessui-menu-items"] { @apply px-4 py-8 lg:px-12 xl:gap-x-24 xl:px-24 3xl:px-[240px]; } +.gql-navbar-strip, .gql-conf-navbar-strip { @apply relative [contain:paint] before:sticky before:top-0 before:z-[9] before:-mt-[var(--navbar-h)] before:block before:h-[var(--navbar-h)] before:w-full before:content-['']; } +.gql-navbar-strip { + --navbar-h: var(--nextra-navbar-height); +} + :root { --navbar-h: 70px; } diff --git a/src/nextra-theme-docs.css b/src/nextra-theme-docs.css index 3a07dfa7d2..fbe3ba187a 100644 --- a/src/nextra-theme-docs.css +++ b/src/nextra-theme-docs.css @@ -2087,56 +2087,6 @@ body, background-color: rgb(var(--nextra-bg)); } } -.nextra-nav-container-blur { - pointer-events: none; - z-index: -1; - --tw-shadow: 0 2px 4px #00000005, 0 1px 0 #0000000f; - --tw-shadow-colored: - 0 2px 4px var(--tw-shadow-color), 0 1px 0 var(--tw-shadow-color); - box-shadow: - var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), - var(--tw-shadow); - width: 100%; - height: 100%; - position: absolute; -} -.nextra-nav-container-blur:is(html[class~="dark"] *) { - --tw-shadow: 0 -1px 0 #ffffff1a inset; - --tw-shadow-colored: inset 0 -1px 0 var(--tw-shadow-color); - box-shadow: - var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), - var(--tw-shadow); -} -@media (prefers-contrast: more) { - .nextra-nav-container-blur { - --tw-shadow: 0 0 0 1px #000; - --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); - box-shadow: - var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), - var(--tw-shadow); - } - .nextra-nav-container-blur:is(html[class~="dark"] *) { - --tw-shadow: 0 0 0 1px #fff; - --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); - box-shadow: - var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), - var(--tw-shadow); - } -} -.nextra-nav-container-blur { - background-color: rgba(var(--nextra-bg), 0.7); - --tw-backdrop-blur: blur(12px); - -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) - var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) - var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) - var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) - var(--tw-backdrop-sepia); - backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) - var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) - var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) - var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) - var(--tw-backdrop-sepia); -} .nextra-toc-footer, .nextra-sidebar-footer { border-top-width: 1px; diff --git a/src/pages/_meta.tsx b/src/pages/_meta.tsx index 104bf3ae14..fa6c9544c6 100644 --- a/src/pages/_meta.tsx +++ b/src/pages/_meta.tsx @@ -80,7 +80,12 @@ export default { }, conf: { type: "page", - title: "GraphQLConf", + title: ( + + GraphQLConf + 2025 + + ), route: "/conf/2025", }, "graphql-js": { diff --git a/theme.config.tsx b/theme.config.tsx index 2580fae932..63fd1090aa 100644 --- a/theme.config.tsx +++ b/theme.config.tsx @@ -1,5 +1,9 @@ import { DocsThemeConfig, ThemeSwitch, useConfig } from "nextra-theme-docs" import NextLink from "next/link" + +import { Navbar } from "@/components/navbar/navbar" +import { useRouter } from "next/router" + import { GraphQLWordmarkLogo, StackOverflowIcon, @@ -7,12 +11,12 @@ import { DiscordIcon, TwitterIcon, } from "./src/icons" -import { useRouter } from "next/router" + // import { createElement } from "react" // import NextImage from "next-image-export-optimizer" const graphQLLogo = ( - + ) const classes = { @@ -201,26 +205,31 @@ export default { ) }, - banner: { - content: ( - <> - 📣 GraphQLConf 2025 • Sept 08-10 • Amsterdam • Early bird tickets - available & sponsorship opportunities open •{" "} - - Learn more - - - ), - key: "graphqlconf-2024", - }, + // Hidden for now, Design is discussing it. + // banner: { + // content: ( + // <> + // 📣 GraphQLConf 2025 • Sept 08-10 • Amsterdam • Early bird tickets + // available & sponsorship opportunities open •{" "} + // + // Learn more + // + // + // ), + // key: "graphqlconf-2024", + // }, logo: graphQLLogo, docsRepositoryBase: "https://github.com/graphql/graphql.github.io/tree/source", color: { hue: 319, + lightness: { + light: 44.1, + dark: 90, + }, }, sidebar: { defaultMenuCollapseLevel: 1, @@ -229,7 +238,10 @@ export default { content: Footer, }, navbar: { - extraContent: , + component: Navbar, + extraContent: ( + + ), }, toc: { backToTop: true,