Skip to content

Adding a sub nav to the docs section to reduce the amount of content in the main nav #1031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 8, 2025
2 changes: 1 addition & 1 deletion src/SyntaxLookup.res
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ let default = (props: props) => {
<div className="text-gray-80">
<Navigation isOverlayOpen setOverlayOpen />
<div className="flex xs:justify-center overflow-hidden pb-48">
<main className="mt-16 min-w-320 lg:align-center w-full px-4 md:px-8 max-w-1280">
<main className="mt-24 min-w-320 lg:align-center w-full px-4 md:px-8 max-w-1280">
<MdxProvider components=MarkdownComponents.default>
<div className="flex justify-center">
<div className="max-w-740 w-full"> content </div>
Expand Down
213 changes: 122 additions & 91 deletions src/components/Navigation.res
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
module Link = Next.Link

let link = "no-underline block hover:cursor-pointer hover:text-fire-30 text-gray-40 mb-px"
let link = "no-underline block hover:cursor-pointer hover:text-fire-30 mb-px"
let activeLink = "font-medium text-fire-30 border-b border-fire"

let linkOrActiveLink = (~target, ~route) => target === route ? activeLink : link

let linkOrActiveLinkSubroute = (~target, ~route) =>
String.startsWith(route, target) ? activeLink : link

let isActiveLink = (~route: string, ~href: string) => {
route == href ? activeLink : link
let isActiveLink = (~includes: string, ~excludes: option<string>=?, ~route: string) => {
// includes means we want the lnk to be active if it contains the expected text
let includes = route->String.includes(includes)
// excludes allows us to not have links be active even if they do have the includes text
let excludes = switch excludes {
| Some(excludes) => route->String.includes(excludes)
| None => false
}
includes && !excludes ? activeLink : link
}

let isDocRoute = (~route) =>
route->String.includes("/docs/") || route->String.includes("/syntax-lookup")

let isDocRouteActive = (~route) => isDocRoute(~route) ? activeLink : link

module MobileNav = {
@react.component
let make = (~route: string) => {
let base = "font-normal mx-4 py-5 text-gray-20 border-b border-gray-80"
let base = "font-normal mx-4 py-5 text-gray-40 border-b border-gray-80"
let extLink = "block hover:cursor-pointer hover:text-white text-gray-60"
<div className="border-gray-80 border-t">
<div className="border-gray-80 border-tn">
<ul>
<li className=base>
<Link href="/try" className={linkOrActiveLink(~target="/try", ~route)}>
Expand Down Expand Up @@ -73,98 +85,117 @@ let make = (~fixed=true, ~isOverlayOpen: bool, ~setOverlayOpen: (bool => bool) =
let fixedNav = fixed ? "fixed top-0" : "relative"

<>
<nav
<header
id="header"
style={ReactDOMStyle.make(~minWidth, ())}
className={fixedNav ++ " items-center z-50 px-4 flex xs:justify-center w-full h-16 bg-gray-90 shadow text-white-80 text-14 transition duration-300 ease-out group-[.nav-disappear]:-translate-y-16 md:group-[.nav-disappear]:transform-none"}>
<div className="flex justify-between items-center h-full w-full max-w-1280">
<div className="h-8 w-8 lg:h-10 lg:w-32">
<a
href="/"
className="block hover:cursor-pointer w-full h-full flex justify-center items-center font-bold">
<img src="/static/[email protected]" className="lg:hidden" />
<img src="/static/[email protected]" className="hidden lg:block" />
</a>
</div>
/* Desktop horizontal navigation */
<div
className="flex items-center xs:justify-between w-full bg-gray-90 sm:h-auto sm:relative">
<div
className="flex ml-10 space-x-5 w-full max-w-320"
style={ReactDOMStyle.make(~maxWidth="26rem", ())}>
<Link
href={`/docs/manual/${version}/introduction`}
className={isActiveLink(~route, ~href=`/docs/manual/${version}/introduction`)}>
{React.string("Docs")}
</Link>
<Link
href={`/docs/manual/${version}/api`}
className={isActiveLink(~route, ~href=`/docs/manual/${version}/api`)}>
{React.string("API")}
</Link>
<Link href={`/syntax-lookup`} className={isActiveLink(~route, ~href=`/syntax-lookup`)}>
{React.string("Syntax")}
</Link>
<Link
href={`/docs/react/latest/introduction`}
className={isActiveLink(~route, ~href=`/docs/react/latest/introduction`)}>
{React.string("React")}
</Link>
<Link
href="/try"
className={"hidden xs:block " ++ linkOrActiveLink(~target="/try", ~route)}>
{React.string("Playground")}
</Link>
<Link
href="/blog"
className={"hidden xs:block " ++ linkOrActiveLinkSubroute(~target="/blog", ~route)}>
{React.string("Blog")}
</Link>
<Link
href="/community/overview"
className={"hidden xs:block " ++ linkOrActiveLink(~target="/community", ~route)}>
{React.string("Community")}
</Link>
className={fixedNav ++ " items-center z-50 w-full transition duration-300 ease-out group-[.nav-disappear]:-translate-y-16 md:group-[.nav-disappear]:transform-none"}>
<nav className="px-4 flex xs:justify-center bg-gray-90 shadow h-16 text-white-80 text-14">
<div className="flex justify-between items-center h-full w-full max-w-1280">
<div className="h-8 w-8 lg:h-10 lg:w-32">
<a
href="/"
className="block hover:cursor-pointer w-full h-full flex justify-center items-center font-bold">
<img src="/static/[email protected]" className="lg:hidden" />
<img src="/static/[email protected]" className="hidden lg:block" />
</a>
</div>
<div className="md:flex flex items-center">
<Search />
<div className="hidden md:flex items-center ml-5">
<a href=Constants.githubHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.GitHub className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.xHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.X className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.blueSkyHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.Bluesky className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.discourseHref rel="noopener noreferrer" className=link>
<Icon.Discourse className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
/* Desktop horizontal navigation */
<div
className="flex items-center xs:justify-between w-full bg-gray-90 sm:h-auto sm:relative">
<div
className="flex ml-10 space-x-5 w-full max-w-320 text-gray-40"
style={ReactDOMStyle.make(~maxWidth="26rem", ())}>
<Link
href={`/docs/manual/${version}/introduction`} className={isDocRouteActive(~route)}>
{React.string("Docs")}
</Link>

<Link
href="/try"
className={"hidden xs:block " ++ linkOrActiveLink(~target="/try", ~route)}>
{React.string("Playground")}
</Link>
<Link
href="/blog"
className={"hidden xs:block " ++ linkOrActiveLinkSubroute(~target="/blog", ~route)}>
{React.string("Blog")}
</Link>
<Link
href="/community/overview"
className={"hidden xs:block " ++ linkOrActiveLink(~target="/community", ~route)}>
{React.string("Community")}
</Link>
</div>
<div className="md:flex flex items-center text-gray-60">
<Search />
<div className="hidden md:flex items-center ml-5">
<a href=Constants.githubHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.GitHub className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.xHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.X className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.blueSkyHref rel="noopener noreferrer" className={"mr-5 " ++ link}>
<Icon.Bluesky className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
<a href=Constants.discourseHref rel="noopener noreferrer" className=link>
<Icon.Discourse className="w-6 h-6 opacity-50 hover:opacity-100" />
</a>
</div>
</div>
</div>
</div>
</div>
/* Burger Button */
<button
className="h-full px-4 xs:hidden flex items-center hover:text-white"
onClick={evt => {
ReactEvent.Mouse.preventDefault(evt)
toggleOverlay()
}}>
<Icon.DrawerDots
className={"h-1 w-auto block " ++ (isOverlayOpen ? "text-fire" : "text-gray-60")}
/>
</button>
/* Mobile overlay */
<div
style={ReactDOMStyle.make(~minWidth, ~top="4rem", ())}
className={(
isOverlayOpen ? "flex" : "hidden"
) ++ " sm:hidden flex-col fixed top-0 left-0 h-full w-full z-50 sm:w-9/12 bg-gray-100 sm:h-auto sm:flex sm:relative sm:flex-row sm:justify-between"}>
<MobileNav route />
</div>
</nav>
/* Burger Button */
<button
className="h-full px-4 xs:hidden flex items-center hover:text-white"
onClick={evt => {
ReactEvent.Mouse.preventDefault(evt)
toggleOverlay()
}}>
<Icon.DrawerDots
className={"h-1 w-auto block " ++ (isOverlayOpen ? "text-fire" : "text-gray-60")}
/>
</button>
/* Mobile overlay */
<div
style={ReactDOMStyle.make(~minWidth, ~top="4rem", ())}
className={(
isOverlayOpen ? "flex" : "hidden"
) ++ " sm:hidden flex-col fixed top-0 left-0 h-full w-full z-50 sm:w-9/12 bg-gray-100 sm:h-auto sm:flex sm:relative sm:flex-row sm:justify-between"}>
<MobileNav route />
</div>
</nav>
// This is a subnav for documentation pages
{isDocRoute(~route)
? <nav
id="docs-subnav"
className="bg-white z-50 px-4 w-full h-12 shadow text-gray-60 text-12 md:text-14 transition duration-300 ease-out group-[.nav-disappear]:-translate-y-16 md:group-[.nav-disappear]:transform-none">
<div
className="pl-30 flex gap-6 lg:gap-10 items-center h-full w-full max-w-1280 m-auto">
<Link
href={`/docs/manual/${version}/introduction`}
className={isActiveLink(~includes="/docs/manual/", ~excludes="/api", ~route)}>
{React.string("Language Manual")}
</Link>
<Link
href={`/docs/manual/${version}/api`}
className={isActiveLink(~includes="/api", ~route)}>
{React.string("API")}
</Link>
<Link
href={`/syntax-lookup`}
className={isActiveLink(~includes="/syntax-lookup", ~route)}>
{React.string("Syntax Lookup")}
</Link>
<Link
href={`/docs/react/latest/introduction`}
className={isActiveLink(~includes="/docs/react/", ~route)}>
{React.string("React")}
</Link>
</div>
</nav>
: React.null}
</header>
</>
}

Expand Down
11 changes: 6 additions & 5 deletions src/layouts/SidebarLayout.res
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,15 @@ module Sidebar = {
id="sidebar"
className={(
isOpen ? "fixed w-full left-0 h-full z-20 min-w-320" : "hidden "
) ++ " md:block md:w-48 md:-ml-4 lg:w-1/5 md:h-auto md:relative overflow-y-visible bg-white"}>
) ++ " overflow-x-hidden md:block md:w-48 md:-ml-4 lg:w-1/5 md:h-auto md:relative overflow-y-visible bg-white"}>
<aside
id="sidebar-content"
className="relative top-0 px-4 w-full block md:top-16 md:pt-16 md:sticky border-r border-gray-20 overflow-y-auto pb-24"
className="relative top-0 px-4 w-full block md:top-16 md:pt-4 md:sticky border-r border-gray-20 overflow-y-auto pb-24"
style={ReactDOMStyle.make(~height="calc(100vh - 4.5rem", ())}>
<div className="flex justify-between">
<div className="w-3/4 md:w-full"> toplevelNav </div>
<button
style={{paddingTop: "72px"}}
onClick={evt => {
ReactEvent.Mouse.preventDefault(evt)
toggle()
Expand Down Expand Up @@ -309,18 +310,18 @@ let make = (
<div className="flex lg:justify-center">
<div className="flex w-full max-w-1280 md:mx-8">
sidebar
<main className="px-4 w-full pt-16 md:ml-12 lg:mr-8 mb-32 md:max-w-576 lg:max-w-740">
<main className="px-4 w-full pt-20 md:ml-12 lg:mr-8 mb-32 md:max-w-576 lg:max-w-740">
//width of the right content part
<div
className={"z-10 fixed border-b shadow top-16 left-0 pl-4 bg-white w-full py-4 md:relative md:border-none md:shadow-none md:p-0 md:top-auto flex items-center transition duration-300 ease-out group-[.nav-disappear]:-translate-y-32 md:group-[.nav-disappear]:transform-none"}>
className={"z-10 fixed border-b shadow top-[112px] left-0 pl-4 bg-white w-full py-4 md:relative md:border-none md:shadow-none md:p-0 md:top-auto flex items-center transition duration-300 ease-out group-[.nav-disappear]:-translate-y-32 md:group-[.nav-disappear]:transform-none"}>
<MobileDrawerButton hidden=isNavOpen onClick={handleDrawerButtonClick} />
<div
className="truncate overflow-x-auto touch-scroll flex items-center space-x-4 md:justify-between mr-4 w-full">
breadcrumbs
editLinkEl
</div>
</div>
<div className={hasBreadcrumbs ? "mt-10" : "-mt-4"}>
<div className={hasBreadcrumbs ? "mt-10" : "mt-6 md:-mt-4"}>
<MdxProvider components> children </MdxProvider>
</div>
pagination
Expand Down