diff --git a/Public/css/output.css b/Public/css/output.css
index 6f47cc5..2c4275c 100644
--- a/Public/css/output.css
+++ b/Public/css/output.css
@@ -10,11 +10,14 @@
--color-red-500: oklch(63.7% 0.237 25.331);
--color-red-600: oklch(57.7% 0.245 27.325);
--color-green-400: oklch(79.2% 0.209 151.711);
+ --color-blue-400: oklch(70.7% 0.165 254.624);
--color-indigo-600: oklch(51.1% 0.262 276.966);
--color-slate-300: oklch(86.9% 0.022 252.894);
--color-slate-900: oklch(20.8% 0.042 265.755);
--color-gray-200: oklch(92.8% 0.006 264.531);
+ --color-gray-300: oklch(87.2% 0.01 258.338);
--color-gray-400: oklch(70.7% 0.022 261.325);
+ --color-gray-900: oklch(21% 0.034 264.665);
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
@@ -6778,6 +6781,9 @@
.justify-end {
justify-content: flex-end;
}
+ .gap-1 {
+ gap: calc(var(--spacing) * 1);
+ }
.gap-2 {
gap: calc(var(--spacing) * 2);
}
@@ -7104,6 +7110,10 @@
border-bottom-style: var(--tw-border-style);
border-bottom-width: 1px;
}
+ .border-b-1 {
+ border-bottom-style: var(--tw-border-style);
+ border-bottom-width: 1px;
+ }
.badge-dash {
@layer daisyui.l1.l2 {
color: var(--badge-color);
@@ -7670,6 +7680,9 @@
}
}
}
+ .p-2 {
+ padding: calc(var(--spacing) * 2);
+ }
.p-4 {
padding: calc(var(--spacing) * 4);
}
@@ -8452,6 +8465,9 @@
.text-error {
color: var(--color-error);
}
+ .text-gray-200 {
+ color: var(--color-gray-200);
+ }
.text-gray-400 {
color: var(--color-gray-400);
}
@@ -9349,6 +9365,27 @@
border-color: var(--color-red-500);
}
}
+ .hover\:bg-gray-900 {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-gray-900);
+ }
+ }
+ }
+ .hover\:bg-neutral {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-neutral);
+ }
+ }
+ }
+ .hover\:bg-neutral-content {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-neutral-content);
+ }
+ }
+ }
.hover\:bg-red-600 {
&:hover {
@media (hover: hover) {
@@ -9356,6 +9393,13 @@
}
}
}
+ .hover\:text-black {
+ &:hover {
+ @media (hover: hover) {
+ color: var(--color-black);
+ }
+ }
+ }
.hover\:text-white {
&:hover {
@media (hover: hover) {
@@ -9379,6 +9423,31 @@
outline-color: var(--color-indigo-600);
}
}
+ .data-active\:bg-gray-900 {
+ &[data-active] {
+ background-color: var(--color-gray-900);
+ }
+ }
+ .data-active\:bg-neutral {
+ &[data-active] {
+ background-color: var(--color-neutral);
+ }
+ }
+ .data-active\:bg-neutral-content {
+ &[data-active] {
+ background-color: var(--color-neutral-content);
+ }
+ }
+ .data-active\:text-black {
+ &[data-active] {
+ color: var(--color-black);
+ }
+ }
+ .data-active\:text-white {
+ &[data-active] {
+ color: var(--color-white);
+ }
+ }
.md\:grid-cols-2 {
@media (width >= 48rem) {
grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -9457,9 +9526,52 @@
display: table-cell;
}
}
- .dark\:text-white {
- @media (prefers-color-scheme: dark) {
- color: var(--color-white);
+ .hover\:dark\:bg-gray-900 {
+ &:hover {
+ @media (hover: hover) {
+ @media (prefers-color-scheme: dark) {
+ background-color: var(--color-gray-900);
+ }
+ }
+ }
+ }
+ .hover\:dark\:bg-neutral {
+ &:hover {
+ @media (hover: hover) {
+ @media (prefers-color-scheme: dark) {
+ background-color: var(--color-neutral);
+ }
+ }
+ }
+ }
+ .hover\:dark\:text-white {
+ &:hover {
+ @media (hover: hover) {
+ @media (prefers-color-scheme: dark) {
+ color: var(--color-white);
+ }
+ }
+ }
+ }
+ .data-active\:dark\:bg-gray-900 {
+ &[data-active] {
+ @media (prefers-color-scheme: dark) {
+ background-color: var(--color-gray-900);
+ }
+ }
+ }
+ .data-active\:dark\:bg-neutral {
+ &[data-active] {
+ @media (prefers-color-scheme: dark) {
+ background-color: var(--color-neutral);
+ }
+ }
+ }
+ .data-active\:dark\:text-white {
+ &[data-active] {
+ @media (prefers-color-scheme: dark) {
+ color: var(--color-white);
+ }
}
}
.is-drawer-close\:tooltip {
@@ -9546,6 +9658,11 @@
}
}
}
+ .is-drawer-close\:mx-auto {
+ &:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
+ margin-inline: auto;
+ }
+ }
.is-drawer-close\:hidden {
&:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
display: none;
@@ -9561,16 +9678,41 @@
min-width: 80px;
}
}
+ .is-drawer-close\:grid-cols-1 {
+ &:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
+ grid-template-columns: repeat(1, minmax(0, 1fr));
+ }
+ }
.is-drawer-close\:items-center {
&:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
align-items: center;
}
}
+ .is-drawer-close\:justify-center {
+ &:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
+ justify-content: center;
+ }
+ }
+ .is-drawer-close\:space-y-2 {
+ &:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
+ :where(& > :not(:last-child)) {
+ --tw-space-y-reverse: 0;
+ margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));
+ margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)));
+ }
+ }
+ }
.is-drawer-close\:overflow-visible {
&:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
overflow: visible;
}
}
+ .is-drawer-close\:text-sm {
+ &:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
+ font-size: var(--text-sm);
+ line-height: var(--tw-leading, var(--text-sm--line-height));
+ }
+ }
.is-drawer-close\:text-error {
&:where(.drawer-toggle:not(:checked) ~ .drawer-side, .drawer-toggle:not(:checked) ~ .drawer-side *) {
color: var(--color-error);
@@ -9581,14 +9723,19 @@
color: var(--color-green-400);
}
}
+ .is-drawer-open\:flex {
+ &:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
+ display: flex;
+ }
+ }
.is-drawer-open\:w-64 {
&:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
width: calc(var(--spacing) * 64);
}
}
- .is-drawer-open\:min-w-\[340px\] {
+ .is-drawer-open\:max-w-\[300px\] {
&:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
- min-width: 340px;
+ max-width: 300px;
}
}
.is-drawer-open\:justify-between {
@@ -9596,6 +9743,11 @@
justify-content: space-between;
}
}
+ .is-drawer-open\:justify-start {
+ &:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
+ justify-content: flex-start;
+ }
+ }
.is-drawer-open\:space-x-4 {
&:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
:where(& > :not(:last-child)) {
@@ -9605,6 +9757,12 @@
}
}
}
+ .is-drawer-open\:text-xl {
+ &:where(.drawer-toggle:checked ~ .drawer-side, .drawer-toggle:checked ~ .drawer-side *) {
+ font-size: var(--text-xl);
+ line-height: var(--tw-leading, var(--text-xl--line-height));
+ }
+ }
}
@layer base {
:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light] {
diff --git a/Sources/Styleguide/SVG.swift b/Sources/Styleguide/SVG.swift
index a6441a5..54afd7f 100644
--- a/Sources/Styleguide/SVG.swift
+++ b/Sources/Styleguide/SVG.swift
@@ -18,6 +18,7 @@ extension SVG {
case badgeCheck
case ban
case chevronRight
+ case chevronsLeft
case circlePlus
case close
case doorClosed
@@ -46,6 +47,10 @@ extension SVG {
return """
"""
+ case .chevronsLeft:
+ return """
+
+ """
case .circlePlus:
return """
diff --git a/Sources/ViewController/Views/FrictionRate/FrictionRateView.swift b/Sources/ViewController/Views/FrictionRate/FrictionRateView.swift
index 48f0d66..5c3a115 100644
--- a/Sources/ViewController/Views/FrictionRate/FrictionRateView.swift
+++ b/Sources/ViewController/Views/FrictionRate/FrictionRateView.swift
@@ -44,19 +44,24 @@ struct FrictionRateView: HTML, Sendable {
var body: some HTML {
div(.class("p-4 space-y-6")) {
- h1(.class("text-4xl font-bold pb-6")) { "Friction Rate" }
- div(.class("flex space-x-4")) {
- if let availableStaticPressure {
- Label("Available Static Pressure")
- Number(availableStaticPressure, digits: 2)
- .attributes(.class("badge badge-lg badge-outline font-bold ms-4"))
- }
- }
- div(.class("flex space-x-4")) {
- if let frictionRateDesignValue {
- Label("Friction Rate Design Value")
- Number(frictionRateDesignValue, digits: 2)
- .attributes(.class("badge badge-lg badge-outline \(badgeColor) font-bold"))
+ Row {
+ h1(.class("text-4xl font-bold pb-6")) { "Friction Rate" }
+ div(.class("space-y-4")) {
+ div(.class("flex space-x-4 justify-end")) {
+ if let availableStaticPressure {
+ Label("Available Static Pressure")
+ Number(availableStaticPressure, digits: 2)
+ .attributes(.class("badge badge-lg badge-outline font-bold ms-4"))
+ }
+ }
+
+ div(.class("flex space-x-4 justify-end")) {
+ if let frictionRateDesignValue {
+ Label("Friction Rate Design Value")
+ Number(frictionRateDesignValue, digits: 2)
+ .attributes(.class("badge badge-lg badge-outline \(badgeColor) font-bold"))
+ }
+ }
}
}
diff --git a/Sources/ViewController/Views/Project/ProjectView.swift b/Sources/ViewController/Views/Project/ProjectView.swift
index ee00464..2edba36 100644
--- a/Sources/ViewController/Views/Project/ProjectView.swift
+++ b/Sources/ViewController/Views/Project/ProjectView.swift
@@ -36,11 +36,13 @@ struct ProjectView: HTML, Sendable {
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 pb-6")
- ) {
- SVG(.sidebarToggle)
+ Tooltip("Open sidebar", position: .right) {
+ label(
+ .for("my-drawer-1"),
+ .class("btn btn-square btn-ghost drawer-button size-7 pb-6")
+ ) {
+ SVG(.sidebarToggle)
+ }
}
switch self.activeTab {
case .project:
@@ -127,58 +129,6 @@ struct ProjectView: HTML, Sendable {
}
}
-// extension SiteRoute.View.ProjectRoute.DetailRoute.Tab {
-//
-// func view(projectID: Project.ID) async throws -> AnySendableHTML {
-// @Dependency(\.database) var database
-// @Dependency(\.manualD) var manualD
-//
-// switch self {
-// case .project:
-// if let project = try await database.projects.get(projectID) {
-// return ProjectDetail(project: project)
-// } else {
-// return div {
-// "FIX ME!"
-// }
-// }
-// case .rooms:
-// return try await RoomsView(
-// projectID: projectID,
-// rooms: database.rooms.fetch(projectID),
-// sensibleHeatRatio: database.projects.getSensibleHeatRatio(projectID)
-// )
-//
-// case .equivalentLength:
-// return try await EffectiveLengthsView(
-// projectID: projectID,
-// effectiveLengths: database.effectiveLength.fetch(projectID)
-// )
-// case .frictionRate:
-// let equipmentInfo = try await database.equipment.fetch(projectID)
-// let componentLosses = try await database.componentLoss.fetch(projectID)
-// let equivalentLengths = try await database.effectiveLength.fetchMax(projectID)
-//
-// return try await FrictionRateView(
-// equipmentInfo: equipmentInfo,
-// componentLosses: componentLosses,
-// equivalentLengths: equivalentLengths,
-// projectID: projectID,
-// frictionRateResponse: manualD.frictionRate(
-// equipmentInfo: equipmentInfo,
-// componentLosses: componentLosses,
-// effectiveLength: equivalentLengths
-// )
-// )
-// case .ductSizing:
-// return try await DuctSizingView(
-// projectID: projectID,
-// rooms: database.calculateDuctSizes(projectID: projectID)
-// )
-// }
-// }
-// }
-
extension ProjectView {
struct Sidebar: HTML {
@@ -199,7 +149,7 @@ extension ProjectView {
.class(
"""
flex min-h-full flex-col items-start bg-base-200
- is-drawer-close:min-w-[80px] is-drawer-open:min-w-[340px]
+ is-drawer-close:min-w-[80px] is-drawer-open:max-w-[300px]
"""
)
) {
@@ -215,7 +165,7 @@ extension ProjectView {
.class(
"""
flex btn btn-secondary btn-square btn-block
- is-drawer-close:items-center
+ items-center
"""
),
.hx.get(route: .project(.index)),
@@ -224,7 +174,8 @@ extension ProjectView {
.hx.swap(.outerHTML),
) {
div(.class("flex is-drawer-open:space-x-4")) {
- span { "<" }
+ // span { "<" }
+ SVG(.chevronsLeft)
span(.class("is-drawer-close:hidden")) { "All Projects" }
}
}
@@ -239,13 +190,14 @@ extension ProjectView {
}
}
- li(.class("w-full")) {
+ li(.class("flex w-full")) {
row(
title: "Project",
icon: .mapPin,
route: .project(.detail(projectID, .index(tab: .project))),
isComplete: true
)
+ .attributes(.data("active", value: "true"), when: active == .project)
.attributes(.class("btn-active"), when: active == .project)
}
@@ -257,16 +209,20 @@ extension ProjectView {
isComplete: completedSteps.rooms
)
.attributes(.class("btn-active"), when: active == .rooms)
+ .attributes(.data("active", value: "true"), when: active == .rooms)
}
li(.class("w-full")) {
+ // Tooltip("Equivalent Lengths", position: .right) {
row(
- title: "Equivalent Lengths",
+ title: "T.E.L.",
icon: .rulerDimensionLine,
route: .project(.detail(projectID, .equivalentLength(.index))),
isComplete: completedSteps.equivalentLength
)
+ .attributes(.data("active", value: "true"), when: active == .equivalentLength)
.attributes(.class("btn-active"), when: active == .equivalentLength)
+ // }
}
li(.class("w-full")) {
@@ -276,6 +232,7 @@ extension ProjectView {
route: .project(.detail(projectID, .frictionRate(.index))),
isComplete: completedSteps.frictionRate
)
+ .attributes(.data("active", value: "true"), when: active == .frictionRate)
.attributes(.class("btn-active"), when: active == .frictionRate)
}
@@ -287,6 +244,7 @@ extension ProjectView {
isComplete: false,
hideIsComplete: true
)
+ .attributes(.data("active", value: "true"), when: active == .ductSizing)
.attributes(.class("btn-active"), when: active == .ductSizing)
}
}
@@ -301,38 +259,104 @@ extension ProjectView {
href: String,
isComplete: Bool,
hideIsComplete: Bool = false
- ) -> some HTML {
- a(
+ ) -> some HTML {
+ button(
.class(
"""
- flex w-full btn btn-soft btn-square btn-block
- is-drawer-open:justify-between is-drawer-close:items-center
- is-drawer-close:tooltip is-drawer-close:tooltip-right
+ w-full gap-1 py-2 border-b-1 border-gray-200
+ hover:bg-neutral data-active:bg-neutral
+ hover:text-white data-active:text-white
+ is-drawer-open:flex is-drawer-open:space-x-4
+ is-drawer-close:grid-cols-1
"""
),
- .href(href),
- .data("tip", value: title)
+ .hx.get(href),
+ .hx.target("body"),
+ .hx.swap(.outerHTML)
) {
- 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)
+ div(
+ .class(
+ """
+ w-full p-2 gap-1
+ is-drawer-open:flex is-drawer-open:space-x-4
+ is-drawer-close:grid-cols-1
+ """
+ )
+ ) {
+ div(
+ .class(
+ """
+ items-center
+ is-drawer-open:justify-start is-drawer-open:flex is-drawer-open:space-x-4
+ is-drawer-close:justify-center is-drawer-close:mx-auto is-drawer-close:space-y-2
+ """
+ )
+ ) {
+ div(.class("flex items-center justify-center")) {
+ SVG(icon)
+ }
+ .attributes(.class("is-drawer-close:text-green-400"), when: isComplete)
+ .attributes(.class("is-drawer-close:text-error"), when: !isComplete && !hideIsComplete)
+
+ div(.class("flex items-center justify-center")) {
+ span { title }
}
}
- .attributes(.class("text-green-400"), when: isComplete)
- .attributes(.class("text-error"), when: !isComplete)
+
+ if !hideIsComplete {
+ div(.class("flex grow justify-end items-end 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)
+ // a(
+ //
+ // // flex w-full btn btn-soft btn-square btn-block btn-lg
+ // .class(
+ // """
+ // flex w-full hover:bg-gray-900 data-active:bg-gray-900
+ // is-drawer-open:justify-between is-drawer-close:items-center
+ // is-drawer-close:tooltip is-drawer-close:tooltip-right
+ // is-drawer-close:justify-center
+ // """
+ // ),
+ // .href(href),
+ // .data("tip", value: title)
+ // ) {
+ // div(
+ // .class(
+ // """
+ // justify-center items-center mx-auto space-4 py-2
+ // is-drawer-open:flex is-drawer-open:space-x-4
+ // """
+ // )
+ // ) {
+ // SVG(icon)
+ // span(.class("text-gray-200 is-drawer-open:text-xl is-drawer-close:text-sm")) {
+ // 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(
@@ -341,7 +365,7 @@ extension ProjectView {
route: SiteRoute.View,
isComplete: Bool,
hideIsComplete: Bool = false
- ) -> some HTML {
+ ) -> some HTML {
row(
title: title, icon: icon, href: SiteRoute.View.router.path(for: route),
isComplete: isComplete, hideIsComplete: hideIsComplete
diff --git a/input.css b/input.css
index 8bc6dde..f577019 100644
--- a/input.css
+++ b/input.css
@@ -4,3 +4,5 @@
@source not "./daisyui{,*}.mjs";
@plugin "./daisyui.mjs";
+@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
+