feat: Updates sidebar to use the drawer classes from daisyui, currently doesn't open automatically on large screens like I want.

This commit is contained in:
2026-01-08 12:40:05 -05:00
parent 79b7892d9a
commit 9356ccb1c9
12 changed files with 578 additions and 147 deletions

View File

@@ -22,10 +22,18 @@ struct ProjectView: HTML, Sendable {
}
var body: some HTML {
div {
div(.class("flex flex-row")) {
Sidebar(active: activeTab, projectID: projectID)
main(.class("flex flex-col h-screen w-full px-6 py-10")) {
div(.class("h-screen w-full")) {
div(.class("drawer lg:drawer-open")) {
input(.id("my-drawer-1"), .type(.checkbox), .class("drawer-toggle"))
div(.class("drawer-content p-4")) {
label(
.for("my-drawer-1"),
.class("btn btn-square btn-ghost drawer-button size-7")
) {
SVG(.sidebarToggle)
}
switch self.activeTab {
case .project:
if let project = try await database.projects.get(projectID) {
@@ -56,6 +64,12 @@ struct ProjectView: HTML, Sendable {
}
}
try await Sidebar(
active: activeTab,
projectID: projectID,
completedSteps: database.projects.getCompletedSteps(projectID)
)
}
}
}
@@ -66,99 +80,164 @@ struct Sidebar: HTML {
let active: SiteRoute.View.ProjectRoute.DetailRoute.Tab
let projectID: Project.ID
let completedSteps: Project.CompletedSteps
var body: some HTML {
aside(
.class(
"""
h-screen sticky top-0 max-w-[280px] flex-none
border-r-2 border-gray-200
shadow-lg
"""
)
) {
div(.class("flex")) {
// TODO: Move somewhere outside of the sidebar.
button(
.class("btn btn-secondary btn-block"),
.hx.get(route: .project(.index)),
.hx.target("body"),
.hx.pushURL(true),
.hx.swap(.outerHTML),
) {
"< All Projects"
div(.class("drawer-side is-drawer-close:overflow-visible")) {
label(
.for("my-drawer-1"), .init(name: "aria-label", value: "close sidebar"),
.class("drawer-overlay")
) {}
div(
.class(
"""
flex min-h-full flex-col items-start bg-base-200
is-drawer-close:min-w-[80px] is-drawer-open:min-w-[340px]
"""
)
) {
ul(.class("w-full")) {
li(.class("w-full")) {
div(
.class("w-full is-drawer-close:tooltip is-drawer-close:tooltip-right"),
.data("tip", value: "All Projects")
) {
a(
.class(
"""
flex btn btn-secondary btn-square btn-block
is-drawer-close:items-center
"""
),
.hx.get(route: .project(.index)),
.hx.target("body"),
.hx.pushURL(true),
.hx.swap(.outerHTML),
) {
div(.class("flex is-drawer-open:space-x-4")) {
span { "<" }
span(.class("is-drawer-close:hidden")) { "All Projects" }
}
}
}
}
// FIX: Move to user profile / settings page.
li(.class("w-full is-drawer-close:hidden")) {
div(.class("flex justify-between p-4")) {
Label("Theme")
input(.type(.checkbox), .class("toggle theme-controller"), .value("light"))
}
}
li(.class("w-full")) {
row(
title: "Project",
icon: .mapPin,
route: .project(.detail(projectID, .index(tab: .project))),
isComplete: true
)
.attributes(.class("btn-active"), when: active == .project)
}
li(.class("w-full")) {
row(
title: "Rooms",
icon: .doorClosed,
route: .project(.detail(projectID, .rooms(.index))),
isComplete: completedSteps.rooms
)
.attributes(.class("btn-active"), when: active == .rooms)
}
li(.class("w-full")) {
row(
title: "Equivalent Lengths",
icon: .rulerDimensionLine,
route: .project(.detail(projectID, .equivalentLength(.index))),
isComplete: completedSteps.equivalentLength
)
.attributes(.class("btn-active"), when: active == .equivalentLength)
}
li(.class("w-full")) {
row(
title: "Friction Rate",
icon: .squareFunction,
route: .project(.detail(projectID, .frictionRate(.index))),
isComplete: completedSteps.frictionRate
)
.attributes(.class("btn-active"), when: active == .frictionRate)
}
li(.class("w-full")) {
row(
title: "Duct Sizes", icon: .wind, href: "#", isComplete: false, hideIsComplete: true
)
.attributes(.class("btn-active"), when: active == .ductSizing)
}
}
}
Row {
Label("Theme")
input(.type(.checkbox), .class("toggle theme-controller"), .value("light"))
}
.attributes(.class("p-4"))
row(
title: "Project",
icon: .mapPin,
route: .project(.detail(projectID, .index(tab: .project)))
)
.attributes(.data("active", value: active == .project ? "true" : "false"))
row(
title: "Rooms",
icon: .doorClosed,
route: .project(.detail(projectID, .rooms(.index)))
)
.attributes(.data("active", value: active == .rooms ? "true" : "false"))
row(
title: "Equivalent Lengths",
icon: .rulerDimensionLine,
route: .project(.detail(projectID, .equivalentLength(.index)))
)
.attributes(.data("active", value: active == .equivalentLength ? "true" : "false"))
row(
title: "Friction Rate",
icon: .squareFunction,
route: .project(.detail(projectID, .frictionRate(.index)))
)
.attributes(.data("active", value: active == .frictionRate ? "true" : "false"))
row(title: "Duct Sizes", icon: .wind, href: "#")
.attributes(.data("active", value: active == .ductSizing ? "true" : "false"))
}
}
// TODO: Use SiteRoute.View routes as href.
private func row(
title: String,
icon: Icon.Key,
href: String
) -> some HTML<HTMLTag.a> {
a(
icon: SVG.Key,
href: String,
isComplete: Bool,
hideIsComplete: Bool = false
) -> some HTML<HTMLTag.div> {
div(
.class(
"""
flex w-full items-center gap-4
hover:bg-gray-300 hover:text-gray-800
data-[active=true]:bg-gray-300 data-[active=true]:text-gray-800
px-4 py-2
"""
"w-full is-drawer-close:tooltip is-drawer-close:tooltip-right"
),
.href(href)
.data("tip", value: title)
) {
Icon(icon)
span(.class("text-xl")) {
title
a(
.class(
"flex btn btn-soft btn-square btn-block is-drawer-open:justify-between is-drawer-close:items-center"
),
.href(href)
) {
div(.class("flex is-drawer-open:space-x-4")) {
SVG(icon)
span(.class("text-xl is-drawer-close:hidden")) {
title
}
}
if !hideIsComplete {
div(.class("is-drawer-close:hidden")) {
if isComplete {
SVG(.badgeCheck)
} else {
SVG(.ban)
}
}
.attributes(.class("text-green-400"), when: isComplete)
.attributes(.class("text-error"), when: !isComplete)
}
}
.attributes(.class("is-drawer-close:text-green-400"), when: isComplete)
.attributes(.class("is-drawer-close:text-error"), when: !isComplete && !hideIsComplete)
}
}
private func row(
title: String,
icon: Icon.Key,
route: SiteRoute.View
) -> some HTML<HTMLTag.a> {
row(title: title, icon: icon, href: SiteRoute.View.router.path(for: route))
icon: SVG.Key,
route: SiteRoute.View,
isComplete: Bool,
hideIsComplete: Bool = false
) -> some HTML<HTMLTag.div> {
row(
title: title, icon: icon, href: SiteRoute.View.router.path(for: route),
isComplete: isComplete, hideIsComplete: hideIsComplete
)
}
}

View File

@@ -0,0 +1,51 @@
import Elementary
struct TestPage: HTML, Sendable {
var body: some HTML {
HTMLRaw(
"""
<div class="drawer lg:drawer-open">
<input id="my-drawer-4" type="checkbox" class="drawer-toggle" checked/>
<div class="drawer-content">
<!-- Navbar -->
<nav class="navbar w-full bg-base-300">
<label for="my-drawer-4" aria-label="open sidebar" class="btn btn-square btn-ghost">
<!-- Sidebar toggle icon -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor" class="my-1.5 inline-block size-4"><path d="M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z"></path><path d="M9 4v16"></path><path d="M14 10l2 2l-2 2"></path></svg>
</label>
<div class="px-4">Navbar Title</div>
</nav>
<!-- Page content here -->
<div class="p-4">Page Content</div>
</div>
<div class="drawer-side is-drawer-close:overflow-visible">
<label for="my-drawer-4" aria-label="close sidebar" class="drawer-overlay"></label>
<div class="flex min-h-full flex-col items-start bg-base-200 is-drawer-close:w-14 is-drawer-open:w-64">
<!-- Sidebar content here -->
<ul class="menu w-full grow">
<!-- List item -->
<li>
<button class="is-drawer-close:tooltip is-drawer-close:tooltip-right" data-tip="Homepage">
<!-- Home icon -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor" class="my-1.5 inline-block size-4"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"></path><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path></svg>
<span class="is-drawer-close:hidden">Homepage</span>
</button>
</li>
<!-- List item -->
<li>
<button class="is-drawer-close:tooltip is-drawer-close:tooltip-right" data-tip="Settings">
<!-- Settings icon -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor" class="my-1.5 inline-block size-4"><path d="M20 7h-9"></path><path d="M14 17H5"></path><circle cx="17" cy="17" r="3"></circle><circle cx="7" cy="7" r="3"></circle></svg>
<span class="is-drawer-close:hidden">Settings</span>
</button>
</li>
</ul>
</div>
</div>
</div>
"""
)
}
}