From f07dfeb2ebf3018bb4070113f41e9d693f8ac89a Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 13 Jul 2024 20:28:53 +0100 Subject: [PATCH] feature: Mobile support --- .../kotlin/website/pages/docs/DocsPage.kt | 71 +++++++++++++------ .../website/pages/docs/components/Dropdown.kt | 2 +- .../website/pages/docs/components/Search.kt | 6 +- .../main/resources/static/css/docs_style.css | 17 ++++- .../main/resources/static/tailwind.config.js | 4 -- scripts/base/src/jsMain/kotlin/Script.kt | 40 +++++++++-- 6 files changed, 102 insertions(+), 38 deletions(-) diff --git a/backend/src/main/kotlin/website/pages/docs/DocsPage.kt b/backend/src/main/kotlin/website/pages/docs/DocsPage.kt index 5fee266..50b627e 100644 --- a/backend/src/main/kotlin/website/pages/docs/DocsPage.kt +++ b/backend/src/main/kotlin/website/pages/docs/DocsPage.kt @@ -320,8 +320,8 @@ private fun FlowContent.content(page: ProjectPage) { div { classes = setOf( - "absolute -z-10 w-[1700px] h-96 left-0 right-0 top-0 mx-auto", - "bg-dots bg-cover opacity-85 pointer-events-none", + "absolute -z-10 w-3/4 h-96 left-0 right-0 top-0 mx-auto", + "dots bg-center opacity-85 pointer-events-none", ) } @@ -402,29 +402,58 @@ private fun UL.entries(entry: Page.Summary, initial: Boolean = false) { } private fun FlowContent.sideBar(project: ProjectData, version: Version, currentPage: ProjectPage) { + + div { + + classes = setOf("absolute opacity-100 xl:opacity-0 top-0 ml-6 mt-6 text-2xl") + i { + id = "show-sidebar-button" + classes = setOf("fa-solid fa-bars cursor-pointer") + } + } + div { + id = "side-bar" classes = setOf( - "fixed", - "opacity-0 xl:opacity-100", - "xl:w-60 2xl:w-72", - "h-screen", - "flex flex-col", - "gap-6", + "fixed z-10", + "bg-docs-bg", + "w-screen xl:w-60 2xl:w-72", + "h-svh h-screen", + "hidden xl:flex flex-col", + "gap-4", "px-4", - "justify-items-center", + "justify-center", ) + div { + classes = setOf( + "absolute top-0 right-0 mr-8 mt-6 text-2xl cursor-pointer", + "xl:opacity-0", + ) + + i { + id = "hide-sidebar-button" + classes = setOf("fa-solid fa-xmark") + } + } + // Logo area div { - classes = setOf("grid", "grid-cols-1", "gap-4", "w-full", "justify-items-center", "h-64") + classes = setOf( + "grid", + "grid-cols-1", + "gap-4", + "w-full", + "justify-items-center", + ) div { classes = setOf("flex items-center h-36 pt-4") a { href = "/" - img(src = project.icon, classes = "col-span-1 w-28") + img(src = project.icon, classes = "col-span-1 w-28 xl:w-24 2xl:w-28") } } @@ -435,21 +464,17 @@ private fun FlowContent.sideBar(project: ProjectData, version: Version, currentP +project.name } } + } - div { - classes = setOf("col-span-1") - - dropDown( - options = project.versions.values.map { ver -> - DropdownOption( - text = ver.reference, - link = "/docs/${ver.reference}/${project.id}", - selected = ver.reference == version.reference, - ) - } + dropDown( + options = project.versions.values.map { ver -> + DropdownOption( + text = ver.reference, + link = "/docs/${ver.reference}/${project.id}", + selected = ver.reference == version.reference, ) } - } + ) div { id = "searchbar-button" diff --git a/backend/src/main/kotlin/website/pages/docs/components/Dropdown.kt b/backend/src/main/kotlin/website/pages/docs/components/Dropdown.kt index a490005..c25238d 100644 --- a/backend/src/main/kotlin/website/pages/docs/components/Dropdown.kt +++ b/backend/src/main/kotlin/website/pages/docs/components/Dropdown.kt @@ -14,7 +14,7 @@ public data class DropdownOption( public fun FlowContent.dropDown(options: List) { div { - classes = setOf("mx-auto", "max-w-sm", "flex", "select-none") + classes = setOf("flex justify-center", "select-none") // Left side of the chooser div { diff --git a/backend/src/main/kotlin/website/pages/docs/components/Search.kt b/backend/src/main/kotlin/website/pages/docs/components/Search.kt index c35aad8..ace412f 100644 --- a/backend/src/main/kotlin/website/pages/docs/components/Search.kt +++ b/backend/src/main/kotlin/website/pages/docs/components/Search.kt @@ -74,7 +74,7 @@ public fun FlowContent.searchArea(project: String, version: String) { "fixed", "w-screen h-screen", "docs-search", - "p-72", + "flex justify-center items-center", ) div { @@ -82,10 +82,8 @@ public fun FlowContent.searchArea(project: String, version: String) { id = "search-area-container" classes = setOf( - "w-2/5 min-h-72", + "w-5/6 xl:w-4/6 2xl:w-3/5 h-3/5", "bg-docs-bg", - "mx-auto", - "my-0", "rounded-lg", "py-4 px-12", "flex flex-col gap-6", diff --git a/backend/src/main/resources/static/css/docs_style.css b/backend/src/main/resources/static/css/docs_style.css index b23a6c9..5947ffa 100644 --- a/backend/src/main/resources/static/css/docs_style.css +++ b/backend/src/main/resources/static/css/docs_style.css @@ -35,10 +35,20 @@ body { margin-left: 20px; } -.opened-search { +.search-locked { overflow: hidden !important; } +.menu-locked { + overflow: hidden !important; +} + +@media (min-width: 1280px) { + .menu-locked { + overflow-y: auto !important; + } +} + .docs-search { z-index: 20; background: rgba(29, 32, 35, 0.9); @@ -86,3 +96,8 @@ body { [data-tooltip]:hover::before, [data-tooltip]:hover::after { opacity: 1; } + +.dots { + background-image: url("/static/images/dots.png"), linear-gradient(0deg, rgba(255,255,255,0) 70%, rgba(20,20,23,1) 100%), linear-gradient(180deg, rgba(255,255,255,0) 70%, rgba(20,20,23,1) 100%); + background-size: cover; +} diff --git a/backend/src/main/resources/static/tailwind.config.js b/backend/src/main/resources/static/tailwind.config.js index 8002f92..e735bfe 100644 --- a/backend/src/main/resources/static/tailwind.config.js +++ b/backend/src/main/resources/static/tailwind.config.js @@ -10,10 +10,6 @@ tailwind.config = { 'docs-bg': '#141417', 'search-bg': '#202023', }, - backgroundImage: { - 'blur-effect': `url('/static/images/blur_effect.png')`, - 'dots': `url('/static/images/dots.png')`, - } } } } diff --git a/scripts/base/src/jsMain/kotlin/Script.kt b/scripts/base/src/jsMain/kotlin/Script.kt index e9565ed..80c7ed6 100644 --- a/scripts/base/src/jsMain/kotlin/Script.kt +++ b/scripts/base/src/jsMain/kotlin/Script.kt @@ -5,7 +5,6 @@ import kotlinx.dom.hasClass import kotlinx.dom.removeClass import org.w3c.dom.Element import org.w3c.dom.Node -import org.w3c.dom.events.Event import org.w3c.dom.events.EventTarget private const val hiddenClass = "opacity-0" @@ -28,7 +27,7 @@ public fun main() { buttonId = "searchbar-button", elementId = "search-area", ) { - document.body?.addClass("opened-search") + document.body?.addClass("search-locked") } // Hide the search area hideListener( @@ -36,8 +35,16 @@ public fun main() { elementId = "search-area", ignoreElementId = "search-area-container", ) { - document.body?.removeClass("opened-search") + document.body?.removeClass("search-locked") } + + // Show sidebar + showListener( + buttonId = "side-bar-button", + elementId = "side-bar", + ) + + sideBarListener() copyCodeListener() } @@ -61,13 +68,36 @@ private fun copyToClipboard(toastElement: Element?, target: EventTarget?) { } } +private fun sideBarListener() { + val showId = "show-sidebar-button" + val hideId = "hide-sidebar-button" + val sideBarId = "side-bar" + + document.addEventListener("click", { event -> + val target = event.target as? Element ?: return@addEventListener + if (target.id != showId && target.id != hideId) return@addEventListener + val sideBarElement = document.getElementById(sideBarId) ?: return@addEventListener + + if (target.id == showId) { + sideBarElement.removeClass("hidden") + sideBarElement.addClass("flex") + document.body?.addClass("menu-locked") + return@addEventListener + } + + sideBarElement.addClass("hidden") + sideBarElement.removeClass("flex") + document.body?.removeClass("menu-locked") + }) +} + private fun showListener( buttonId: String, elementId: String, extra: () -> Unit = {}, ) { - document.addEventListener("click", { event: Event -> + document.addEventListener("click", { event -> val buttonElement = document.getElementById(buttonId) ?: return@addEventListener if (!buttonElement.contains(event.target as Node)) return@addEventListener @@ -95,7 +125,7 @@ private fun hideListener( extra: () -> Unit = {}, ) { - document.addEventListener("click", { event: Event -> + document.addEventListener("click", { event -> val buttonElement = document.getElementById(buttonId) val ignoreElement = ignoreElementId?.let { document.getElementById(it) }