← Back to task

Commit 78ad1158

commit 78ad115885c3389680411241e04ee2644a2d0a43
Author: Ben Sima <ben@bensima.com>
Date:   Thu Nov 27 16:37:20 2025

    Implement hamburger collapse menu for mobile
    
    The implementation is complete. I've implemented a hamburger
    collapse me
    
    1. **Omni/Jr/Web.hs**: Added a checkbox-based hamburger menu toggle
    (CSS
       - Hidden checkbox input for toggle state - Label with 3 hamburger
       lines that acts as the button - The navbar links are shown/hidden
       based on checkbox state
    
    2. **Omni/Jr/Web/Style.hs**: Added responsive CSS styles:
       - Hamburger menu styles (`.navbar-hamburger`, `.hamburger-line`)
       - Hidden by default on desktop, displayed on mobile (< 600px) -
       Full-width mobile menu with proper ordering - Dark mode support
       for hamburger lines - Dropdown menus expand inline on mobile
    
    Task-Id: t-154.3

diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs
index 3327b269..d9746a13 100644
--- a/Omni/Jr/Web.hs
+++ b/Omni/Jr/Web.hs
@@ -189,6 +189,19 @@ navbar :: (Monad m) => Lucid.HtmlT m ()
 navbar =
   Lucid.nav_ [Lucid.class_ "navbar"] <| do
     Lucid.a_ [Lucid.href_ "/", Lucid.class_ "navbar-brand"] "Jr"
+    Lucid.input_
+      [ Lucid.type_ "checkbox",
+        Lucid.id_ "navbar-toggle",
+        Lucid.class_ "navbar-toggle-checkbox"
+      ]
+    Lucid.label_
+      [ Lucid.for_ "navbar-toggle",
+        Lucid.class_ "navbar-hamburger"
+      ]
+      <| do
+        Lucid.span_ [Lucid.class_ "hamburger-line"] ""
+        Lucid.span_ [Lucid.class_ "hamburger-line"] ""
+        Lucid.span_ [Lucid.class_ "hamburger-line"] ""
     Lucid.div_ [Lucid.class_ "navbar-links"] <| do
       Lucid.a_ [Lucid.href_ "/", Lucid.class_ "navbar-link"] "Dashboard"
       Lucid.div_ [Lucid.class_ "navbar-dropdown"] <| do
diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs
index 6fb793df..86fe5d0b 100644
--- a/Omni/Jr/Web/Style.hs
+++ b/Omni/Jr/Web/Style.hs
@@ -162,6 +162,23 @@ navigationStyles = do
     color "#0066cc"
     textDecoration none
   ".navbar-brand" # hover ? textDecoration none
+  ".navbar-toggle-checkbox" ? display none
+  ".navbar-hamburger" ? do
+    display none
+    flexDirection column
+    justifyContent center
+    alignItems center
+    width (px 32)
+    height (px 32)
+    cursor pointer
+    Stylesheet.key "gap" ("4px" :: Text)
+  ".hamburger-line" ? do
+    display block
+    width (px 20)
+    height (px 2)
+    backgroundColor "#374151"
+    borderRadius (px 1) (px 1) (px 1) (px 1)
+    transition "all" (ms 200) ease (sec 0)
   ".navbar-links" ? do
     display flex
     Stylesheet.key "gap" ("2px" :: Text)
@@ -842,17 +859,39 @@ responsiveStyles = do
     ".container" ? padding (px 6) (px 8) (px 6) (px 8)
     ".navbar" ? do
       padding (px 6) (px 8) (px 6) (px 8)
+      flexWrap Flexbox.wrap
+    ".navbar-hamburger" ? do
+      display flex
+      Stylesheet.key "order" ("2" :: Text)
     ".navbar-links" ? do
-      Stylesheet.key "gap" ("1px" :: Text)
+      display none
+      width (pct 100)
+      Stylesheet.key "order" ("3" :: Text)
+      flexDirection column
+      alignItems flexStart
+      paddingTop (px 8)
+      Stylesheet.key "gap" ("0" :: Text)
+    ".navbar-toggle-checkbox" # checked |+ ".navbar-hamburger" |+ ".navbar-links" ? do
+      display flex
     ".navbar-link" ? do
-      padding (px 4) (px 6) (px 4) (px 6)
-      fontSize (px 11)
+      padding (px 8) (px 6) (px 8) (px 6)
+      fontSize (px 13)
+      width (pct 100)
+    ".navbar-dropdown" ? do
+      width (pct 100)
     ".navbar-dropdown-btn" ? do
-      padding (px 4) (px 6) (px 4) (px 6)
-      fontSize (px 11)
+      padding (px 8) (px 6) (px 8) (px 6)
+      fontSize (px 13)
+      width (pct 100)
+      textAlign (alignSide sideLeft)
+    ".navbar-dropdown-content" ? do
+      position static
+      Stylesheet.key "box-shadow" ("none" :: Text)
+      paddingLeft (px 12)
+      backgroundColor transparent
     ".navbar-dropdown-item" ? do
       padding (px 6) (px 10) (px 6) (px 10)
-      fontSize (px 11)
+      fontSize (px 12)
     ".nav-content" ? do
       flexDirection column
       alignItems flexStart
@@ -908,6 +947,7 @@ darkModeStyles =
       Stylesheet.key "box-shadow" ("0 2px 8px rgba(0,0,0,0.3)" :: Text)
     ".navbar-dropdown-item" ? color "#d1d5db"
     ".navbar-dropdown-item" # hover ? backgroundColor "#374151"
+    ".hamburger-line" ? backgroundColor "#d1d5db"
     ".nav-brand" ? color "#f3f4f6"
     "h2" <> "h3" ? color "#d1d5db"
     a ? color "#60a5fa"