commit 39e94ca23b77af5634abfa7787033e23960e08d4
Author: Coder Agent <coder@agents.omni>
Date: Mon Feb 16 19:04:25 2026
Unify top nav links across tasks, news, and files
Add shared top-level links (/tasks, /news, /files)
in Task Web, Newsreader, and Serve pages.
This keeps navigation consistent from every entrypoint.
Also handle TaskCore.Verified in Task Web status
badge and dropdown rendering.
Task-Id: t-613
Task-Id: t-614
diff --git a/Omni/Newsreader/Web.hs b/Omni/Newsreader/Web.hs
index 38259a69..5d6064ad 100644
--- a/Omni/Newsreader/Web.hs
+++ b/Omni/Newsreader/Web.hs
@@ -318,8 +318,11 @@ articleCard p' feedMap art = do
nav :: Pfx -> L.Html ()
nav p' =
L.nav_ <| do
- L.a_ [L.href_ (p' "/"), L.class_ "brand"] "newsreader"
+ L.a_ [L.href_ "/tasks", L.class_ "brand"] "omni"
L.span_ [L.class_ "nav-links"] <| do
+ L.a_ [L.href_ "/tasks"] "tasks"
+ L.a_ [L.href_ "/news/"] "news"
+ L.a_ [L.href_ "/files/"] "files"
L.a_ [L.href_ (p' "/topics")] "topics"
L.a_ [L.href_ (p' "/feeds")] "feeds"
L.a_ [L.href_ (p' "/search")] "search"
diff --git a/Omni/Serve.hs b/Omni/Serve.hs
index 9fd6de9d..077a92d1 100755
--- a/Omni/Serve.hs
+++ b/Omni/Serve.hs
@@ -183,6 +183,14 @@ breadcrumbs p' relPath = do
where
parts = filter (/= ".") (FP.splitDirectories relPath)
+-- | Shared Omni top navigation.
+topNav :: L.Html ()
+topNav =
+ L.nav_ [L.class_ "topnav"] <| do
+ L.a_ [L.href_ "/tasks", L.class_ "topnav-link"] "tasks"
+ L.a_ [L.href_ "/news/", L.class_ "topnav-link"] "news"
+ L.a_ [L.href_ "/files/", L.class_ "topnav-link"] "files"
+
-- | Common page shell with CSS.
pageShell :: Text -> L.Html () -> L.Html ()
pageShell title body =
@@ -192,7 +200,9 @@ pageShell title body =
L.meta_ [L.name_ "viewport", L.content_ "width=device-width, initial-scale=1"]
L.title_ (L.toHtml title)
L.style_ css
- L.body_ body
+ L.body_ <| do
+ topNav
+ body
-- | Stylesheet.
css :: Text
@@ -210,6 +220,10 @@ css =
" background: var(--bg); color: var(--fg); line-height: 1.6; }",
"a { color: var(--link); text-decoration: none; }",
"a:hover { text-decoration: underline; }",
+ ".topnav { display: flex; gap: 1rem; align-items: baseline;",
+ " border-bottom: 1px solid var(--border); margin: 0 0 1rem; padding: 0.5rem 0; }",
+ ".topnav-link { color: var(--muted); font-size: 0.95rem; }",
+ ".topnav-link:hover { color: var(--fg); }",
".breadcrumb { font-size: 0.85rem; color: var(--muted); margin-bottom: 1rem; }",
"h1 { font-size: 1.5rem; margin: 0 0 1rem; }",
"",
diff --git a/Omni/Task/Web/Components.hs b/Omni/Task/Web/Components.hs
index 364f5235..275d542e 100644
--- a/Omni/Task/Web/Components.hs
+++ b/Omni/Task/Web/Components.hs
@@ -569,7 +569,9 @@ navbar =
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.a_ [Lucid.href_ "/tasks", Lucid.class_ "navbar-link"] "Tasks"
+ Lucid.a_ [Lucid.href_ "/news/", Lucid.class_ "navbar-link"] "News"
+ Lucid.a_ [Lucid.href_ "/files/", Lucid.class_ "navbar-link"] "Files"
Lucid.div_ [Lucid.class_ "navbar-dropdown"] <| do
Lucid.button_ [Lucid.class_ "navbar-dropdown-btn"] "Tasks ▾"
Lucid.div_ [Lucid.class_ "navbar-dropdown-content"] <| do
@@ -596,6 +598,7 @@ statusBadge status =
TaskCore.ReviewInProgress -> ("badge badge-review", "Review In Progress")
TaskCore.Approved -> ("badge badge-approved", "Approved")
TaskCore.Integrating -> ("badge badge-inprogress", "Integrating")
+ TaskCore.Verified -> ("badge badge-approved", "Verified")
TaskCore.Done -> ("badge badge-done", "Done")
TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
in Lucid.span_ [Lucid.class_ cls] label
@@ -734,6 +737,7 @@ clickableBadge status _tid =
TaskCore.ReviewInProgress -> ("badge badge-review status-badge-clickable", "Review In Progress")
TaskCore.Approved -> ("badge badge-approved status-badge-clickable", "Approved")
TaskCore.Integrating -> ("badge badge-inprogress status-badge-clickable", "Integrating")
+ TaskCore.Verified -> ("badge badge-approved status-badge-clickable", "Verified")
TaskCore.Done -> ("badge badge-done status-badge-clickable", "Done")
TaskCore.NeedsHelp -> ("badge badge-needshelp status-badge-clickable", "Needs Help")
in Lucid.span_
@@ -764,6 +768,7 @@ statusDropdownOptions currentStatus tid =
statusOption TaskCore.ReviewInProgress currentStatus tid
statusOption TaskCore.Approved currentStatus tid
statusOption TaskCore.Integrating currentStatus tid
+ statusOption TaskCore.Verified currentStatus tid
statusOption TaskCore.Done currentStatus tid
statusOption TaskCore.NeedsHelp currentStatus tid
@@ -777,6 +782,7 @@ statusOption opt currentStatus tid =
TaskCore.ReviewInProgress -> ("badge badge-review", "Review In Progress")
TaskCore.Approved -> ("badge badge-approved", "Approved")
TaskCore.Integrating -> ("badge badge-inprogress", "Integrating")
+ TaskCore.Verified -> ("badge badge-approved", "Verified")
TaskCore.Done -> ("badge badge-done", "Done")
TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
isSelected = opt == currentStatus