Skip to content

Commit 570248c

Browse files
committed
Bring back collapsible navbar on mobile layout
1 parent 3f96742 commit 570248c

File tree

4 files changed

+147
-96
lines changed

4 files changed

+147
-96
lines changed

src/common/App.res

Lines changed: 106 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@
3232
hljs.registerLanguage('diff', diff)
3333
`)
3434

35+
module EnableCollapsibleNavbar = {
36+
@react.component
37+
let make = (~children) => {
38+
let scrollDir = Hooks.useScrollDirection()
39+
40+
<div
41+
className={switch scrollDir {
42+
| Up(_) => "group nav-appear"
43+
| Down(_) => "group nav-disappear"
44+
}}>
45+
children
46+
</div>
47+
}
48+
}
49+
3550
type pageComponent = React.component<{.}>
3651
type pageProps = {.}
3752

@@ -55,99 +70,112 @@ let make = (props: props): React.element => {
5570
| {base: [], pagepath: []} => <LandingPageLayout> content </LandingPageLayout>
5671
// docs routes
5772
| {base: ["docs", "manual"], pagepath} =>
58-
// check if it's an api route
59-
switch pagepath[0] {
60-
| Some("api") =>
61-
switch url->Url.getVersionString {
62-
| ("v11.0.0" | "v12.0.0") as version =>
63-
switch (Array.length(pagepath), pagepath[1]) {
64-
| (1, _) => <ApiOverviewLayout.Docs version> content </ApiOverviewLayout.Docs>
73+
<EnableCollapsibleNavbar>
74+
// check if it's an api route
75+
{switch pagepath[0] {
76+
| Some("api") =>
77+
switch url->Url.getVersionString {
78+
| ("v11.0.0" | "v12.0.0") as version =>
79+
switch (Array.length(pagepath), pagepath[1]) {
80+
| (1, _) => <ApiOverviewLayout.Docs version> content </ApiOverviewLayout.Docs>
81+
| _ => content
82+
}
83+
| "v8.0.0" =>
84+
switch (Array.length(pagepath), pagepath[1]) {
85+
| (1, _) => <ApiOverviewLayout8_0_0.Docs> content </ApiOverviewLayout8_0_0.Docs>
86+
| (2, Some("js")) => <JsDocsLayout8_0_0.Prose> content </JsDocsLayout8_0_0.Prose>
87+
| (2, Some("belt")) => <BeltDocsLayout8_0_0.Prose> content </BeltDocsLayout8_0_0.Prose>
88+
| (_, Some("js")) => <JsDocsLayout8_0_0.Docs> content </JsDocsLayout8_0_0.Docs>
89+
| (_, Some("belt")) => <BeltDocsLayout8_0_0.Docs> content </BeltDocsLayout8_0_0.Docs>
90+
| (_, Some("dom")) => <DomDocsLayout8_0_0.Docs> content </DomDocsLayout8_0_0.Docs>
91+
| _ => React.null
92+
}
93+
| "v9.0.0" =>
94+
switch (Array.length(pagepath), pagepath[1]) {
95+
| (1, _) => <ApiOverviewLayout9_0_0.Docs> content </ApiOverviewLayout9_0_0.Docs>
96+
| (2, Some("js")) => <JsDocsLayout9_0_0.Prose> content </JsDocsLayout9_0_0.Prose>
97+
| (2, Some("belt")) => <BeltDocsLayout9_0_0.Prose> content </BeltDocsLayout9_0_0.Prose>
98+
| (_, Some("js")) => <JsDocsLayout9_0_0.Docs> content </JsDocsLayout9_0_0.Docs>
99+
| (_, Some("belt")) => <BeltDocsLayout9_0_0.Docs> content </BeltDocsLayout9_0_0.Docs>
100+
| (_, Some("dom")) => <DomDocsLayout9_0_0.Docs> content </DomDocsLayout9_0_0.Docs>
101+
| _ => React.null
102+
}
103+
| "v10.0.0" =>
104+
switch (Array.length(pagepath), pagepath[1]) {
105+
| (1, _) => <ApiOverviewLayout10_0_0.Docs> content </ApiOverviewLayout10_0_0.Docs>
106+
| (2, Some("js")) => <JsDocsLayout10_0_0.Prose> content </JsDocsLayout10_0_0.Prose>
107+
| (2, Some("belt")) => <BeltDocsLayout10_0_0.Prose> content </BeltDocsLayout10_0_0.Prose>
108+
| (_, Some("js")) => <JsDocsLayout10_0_0.Docs> content </JsDocsLayout10_0_0.Docs>
109+
| (_, Some("belt")) => <BeltDocsLayout10_0_0.Docs> content </BeltDocsLayout10_0_0.Docs>
110+
| (_, Some("dom")) => <DomDocsLayout10_0_0.Docs> content </DomDocsLayout10_0_0.Docs>
111+
| _ => React.null
112+
}
65113
| _ => content
66114
}
67-
| "v8.0.0" =>
68-
switch (Array.length(pagepath), pagepath[1]) {
69-
| (1, _) => <ApiOverviewLayout8_0_0.Docs> content </ApiOverviewLayout8_0_0.Docs>
70-
| (2, Some("js")) => <JsDocsLayout8_0_0.Prose> content </JsDocsLayout8_0_0.Prose>
71-
| (2, Some("belt")) => <BeltDocsLayout8_0_0.Prose> content </BeltDocsLayout8_0_0.Prose>
72-
| (_, Some("js")) => <JsDocsLayout8_0_0.Docs> content </JsDocsLayout8_0_0.Docs>
73-
| (_, Some("belt")) => <BeltDocsLayout8_0_0.Docs> content </BeltDocsLayout8_0_0.Docs>
74-
| (_, Some("dom")) => <DomDocsLayout8_0_0.Docs> content </DomDocsLayout8_0_0.Docs>
75-
| _ => React.null
76-
}
77-
| "v9.0.0" =>
78-
switch (Array.length(pagepath), pagepath[1]) {
79-
| (1, _) => <ApiOverviewLayout9_0_0.Docs> content </ApiOverviewLayout9_0_0.Docs>
80-
| (2, Some("js")) => <JsDocsLayout9_0_0.Prose> content </JsDocsLayout9_0_0.Prose>
81-
| (2, Some("belt")) => <BeltDocsLayout9_0_0.Prose> content </BeltDocsLayout9_0_0.Prose>
82-
| (_, Some("js")) => <JsDocsLayout9_0_0.Docs> content </JsDocsLayout9_0_0.Docs>
83-
| (_, Some("belt")) => <BeltDocsLayout9_0_0.Docs> content </BeltDocsLayout9_0_0.Docs>
84-
| (_, Some("dom")) => <DomDocsLayout9_0_0.Docs> content </DomDocsLayout9_0_0.Docs>
115+
| _ =>
116+
switch url->Url.getVersionString {
117+
| "v8.0.0" =>
118+
<ManualDocsLayout.V800 frontmatter={component->frontmatter}>
119+
content
120+
</ManualDocsLayout.V800>
121+
| "v9.0.0" =>
122+
<ManualDocsLayout.V900 frontmatter={component->frontmatter}>
123+
content
124+
</ManualDocsLayout.V900>
125+
| "v10.0.0" =>
126+
<ManualDocsLayout.V1000 frontmatter={component->frontmatter}>
127+
content
128+
</ManualDocsLayout.V1000>
129+
| "v11.0.0" =>
130+
<ManualDocsLayout.V1100 frontmatter={component->frontmatter}>
131+
content
132+
</ManualDocsLayout.V1100>
133+
| "v12.0.0" =>
134+
<ManualDocsLayout.V1200 frontmatter={component->frontmatter}>
135+
content
136+
</ManualDocsLayout.V1200>
85137
| _ => React.null
86138
}
87-
| "v10.0.0" =>
88-
switch (Array.length(pagepath), pagepath[1]) {
89-
| (1, _) => <ApiOverviewLayout10_0_0.Docs> content </ApiOverviewLayout10_0_0.Docs>
90-
| (2, Some("js")) => <JsDocsLayout10_0_0.Prose> content </JsDocsLayout10_0_0.Prose>
91-
| (2, Some("belt")) => <BeltDocsLayout10_0_0.Prose> content </BeltDocsLayout10_0_0.Prose>
92-
| (_, Some("js")) => <JsDocsLayout10_0_0.Docs> content </JsDocsLayout10_0_0.Docs>
93-
| (_, Some("belt")) => <BeltDocsLayout10_0_0.Docs> content </BeltDocsLayout10_0_0.Docs>
94-
| (_, Some("dom")) => <DomDocsLayout10_0_0.Docs> content </DomDocsLayout10_0_0.Docs>
95-
| _ => React.null
96-
}
97-
| _ => content
98-
}
99-
| _ =>
100-
switch url->Url.getVersionString {
101-
| "v8.0.0" =>
102-
<ManualDocsLayout.V800 frontmatter={component->frontmatter}>
103-
content
104-
</ManualDocsLayout.V800>
105-
| "v9.0.0" =>
106-
<ManualDocsLayout.V900 frontmatter={component->frontmatter}>
107-
content
108-
</ManualDocsLayout.V900>
109-
| "v10.0.0" =>
110-
<ManualDocsLayout.V1000 frontmatter={component->frontmatter}>
139+
}}
140+
</EnableCollapsibleNavbar>
141+
142+
| {base: ["docs", "react"], version} =>
143+
<EnableCollapsibleNavbar>
144+
{switch version {
145+
| Latest =>
146+
<ReactDocsLayout.Latest frontmatter={component->frontmatter}>
111147
content
112-
</ManualDocsLayout.V1000>
113-
| "v11.0.0" =>
114-
<ManualDocsLayout.V1100 frontmatter={component->frontmatter}>
148+
</ReactDocsLayout.Latest>
149+
| Version("v0.10.0") =>
150+
<ReactDocsLayout.V0100 frontmatter={component->frontmatter}>
115151
content
116-
</ManualDocsLayout.V1100>
117-
| "v12.0.0" =>
118-
<ManualDocsLayout.V1200 frontmatter={component->frontmatter}>
152+
</ReactDocsLayout.V0100>
153+
| Version("v0.11.0") =>
154+
<ReactDocsLayout.V0110 frontmatter={component->frontmatter}>
119155
content
120-
</ManualDocsLayout.V1200>
156+
</ReactDocsLayout.V0110>
121157
| _ => React.null
122-
}
123-
}
124-
125-
| {base: ["docs", "react"], version} =>
126-
switch version {
127-
| Latest =>
128-
<ReactDocsLayout.Latest frontmatter={component->frontmatter}>
129-
content
130-
</ReactDocsLayout.Latest>
131-
| Version("v0.10.0") =>
132-
<ReactDocsLayout.V0100 frontmatter={component->frontmatter}> content </ReactDocsLayout.V0100>
133-
| Version("v0.11.0") =>
134-
<ReactDocsLayout.V0110 frontmatter={component->frontmatter}> content </ReactDocsLayout.V0110>
135-
| _ => React.null
136-
}
158+
}}
159+
</EnableCollapsibleNavbar>
137160

138161
// common routes
139162
| {base} =>
140163
switch List.fromArray(base) {
141164
| list{"community", ..._rest} =>
142-
<CommunityLayout frontmatter={component->frontmatter}> content </CommunityLayout>
165+
<EnableCollapsibleNavbar>
166+
<CommunityLayout frontmatter={component->frontmatter}> content </CommunityLayout>
167+
</EnableCollapsibleNavbar>
143168

144169
| list{"try"} => content
145-
| list{"blog"} => content // Blog implements its own layout as well
146-
| list{"syntax-lookup"} => content
147-
| list{"packages"} => content
148-
| list{"blog", ..._rest} => // Here, the layout will be handled by the Blog_Article component
149-
// to keep the frontmatter parsing etc in one place
150-
content
170+
| list{"blog"} => <EnableCollapsibleNavbar> content </EnableCollapsibleNavbar> // Blog implements its own layout as well
171+
| list{"syntax-lookup"} => <EnableCollapsibleNavbar> content </EnableCollapsibleNavbar>
172+
| list{"packages"} => <EnableCollapsibleNavbar> content </EnableCollapsibleNavbar>
173+
| list{"blog", ..._rest} =>
174+
<EnableCollapsibleNavbar>
175+
// Here, the layout will be handled by the Blog_Article component
176+
// to keep the frontmatter parsing etc in one place
177+
content
178+
</EnableCollapsibleNavbar>
151179
| _ =>
152180
let fm = component->frontmatter->DocFrontmatter.decode
153181
let title = switch url {

src/common/Hooks.res

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,50 @@ let useScrollDirection = (~topMargin=80, ~threshold=20) => {
3838
}))
3939

4040
React.useEffect(() => {
41-
let onScroll = _e => {
41+
let onScroll = e => {
42+
let eventType = (e["type"] :> string)
43+
4244
setScrollDir(prev => {
4345
let scrollY = Webapi.Window.scrollY
4446
let enterTopMargin = scrollY <= topMargin
4547

46-
let action = switch prev {
47-
| Up(_) if enterTopMargin => Skip
48-
| Down(_) if enterTopMargin => EnterTop
49-
| Up({scrollY: prevScrollY}) if prevScrollY < scrollY => UpToDown
50-
| Up({scrollY: prevScrollY}) if prevScrollY - threshold >= scrollY => KeepUp
51-
| Down({scrollY: prevScrollY}) if scrollY < prevScrollY => DownToUp
52-
| Down({scrollY: prevScrollY}) if scrollY - threshold >= prevScrollY => KeepDown
53-
| _ => Skip
54-
}
48+
if eventType === "reset-scroll-direction" {
49+
Up({scrollY: scrollY})
50+
} else {
51+
let action = switch prev {
52+
| Up(_) if enterTopMargin => Skip
53+
| Down(_) if enterTopMargin => EnterTop
54+
| Up({scrollY: prevScrollY}) if prevScrollY < scrollY => UpToDown
55+
| Up({scrollY: prevScrollY}) if prevScrollY - threshold >= scrollY => KeepUp
56+
| Down({scrollY: prevScrollY}) if scrollY < prevScrollY => DownToUp
57+
| Down({scrollY: prevScrollY}) if scrollY - threshold >= prevScrollY => KeepDown
58+
| _ => Skip
59+
}
5560

56-
switch action {
57-
| Skip => prev
58-
| EnterTop | DownToUp | KeepUp => Up({scrollY: scrollY})
59-
| UpToDown | KeepDown => Down({scrollY: scrollY})
61+
switch action {
62+
| Skip => prev
63+
| EnterTop | DownToUp | KeepUp => Up({scrollY: scrollY})
64+
| UpToDown | KeepDown => Down({scrollY: scrollY})
65+
}
6066
}
6167
})
6268
}
6369
Webapi.Window.addEventListener("scroll", onScroll)
64-
Some(() => Webapi.Window.removeEventListener("scroll", onScroll))
70+
Webapi.Window.addEventListener("reset-scroll-direction", onScroll)
71+
Some(
72+
() => {
73+
Webapi.Window.removeEventListener("scroll", onScroll)
74+
Webapi.Window.removeEventListener("reset-scroll-direction", onScroll)
75+
},
76+
)
6577
}, [topMargin, threshold])
6678

6779
scrollDir
6880
}
81+
82+
let useResetScrollDirection = () => {
83+
React.useCallback(() => {
84+
// We really need better handling for plain DOM...
85+
%raw(`window.dispatchEvent(new Event("reset-scroll-direction"))`)
86+
}, [])
87+
}

src/components/Navigation.res

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ let make = (~fixed=true, ~isOverlayOpen: bool, ~setOverlayOpen: (bool => bool) =
8888
<header
8989
id="header"
9090
style={ReactDOMStyle.make(~minWidth, ())}
91-
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"}>
91+
className={fixedNav ++ " items-center z-50 w-full transition duration-300 ease-out group-[.nav-disappear]:-translate-y-16 group-[.nav-disappear]:pointer-events-none md:group-[.nav-disappear]:transform-none"}>
9292
<nav className="px-4 flex xs:justify-center bg-gray-90 shadow h-16 text-white-80 text-14">
9393
<div className="flex justify-between items-center h-full w-full max-w-1280">
9494
<div className="h-8 w-8 lg:h-10 lg:w-32">

src/layouts/SidebarLayout.res

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,12 @@ let make = (
234234

235235
let breadcrumbs = breadcrumbs->Option.mapOr(React.null, crumbs => <BreadCrumbs crumbs />)
236236

237+
let resetScrollDirection = Hooks.useResetScrollDirection()
237238
let (_isSidebarOpen, setSidebarOpen) = sidebarState
238-
let toggleSidebar = () => setSidebarOpen(prev => !prev)
239+
let toggleSidebar = () => {
240+
setSidebarOpen(prev => !prev)
241+
resetScrollDirection()
242+
}
239243

240244
React.useEffect(() => {
241245
open Next.Router.Events
@@ -313,7 +317,7 @@ let make = (
313317
<main className="px-4 w-full pt-20 md:ml-12 lg:mr-8 mb-32 md:max-w-576 lg:max-w-740">
314318
//width of the right content part
315319
<div
316-
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"}>
320+
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-[112px] md:group-[.nav-disappear]:transform-none"}>
317321
<MobileDrawerButton hidden=isNavOpen onClick={handleDrawerButtonClick} />
318322
<div
319323
className="truncate overflow-x-auto touch-scroll flex items-center space-x-4 md:justify-between mr-4 w-full">

0 commit comments

Comments
 (0)