diff --git a/src/common/App.res b/src/common/App.res index 78dfde1f5..a00eec866 100644 --- a/src/common/App.res +++ b/src/common/App.res @@ -32,6 +32,21 @@ hljs.registerLanguage('diff', diff) `) +module EnableCollapsibleNavbar = { + @react.component + let make = (~children) => { + let scrollDir = Hooks.useScrollDirection() + +
"group nav-appear" + | Down(_) => "group nav-disappear" + }}> + children +
+ } +} + type pageComponent = React.component<{.}> type pageProps = {.} @@ -55,99 +70,112 @@ let make = (props: props): React.element => { | {base: [], pagepath: []} => content // docs routes | {base: ["docs", "manual"], pagepath} => - // check if it's an api route - switch pagepath[0] { - | Some("api") => - switch url->Url.getVersionString { - | ("v11.0.0" | "v12.0.0") as version => - switch (Array.length(pagepath), pagepath[1]) { - | (1, _) => content + + // check if it's an api route + {switch pagepath[0] { + | Some("api") => + switch url->Url.getVersionString { + | ("v11.0.0" | "v12.0.0") as version => + switch (Array.length(pagepath), pagepath[1]) { + | (1, _) => content + | _ => content + } + | "v8.0.0" => + switch (Array.length(pagepath), pagepath[1]) { + | (1, _) => content + | (2, Some("js")) => content + | (2, Some("belt")) => content + | (_, Some("js")) => content + | (_, Some("belt")) => content + | (_, Some("dom")) => content + | _ => React.null + } + | "v9.0.0" => + switch (Array.length(pagepath), pagepath[1]) { + | (1, _) => content + | (2, Some("js")) => content + | (2, Some("belt")) => content + | (_, Some("js")) => content + | (_, Some("belt")) => content + | (_, Some("dom")) => content + | _ => React.null + } + | "v10.0.0" => + switch (Array.length(pagepath), pagepath[1]) { + | (1, _) => content + | (2, Some("js")) => content + | (2, Some("belt")) => content + | (_, Some("js")) => content + | (_, Some("belt")) => content + | (_, Some("dom")) => content + | _ => React.null + } | _ => content } - | "v8.0.0" => - switch (Array.length(pagepath), pagepath[1]) { - | (1, _) => content - | (2, Some("js")) => content - | (2, Some("belt")) => content - | (_, Some("js")) => content - | (_, Some("belt")) => content - | (_, Some("dom")) => content - | _ => React.null - } - | "v9.0.0" => - switch (Array.length(pagepath), pagepath[1]) { - | (1, _) => content - | (2, Some("js")) => content - | (2, Some("belt")) => content - | (_, Some("js")) => content - | (_, Some("belt")) => content - | (_, Some("dom")) => content + | _ => + switch url->Url.getVersionString { + | "v8.0.0" => + frontmatter}> + content + + | "v9.0.0" => + frontmatter}> + content + + | "v10.0.0" => + frontmatter}> + content + + | "v11.0.0" => + frontmatter}> + content + + | "v12.0.0" => + frontmatter}> + content + | _ => React.null } - | "v10.0.0" => - switch (Array.length(pagepath), pagepath[1]) { - | (1, _) => content - | (2, Some("js")) => content - | (2, Some("belt")) => content - | (_, Some("js")) => content - | (_, Some("belt")) => content - | (_, Some("dom")) => content - | _ => React.null - } - | _ => content - } - | _ => - switch url->Url.getVersionString { - | "v8.0.0" => - frontmatter}> - content - - | "v9.0.0" => - frontmatter}> - content - - | "v10.0.0" => - frontmatter}> + }} + + + | {base: ["docs", "react"], version} => + + {switch version { + | Latest => + frontmatter}> content - - | "v11.0.0" => - frontmatter}> + + | Version("v0.10.0") => + frontmatter}> content - - | "v12.0.0" => - frontmatter}> + + | Version("v0.11.0") => + frontmatter}> content - + | _ => React.null - } - } - - | {base: ["docs", "react"], version} => - switch version { - | Latest => - frontmatter}> - content - - | Version("v0.10.0") => - frontmatter}> content - | Version("v0.11.0") => - frontmatter}> content - | _ => React.null - } + }} + // common routes | {base} => switch List.fromArray(base) { | list{"community", ..._rest} => - frontmatter}> content + + frontmatter}> content + | list{"try"} => content - | list{"blog"} => content // Blog implements its own layout as well - | list{"syntax-lookup"} => content - | list{"packages"} => content - | list{"blog", ..._rest} => // Here, the layout will be handled by the Blog_Article component - // to keep the frontmatter parsing etc in one place - content + | list{"blog"} => content // Blog implements its own layout as well + | list{"syntax-lookup"} => content + | list{"packages"} => content + | list{"blog", ..._rest} => + + // Here, the layout will be handled by the Blog_Article component + // to keep the frontmatter parsing etc in one place + content + | _ => let fm = component->frontmatter->DocFrontmatter.decode let title = switch url { diff --git a/src/common/Hooks.res b/src/common/Hooks.res index e20fda83b..319c12b0b 100644 --- a/src/common/Hooks.res +++ b/src/common/Hooks.res @@ -38,31 +38,50 @@ let useScrollDirection = (~topMargin=80, ~threshold=20) => { })) React.useEffect(() => { - let onScroll = _e => { + let onScroll = e => { + let eventType = (e["type"] :> string) + setScrollDir(prev => { let scrollY = Webapi.Window.scrollY let enterTopMargin = scrollY <= topMargin - let action = switch prev { - | Up(_) if enterTopMargin => Skip - | Down(_) if enterTopMargin => EnterTop - | Up({scrollY: prevScrollY}) if prevScrollY < scrollY => UpToDown - | Up({scrollY: prevScrollY}) if prevScrollY - threshold >= scrollY => KeepUp - | Down({scrollY: prevScrollY}) if scrollY < prevScrollY => DownToUp - | Down({scrollY: prevScrollY}) if scrollY - threshold >= prevScrollY => KeepDown - | _ => Skip - } + if eventType === "reset-scroll-direction" { + Up({scrollY: scrollY}) + } else { + let action = switch prev { + | Up(_) if enterTopMargin => Skip + | Down(_) if enterTopMargin => EnterTop + | Up({scrollY: prevScrollY}) if prevScrollY < scrollY => UpToDown + | Up({scrollY: prevScrollY}) if prevScrollY - threshold >= scrollY => KeepUp + | Down({scrollY: prevScrollY}) if scrollY < prevScrollY => DownToUp + | Down({scrollY: prevScrollY}) if scrollY - threshold >= prevScrollY => KeepDown + | _ => Skip + } - switch action { - | Skip => prev - | EnterTop | DownToUp | KeepUp => Up({scrollY: scrollY}) - | UpToDown | KeepDown => Down({scrollY: scrollY}) + switch action { + | Skip => prev + | EnterTop | DownToUp | KeepUp => Up({scrollY: scrollY}) + | UpToDown | KeepDown => Down({scrollY: scrollY}) + } } }) } Webapi.Window.addEventListener("scroll", onScroll) - Some(() => Webapi.Window.removeEventListener("scroll", onScroll)) + Webapi.Window.addEventListener("reset-scroll-direction", onScroll) + Some( + () => { + Webapi.Window.removeEventListener("scroll", onScroll) + Webapi.Window.removeEventListener("reset-scroll-direction", onScroll) + }, + ) }, [topMargin, threshold]) scrollDir } + +let useResetScrollDirection = () => { + React.useCallback(() => { + // We really need better handling for plain DOM... + %raw(`window.dispatchEvent(new Event("reset-scroll-direction"))`) + }, []) +} diff --git a/src/components/Navigation.res b/src/components/Navigation.res index 48bfb3863..2fd3356f7 100644 --- a/src/components/Navigation.res +++ b/src/components/Navigation.res @@ -88,7 +88,7 @@ let make = (~fixed=true, ~isOverlayOpen: bool, ~setOverlayOpen: (bool => bool) =