diff options
Diffstat (limited to 'docs/src/app/layout.gleam')
-rw-r--r-- | docs/src/app/layout.gleam | 222 |
1 files changed, 180 insertions, 42 deletions
diff --git a/docs/src/app/layout.gleam b/docs/src/app/layout.gleam index 9f3b294..5ec9222 100644 --- a/docs/src/app/layout.gleam +++ b/docs/src/app/layout.gleam @@ -1,19 +1,106 @@ // IMPORTS --------------------------------------------------------------------- +import app/ui/hooks +import app/ui/radix +import app/ui/markdown import gleam/list +import gleam/string import lustre/attribute import lustre/element.{Element} import lustre/element/html +import lustre/event -pub fn docs(md: String) -> Element(msg) { - let #(content, summary) = parse_markdown(md) +pub fn docs_page(md: String) -> Element(msg) { + let #(content, summary) = markdown.parse(md) html.body( - [attribute.class("bg-gray-50 prose max-w-none")], + [attribute.class("prose prose-lustre max-w-none")], [ html.div( [attribute.class("max-w-[96rem] mx-auto grid grid-cols-8")], - [docs_left(), docs_content(content), docs_right(summary)], + [docs_top(), docs_left(), docs_content(content), docs_right(summary)], + ), + ], + ) +} + +pub fn docs_section(md: String) -> Element(msg) { + let #(content, summary) = markdown.parse(md) + + html.div( + [attribute.class("prose prose-lustre max-w-none")], + [ + html.div( + [attribute.class("max-w-[96rem] mx-auto grid grid-cols-8")], + [docs_top(), docs_left(), docs_content(content), docs_right(summary)], + ), + ], + ) +} + +fn docs_top() -> Element(msg) { + html.header( + [attribute.class("sticky top-0 z-10 col-span-8 lg:hidden bg-white")], + [docs_top_toggle()], + ) +} + +fn docs_top_toggle() -> Element(msg) { + use open, set_open, _ <- hooks.use_state(False) + + case open { + True -> docs_top_open(set_open(False)) + False -> docs_top_closed(set_open(True)) + } +} + +fn docs_top_open(close: msg) -> Element(msg) { + html.div( + [attribute.class("relative")], + [ + html.div( + [attribute.class("flex justify-between items-center px-4 py-2")], + [ + html.h2( + [attribute.class("text-indigo-600 my-0")], + [element.text("Lustre.")], + ), + html.button( + [ + event.on_click(close), + attribute.class("hover:bg-gray-200 rounded p-2"), + ], + [radix.cross([attribute.class("w-4 h-4")])], + ), + ], + ), + html.nav( + [ + attribute.class( + "absolute top-0 w-full rounded-b-2xl px-4 mt-12 bg-white shadow", + ), + ], + docs_left_links(), + ), + ], + ) +} + +fn docs_top_closed(open: msg) -> Element(msg) { + html.div( + [ + attribute.class( + "flex justify-between items-center px-4 py-2 border-b shadow", + ), + ], + [ + html.h2( + [attribute.class("text-indigo-600 my-0")], + [element.text("Lustre.")], + ), + html.button( + [event.on_click(open), attribute.class("hover:bg-gray-100 rounded p-2")], + [radix.hamburger([attribute.class("w-4 h-4")])], ), ], ) @@ -23,7 +110,7 @@ fn docs_left() -> Element(msg) { html.aside( [ attribute.style([#("align-self", "start")]), - attribute.class("sticky top-0 border-r hidden px-4 h-screen"), + attribute.class("relative sticky top-0 hidden px-4 pb-10 h-screen"), attribute.class("lg:block lg:col-span-2"), attribute.class("xl:col-span-2"), ], @@ -31,46 +118,86 @@ fn docs_left() -> Element(msg) { html.div( [ attribute.class( - "absolute right-0 inset-y-0 w-[50vw] bg-gray-100 -z-10", + "absolute right-0 inset-y-0 w-[50vw] bg-gradient-to-b from-white to-gray-100 -z-10", ), ], [], ), - html.h2([attribute.class("text-indigo-600")], [element.text("Lustre.")]), - docs_left_section( - "Docs", - [ - #("Quickstart", "/docs/quickstart"), - #("Managing state", "/docs/managing-state"), - #("Side effects", "/docs/side-effects"), - #("Components", "/docs/components"), - #("Server-side rendering", "/docs/server-side-rendering"), - ], - ), - docs_left_section( - "Reference", - [ - #("lustre", "/api/lustre"), - #("lustre/attribute", "/api/lustre/attribute"), - #("lustre/effect", "/api/lustre/effect"), - #("lustre/element", "/api/lustre/element"), - #("lustre/element/html", "/api/lustre/element/html"), - #("lustre/element/svg", "/api/lustre/element/svg"), - #("lustre/event", "/api/lustre/event"), - ], - ), - docs_left_section( - "External", + html.div( + [attribute.class("flex flex-col h-full overflow-y-scroll")], [ - #("GitHub", "https://github.com/hayleigh-dot-dev/gleam-lustre"), - #("Discord", "https://discord.gg/Fm8Pwmy"), - #("Buy me a coffee?", "https://github.com/sponsors/hayleigh-dot-dev"), + html.h2( + [attribute.class("mb-0")], + [ + html.a( + [ + attribute.href("/"), + attribute.class("text-indigo-600 no-underline"), + ], + [element.text("Lustre")], + ), + ], + ), + html.p( + [attribute.class("text-gray-400 font-bold")], + [element.text("Web apps from space.")], + ), + ..docs_left_links() ], ), ], ) } +fn docs_left_links() -> List(Element(msg)) { + let link = string.append(base_url(), _) + + [ + docs_left_section( + "Docs", + [ + #("Quickstart", link("docs/quickstart")), + #("Managing state", link("docs/managing-state")), + #("Side effects", link("docs/side-effects")), + #("Components", link("docs/components")), + #("Server-side rendering", link("docs/server-side-rendering")), + ], + ), + docs_left_section( + "Guides", + [ + #("Using with Mist", link("guides/mist")), + #("Using with Wisp", link("guides/wisp")), + ], + ), + docs_left_section( + "Reference", + [ + #("lustre", link("api/lustre")), + #("lustre/attribute", link("api/lustre/attribute")), + #("lustre/effect", link("api/lustre/effect")), + #("lustre/element", link("api/lustre/element")), + #("lustre/element/html", link("api/lustre/element/html")), + #("lustre/element/svg", link("api/lustre/element/svg")), + #("lustre/event", link("api/lustre/event")), + ], + ), + docs_left_section( + "External", + [ + #("GitHub", "https://github.com/hayleigh-dot-dev/gleam-lustre"), + #("Discord", "https://discord.gg/Fm8Pwmy"), + #("Buy me a coffee?", "https://github.com/sponsors/hayleigh-dot-dev"), + ], + ), + ] +} + +@external(javascript, "../app.ffi.mjs", "base") +fn base_url() -> String { + "/" +} + fn docs_left_section( title: String, pages: List(#(String, String)), @@ -78,12 +205,20 @@ fn docs_left_section( html.nav( [], [ - html.h2([], [element.text(title)]), + html.h2([attribute.class("my-0 lg:mt-8 lg:mb-4")], [element.text(title)]), html.ul( [attribute.class("ml-2")], { use #(name, url) <- list.map(pages) - html.li([], [html.a([attribute.href(url)], [element.text(name)])]) + html.li( + [], + [ + html.a( + [attribute.href(url), attribute.class("font-serif")], + [element.text(name)], + ), + ], + ) }, ), ], @@ -105,19 +240,22 @@ fn docs_right(summary: List(Element(msg))) -> Element(msg) { html.aside( [ attribute.style([#("align-self", "start")]), - attribute.class("sticky top-0 border-l hidden p-4 py-10 h-screen"), + attribute.class("sticky relative top-0 hidden p-4 py-10 h-screen"), attribute.class("xl:block xl:col-span-1"), ], [ html.div( + [ + attribute.class( + "absolute left-0 inset-y-0 w-[50vw] bg-gradient-to-b from-white to-gray-100 -z-10", + ), + ], + [], + ), + html.div( [attribute.class("flex flex-col h-full overflow-y-scroll")], summary, ), ], ) } - -// EXTERNALS ------------------------------------------------------------------- - -@external(javascript, "../app.ffi.mjs", "parse_markdown") -fn parse_markdown(md: String) -> #(List(Element(msg)), List(Element(msg))) |