diff --git a/astro.config.ts b/astro.config.ts index d9f6ef3f502980e..5d67bdf4bea9ac1 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -103,11 +103,11 @@ export default defineConfig({ components: { Footer: "./src/components/overrides/Footer.astro", Head: "./src/components/overrides/Head.astro", + Header: "./src/components/overrides/Header.astro", Hero: "./src/components/overrides/Hero.astro", MarkdownContent: "./src/components/overrides/MarkdownContent.astro", Sidebar: "./src/components/overrides/Sidebar.astro", PageTitle: "./src/components/overrides/PageTitle.astro", - SocialIcons: "./src/components/overrides/SocialIcons.astro", TableOfContents: "./src/components/overrides/TableOfContents.astro", }, sidebar, diff --git a/package-lock.json b/package-lock.json index 169fcef653db3b6..f036a10d63e23e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@cloudflare/workers-types": "4.20250303.0", "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.40.2", + "@floating-ui/react": "0.27.5", "@iarna/toml": "2.2.5", "@marsidev/react-turnstile": "1.1.0", "@octokit/webhooks-types": "7.6.1", @@ -2548,6 +2549,64 @@ "node": ">=14" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.5.tgz", + "integrity": "sha512-BX3jKxo39Ba05pflcQmqPPwc0qdNsdNi/eweAFtoIdrJWNen2sVEWMEac3i6jU55Qfx+lOcdMNKYn2CtWmlnOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.9", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "dev": true, + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -16852,6 +16911,13 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", diff --git a/package.json b/package.json index 50d9eec3ada1ea4..44064460e7590de 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@cloudflare/workers-types": "4.20250303.0", "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.40.2", + "@floating-ui/react": "0.27.5", "@iarna/toml": "2.2.5", "@marsidev/react-turnstile": "1.1.0", "@octokit/webhooks-types": "7.6.1", diff --git a/src/components/HeaderDropdowns.tsx b/src/components/HeaderDropdowns.tsx new file mode 100644 index 000000000000000..0a8ed8f9027052d --- /dev/null +++ b/src/components/HeaderDropdowns.tsx @@ -0,0 +1,95 @@ +import { + useFloating, + useInteractions, + useClick, + useDismiss, + shift, + offset, + autoUpdate, +} from "@floating-ui/react"; +import { useState } from "react"; +import { PiCaretDownBold } from "react-icons/pi"; + +const dropdowns = Object.entries({ + "API & SDKs": [ + { + label: "API documentation", + href: "https://developers.cloudflare.com/api/", + }, + { label: "SDKs", href: "/fundamentals/api/reference/sdks/" }, + ], + Help: [ + { label: "Help center", href: "https://support.cloudflare.com/" }, + { label: "Cloudflare status", href: "https://www.cloudflarestatus.com/" }, + { label: "Community", href: "https://community.cloudflare.com/" }, + ], +}); + +function Dropdown({ dropdown }: { dropdown: (typeof dropdowns)[number] }) { + const [label, pages] = dropdown; + const [isOpen, setIsOpen] = useState(false); + + const { refs, floatingStyles, context } = useFloating({ + open: isOpen, + onOpenChange: setIsOpen, + middleware: [shift(), offset(5)], + whileElementsMounted: autoUpdate, + }); + + const click = useClick(context); + const dismiss = useDismiss(context); + + const { getReferenceProps, getFloatingProps } = useInteractions([ + click, + dismiss, + ]); + + return ( + <> + + {isOpen && ( + + )} + + ); +} + +export default function HeaderDropdownsComponent() { + return ( +
+ + Docs Directory + + {dropdowns.map((dropdown) => ( + + ))} +
+ ); +} diff --git a/src/components/overrides/Header.astro b/src/components/overrides/Header.astro new file mode 100644 index 000000000000000..158974662a24490 --- /dev/null +++ b/src/components/overrides/Header.astro @@ -0,0 +1,66 @@ +--- +import LanguageSelect from "@astrojs/starlight/components/LanguageSelect.astro"; +import DocSearch from "@astrojs/starlight-docsearch/DocSearch.astro"; +import SiteTitle from "@astrojs/starlight/components/SiteTitle.astro"; +import SocialIcons from "@astrojs/starlight/components/SocialIcons.astro"; +import ThemeSelect from "@astrojs/starlight/components/ThemeSelect.astro"; + +import HeaderDropdowns from "../HeaderDropdowns.tsx"; +--- + +
+ +
+
+ +
+ +
+
+ + diff --git a/src/components/overrides/SocialIcons.astro b/src/components/overrides/SocialIcons.astro deleted file mode 100644 index c40ac1c4d199d4f..000000000000000 --- a/src/components/overrides/SocialIcons.astro +++ /dev/null @@ -1,33 +0,0 @@ ---- -import Default from "@astrojs/starlight/components/SocialIcons.astro"; - -const links = Object.entries({ - Products: "/products/", - Learning: "/learning-paths/", - Status: "https://www.cloudflarestatus.com/", - Support: "/support/contacting-cloudflare-support/", - "Log in": "https://dash.cloudflare.com", -}); ---- - - - - - diff --git a/src/styles/title.css b/src/styles/title.css deleted file mode 100644 index ec82711a53728a9..000000000000000 --- a/src/styles/title.css +++ /dev/null @@ -1,11 +0,0 @@ -.site-title { - gap: calc(0.5 * var(--sl-nav-gap)); - - span { - color: var(--sl-color-white); - } - - img { - height: calc(var(--sl-nav-height) - 3 * var(--sl-nav-pad-y)); - } -}