← Back to task

Commit 4ccd1ada

commit 4ccd1ada825395654a9e6053d9d7e6cd4986b1c0
Author: Ben Sima <ben@bensima.com>
Date:   Thu Nov 27 18:34:10 2025

    Convert dashboard ready queue and recent activity to list-group pattern
    
    All the changes are in place: 1. Created `renderListGroupItem` function
    for compact list-style task di 2. Updated the dashboard's Ready
    Queue section to use `list-group` with 3. Updated the dashboard's
    Recent Activity section to use `list-group` w 4. Updated the
    `RecentActivityPartial` (HTMX partial) to also use the li 5. Added CSS
    styles for `.list-group`, `.list-group-item`, etc. in Style 6. Added
    dark mode styles for the list-group components
    
    The build and tests pass successfully.
    
    Task-Id: t-156.2

diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs
index 9bc5ae51..79e32f65 100644
--- a/Omni/Jr/Web.hs
+++ b/Omni/Jr/Web.hs
@@ -310,6 +310,20 @@ renderTaskCard t =
         Lucid.span_ [Lucid.class_ "priority"] (Lucid.toHtml (tshow (TaskCore.taskPriority t)))
       Lucid.p_ [Lucid.class_ "task-title"] (Lucid.toHtml (TaskCore.taskTitle t))
 
+renderListGroupItem :: (Monad m) => TaskCore.Task -> Lucid.HtmlT m ()
+renderListGroupItem t =
+  Lucid.a_
+    [ Lucid.class_ "list-group-item",
+      Lucid.href_ ("/tasks/" <> TaskCore.taskId t)
+    ]
+    <| do
+      Lucid.div_ [Lucid.class_ "list-group-item-content"] <| do
+        Lucid.span_ [Lucid.class_ "list-group-item-id"] (Lucid.toHtml (TaskCore.taskId t))
+        Lucid.span_ [Lucid.class_ "list-group-item-title"] (Lucid.toHtml (TaskCore.taskTitle t))
+      Lucid.div_ [Lucid.class_ "list-group-item-meta"] <| do
+        statusBadge (TaskCore.taskStatus t)
+        Lucid.span_ [Lucid.class_ "priority"] (Lucid.toHtml (tshow (TaskCore.taskPriority t)))
+
 instance Lucid.ToHtml HomePage where
   toHtmlRaw = Lucid.toHtml
   toHtml (HomePage stats readyTasks recentTasks) =
@@ -342,8 +356,8 @@ instance Lucid.ToHtml HomePage where
           if null readyTasks
             then Lucid.p_ [Lucid.class_ "empty-msg"] "No tasks ready for work."
             else
-              Lucid.div_ [Lucid.class_ "task-list"]
-                <| traverse_ renderTaskCard (take 5 readyTasks)
+              Lucid.div_ [Lucid.class_ "list-group"]
+                <| traverse_ renderListGroupItem (take 5 readyTasks)
 
           Lucid.h2_ "Recent Activity"
           Lucid.div_
@@ -354,8 +368,8 @@ instance Lucid.ToHtml HomePage where
             <| if null recentTasks
               then Lucid.p_ [Lucid.class_ "empty-msg"] "No recent tasks."
               else
-                Lucid.div_ [Lucid.class_ "task-list"]
-                  <| traverse_ renderTaskCard recentTasks
+                Lucid.div_ [Lucid.class_ "list-group"]
+                  <| traverse_ renderListGroupItem recentTasks
     where
       statCard :: (Monad m) => Text -> Int -> Text -> Text -> Lucid.HtmlT m ()
       statCard label count badgeClass href =
@@ -1126,8 +1140,8 @@ instance Lucid.ToHtml RecentActivityPartial where
     if null recentTasks
       then Lucid.p_ [Lucid.class_ "empty-msg"] "No recent tasks."
       else
-        Lucid.div_ [Lucid.class_ "task-list"]
-          <| traverse_ renderTaskCard recentTasks
+        Lucid.div_ [Lucid.class_ "list-group"]
+          <| traverse_ renderListGroupItem recentTasks
 
 instance Lucid.ToHtml ReadyCountPartial where
   toHtmlRaw = Lucid.toHtml
diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs
index 8b1946a4..51c3fd5d 100644
--- a/Omni/Jr/Web/Style.hs
+++ b/Omni/Jr/Web/Style.hs
@@ -25,6 +25,7 @@ stylesheet = do
   layoutStyles
   navigationStyles
   cardStyles
+  listGroupStyles
   statusBadges
   buttonStyles
   formStyles
@@ -443,6 +444,52 @@ cardStyles = do
     padding (px 8) (px 10) (px 8) (px 10)
     margin (px 8) (px 0) (px 8) (px 0)
 
+listGroupStyles :: Css
+listGroupStyles = do
+  ".list-group" ? do
+    display flex
+    flexDirection column
+    backgroundColor white
+    borderRadius (px 2) (px 2) (px 2) (px 2)
+    border (px 1) solid "#d0d0d0"
+    overflow hidden
+  ".list-group-item" ? do
+    display flex
+    alignItems center
+    justifyContent spaceBetween
+    padding (px 8) (px 10) (px 8) (px 10)
+    borderBottom (px 1) solid "#e5e7eb"
+    textDecoration none
+    color inherit
+    transition "background-color" (ms 150) ease (sec 0)
+  ".list-group-item" # lastChild ? borderBottom (px 0) none transparent
+  ".list-group-item" # hover ? do
+    backgroundColor "#f9fafb"
+    textDecoration none
+  ".list-group-item-content" ? do
+    display flex
+    alignItems center
+    Stylesheet.key "gap" ("8px" :: Text)
+    Stylesheet.key "flex" ("1" :: Text)
+    minWidth (px 0)
+    overflow hidden
+  ".list-group-item-id" ? do
+    fontFamily ["SF Mono", "Monaco", "monospace"] [monospace]
+    color "#0066cc"
+    fontSize (px 12)
+    flexShrink 0
+  ".list-group-item-title" ? do
+    fontSize (px 13)
+    color "#374151"
+    overflow hidden
+    Stylesheet.key "text-overflow" ("ellipsis" :: Text)
+    whiteSpace nowrap
+  ".list-group-item-meta" ? do
+    display flex
+    alignItems center
+    Stylesheet.key "gap" ("6px" :: Text)
+    flexShrink 0
+
 statusBadges :: Css
 statusBadges = do
   ".badge" ? do
@@ -961,9 +1008,14 @@ darkModeStyles =
       <> ".status-form"
       <> ".diff-section"
       <> ".review-actions"
+      <> ".list-group"
       ? do
         backgroundColor "#1f2937"
         borderColor "#374151"
+    ".list-group-item" ? borderBottomColor "#374151"
+    ".list-group-item" # hover ? backgroundColor "#374151"
+    ".list-group-item-id" ? color "#60a5fa"
+    ".list-group-item-title" ? color "#d1d5db"
     header ? do
       backgroundColor "#1f2937"
       borderColor "#374151"