import Elementary import ElementaryHTMX import Routes import Styleguide struct MainPage: SendableHTMLDocument where Inner: Sendable { let title = "HVAC-Toolbox" let lang = "en-US" let inner: @Sendable () -> Inner var head: some HTML { meta(.charset(.utf8)) meta(.name("viewport"), .content("width=device-width, initial-scale=1.0")) meta(.name("author"), .content("Michael Housh and Dustin Cole")) meta(.name("og:site-name"), .content("HVAC-Toolbox")) meta(.name("apple-mobile-web-app-title"), .content("HVAC-Toolbox")) meta(.name("format-detection"), .content("telephone=no")) meta(.name("HandheldFriendly"), .content("True")) meta(.name("MobileOptimized"), .content("320")) meta(.name("keywords"), .content("hvac, HVAC, design, system-design, calculators")) Elementary.title { self.title } link(.rel(.stylesheet), .href("/output.css")) link( .rel(.icon), .href("/favicon-32x32.png"), .init(name: "type", value: "image/png"), .init(name: "sizes", value: "32x32") ) link( .rel(.icon), .href("/favicon-16x16.png"), .init(name: "type", value: "image/png"), .init(name: "sizes", value: "16x16") ) link( .rel(.init(rawValue: "apple-touch-icon")), .href("/apple-touch-icon.png"), .init(name: "sizes", value: "180x180") ) link(.rel(.init(rawValue: "mainifest")), .href("/site.webmanifest")) script(.src("https://unpkg.com/htmx.org@2.0.4")) {} } var body: some HTML { main(.class("bg-slate-100 dark:bg-gray-800")) { div(.class("min-h-screen")) { Header() PageContent(body: inner) } Footer() } } } private struct Header: HTML { var content: some HTML { header(.class("\(bg: .blue) mb-8 flex flex-row gap-2 border \(border: .yellow)")) { a( .href(route: .index), .class("group flex flex-row gap-2 \(bg: .yellow) pe-2 rounded-e-lg \(text: .blue) hover:text-blue-600") ) { img(.src("/images/toolbox.svg"), .width(40), .height(40), .class("py-1")) div(.class("flex flex-row mt-2")) { h2(.class("text-2xl font-extrabold pe-3")) { "HVAC-Toolbox" } SVG(.wind, color: .blue) .attributes(.class("group-hover:text-blue-600")) } } // nav(.class("flex flex-row gap-2 p-2 mt-2")) { // // TODO: Add class active, to button that is the active route. // ul(.class("flex flex-wrap gap-x-2 lg:gap-x-5 \(text: .yellow) font-bold")) { // navLink(label: "Mold-Risk", route: .moldRisk(.index)) // navLink(label: "Dehumidifier-Sizing", route: .dehumidifierSize(.index)) // navLink(label: "HVAC-System-Performance", route: .hvacSystemPerformance(.index)) // navLink(label: "Room-Pressure", route: .roomPressure(.index)) // navLink(label: "Capcitor-Calculator", route: .capacitor(.index)) // navLink(label: "Attic-Ventilation", route: .atticVentilation(.index)) // } // } } } func navLink(label: String, route: SiteRoute.View) -> some HTML { li { a(.class("hover:border-b border-yellow-300"), .hx.get(route: route), .hx.target("#content"), .hx.pushURL(true)) { label } } } } private struct Footer: HTML { var content: some HTML { div(.class("bg-blue-500 text-yellow-300 text-sm font-semibold border-t border-yellow-300 mt-20")) { div(.class("sm:grid sm:grid-cols-1 lg:flex lg:justify-between")) { div(.class("grid grid-cols-1 p-4")) { div(.class("flex")) { span { "Toolbox icon by" } a(.class("mx-1"), .href("https://dribbble.com/Laridae?ref=svgrepo.com"), .target(.blank)) { u { "Laridae" } } span { "in CC Attribution License via" } a(.class("mx-1"), .href("https://www.svgrepo.com/"), .target(.blank)) { u { "SVG Repo" } } } div(.class("flex")) { span { "Other SVG's by" } a(.class("mx-1"), .href("https://lucide.dev"), .target(.blank)) { u { "Lucide" } } span { "and licensed under" } a(.class("mx-1"), .href("https://lucide.dev/license")) { u { "MIT." } } } } div(.class("lg:p-8 sm:p-4")) { p { "© Copyright 2025 Michael Housh and Dustin Cole" } } } } } } private struct PageContent: HTML where Body: Sendable { let body: () -> Body var content: some HTML { div(.class("mx-5 lg:mx-20")) { div(.class("rounded-xl shadow-lg bg-white dark:bg-slate-700 p-8 text-gray-600 dark:text-slate-200")) { div(.id("content")) { body() } } } } } protocol SendableHTMLDocument: HTMLDocument, Sendable {}