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:
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
51
Sources/ViewController/Views/TestPage.swift
Normal file
51
Sources/ViewController/Views/TestPage.swift
Normal 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>
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user