Add view switcher nav links to header
Assisted-by: Claude Opus 4.6 via Claude Code
diff --git a/lib/ketchup/views/layout.rb b/lib/ketchup/views/layout.rb
index 129f0cd..6db5885 100644
--- a/lib/ketchup/views/layout.rb
+++ b/lib/ketchup/views/layout.rb
@@ -4,9 +4,10 @@ require "phlex"
module Views
class Layout < Phlex::HTML
- def initialize(current_user:, title: "Ketchup")
+ def initialize(current_user:, title: "Ketchup", active_view: :list)
@current_user = current_user
@title = title
+ @active_view = active_view
end
def view_template(&)
@@ -35,6 +36,12 @@ module Views
header(class: "site-header") do
a(href: "/", class: "site-name") { "Ketchup" }
nav(class: "site-nav") do
+ view_links.each do |path, label, view_key|
+ a(
+ href: path,
+ class: ["view-link", ("view-link--active" if @active_view == view_key)]
+ ) { label }
+ end
a(href: "/series/new", class: "header-action") { "+ New" }
a(href: "/users/#{@current_user[:id]}", class: "header-user") { @current_user[:login] }
end
@@ -56,6 +63,15 @@ module Views
private
+ def view_links
+ [
+ ["/", "List", :list],
+ ["/focus", "Focus", :focus],
+ ["/calendar", "Calendar", :calendar],
+ ["/agenda", "Agenda", :agenda],
+ ]
+ end
+
def render_footer
config = CONFIG
parts = []
diff --git a/public/css/app.css b/public/css/app.css
index 0bd1d2e..393de28 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -79,6 +79,21 @@ h2 { font-size: var(--step-0); font-weight: 600; }
color: #555;
}
+.view-link {
+ font-size: var(--step--1);
+ color: #999;
+ text-decoration: none;
+}
+
+.view-link:hover {
+ color: #555;
+}
+
+.view-link--active {
+ color: #1a1a1a;
+ font-weight: 600;
+}
+
/* -------------------- */
/* Site footer */
/* -------------------- */
diff --git a/test/test_web.rb b/test/test_web.rb
index 56b1d5b..bf3a430 100644
--- a/test/test_web.rb
+++ b/test/test_web.rb
@@ -535,6 +535,19 @@ class TestWeb < Minitest::Test
assert_includes last_response.body, 'x-data="panel"'
end
+ def test_header_shows_view_nav
+ get "/", {}, auth_headers
+ assert_includes last_response.body, 'href="/"'
+ assert_includes last_response.body, 'href="/focus"'
+ assert_includes last_response.body, 'href="/calendar"'
+ assert_includes last_response.body, 'href="/agenda"'
+ end
+
+ def test_header_highlights_active_view
+ get "/", {}, auth_headers
+ assert_includes last_response.body, "view-link--active"
+ end
+
def test_csrf_rejects_post_without_token
get "/", {}, auth_headers # establish session
post "/series", {