[object Object]

← back to AbramsOS

AbramsOS nav: move 18 top tabs into a left sidebar panel + add missing Settlements link

889a18c83f49aec31d47a5d5f809ef1ba2048b23 · 2026-08-18 16:04:41 -0700 · Steve

- header.ejs: topbar -> sticky left .sidebar (vertical scroll nav, brand top, sign-out+theme bottom); adds /settlements (+ Claims) to the nav; client-side active-link highlight
- footer.ejs: close the new content-wrap/applayout wrappers
- app.css: .applayout flex + .sidebar/.sidenav rules + <=860px row-wrap fallback

Files touched

Diff

commit 889a18c83f49aec31d47a5d5f809ef1ba2048b23
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Aug 18 16:04:41 2026 -0700

    AbramsOS nav: move 18 top tabs into a left sidebar panel + add missing Settlements link
    
    - header.ejs: topbar -> sticky left .sidebar (vertical scroll nav, brand top, sign-out+theme bottom); adds /settlements (+ Claims) to the nav; client-side active-link highlight
    - footer.ejs: close the new content-wrap/applayout wrappers
    - app.css: .applayout flex + .sidebar/.sidenav rules + <=860px row-wrap fallback
---
 public/css/app.css        | 31 ++++++++++++++++
 views/partials/footer.ejs |  2 ++
 views/partials/header.ejs | 92 ++++++++++++++++++++++++++---------------------
 3 files changed, 85 insertions(+), 40 deletions(-)

diff --git a/public/css/app.css b/public/css/app.css
index 862c026..5b953b7 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -371,3 +371,34 @@ form input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0
 .recalls { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 8px; }
 .recall-item { border-left: 3px solid var(--danger); padding: 6px 10px; background: rgba(248,113,113,0.06); border-radius: 6px; font-size: 12px; }
 .recall-item strong { color: var(--danger); }
+
+/* ─── left sidebar nav (moved off the overloaded topbar) ─── */
+.applayout { display: flex; align-items: flex-start; min-height: 100vh; }
+.sidebar {
+  flex: 0 0 210px; width: 210px;
+  margin: 14px; padding: 14px 10px;
+  border-radius: var(--radius);
+  position: sticky; top: 14px;
+  height: calc(100vh - 28px);
+  display: flex; flex-direction: column; gap: 12px;
+  overflow-y: auto; z-index: 10;
+}
+.sidebar .brand { padding: 4px 8px 6px; }
+.sidenav { display: flex; flex-direction: column; gap: 2px; margin: 0; }
+.sidenav a { color: var(--text-dim); font-size: 14px; padding: 8px 10px; border-radius: 8px; }
+.sidenav a:hover { color: var(--text); background: var(--surface-strong); }
+.sidenav a.active { color: var(--text); background: var(--surface-strong); font-weight: 600; }
+.side-actions { margin-top: auto; display: flex; align-items: center; gap: 8px; padding: 8px; border-top: 1px solid var(--border); }
+.content-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; }
+.content-wrap main { margin: 0 auto; width: 100%; }
+
+@media (max-width: 860px) {
+  .applayout { flex-direction: column; }
+  .sidebar {
+    flex: none; width: auto; height: auto;
+    position: static; margin: 14px 14px 0;
+    flex-direction: row; flex-wrap: wrap; align-items: center;
+  }
+  .sidenav { flex-direction: row; flex-wrap: wrap; gap: 4px; }
+  .side-actions { margin: 0 0 0 auto; border-top: none; }
+}
diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs
index 45f8047..7099435 100644
--- a/views/partials/footer.ejs
+++ b/views/partials/footer.ejs
@@ -3,6 +3,8 @@
     <small>Contact: <a href="mailto:<%= infoEmail %>"><%= infoEmail %></a></small>
     <small>Drafts only — not legal advice. See docs/COMPLIANCE.md.</small>
   </footer>
+  </div><!-- /content-wrap -->
+  </div><!-- /applayout -->
   <script src="/js/theme.js"></script>
   <% if (typeof gridScript !== 'undefined' && gridScript) { %>
     <script src="/js/sort-density.js"></script>
diff --git a/views/partials/header.ejs b/views/partials/header.ejs
index 7756feb..39e3b23 100644
--- a/views/partials/header.ejs
+++ b/views/partials/header.ejs
@@ -15,43 +15,55 @@
   </script>
 </head>
 <body>
-  <header class="topbar glass">
-    <div class="brand">
-      <a href="/">AbramsOS</a>
-      <span class="version">v0.1</span>
-    </div>
-    <nav>
-      <a href="/">Home</a>
-      <a href="/deadlines">Deadlines</a>
-      <a href="/bills">Bills</a>
-      <a href="/assets">Assets</a>
-      <a href="/neighborhood">Watch</a>
-      <a href="/warranties">Warranties</a>
-      <a href="/reorders">Reorders</a>
-      <a href="/savings">Savings</a>
-      <a href="/health">Health</a>
-      <a href="/biometrics">Biometrics</a>
-      <a href="/medications">Meds</a>
-      <a href="/prescriptions">Rx</a>
-      <a href="/household">Household</a>
-      <a href="/purchases">Purchases</a>
-      <a href="/claims">Claims</a>
-      <a href="/recalls">Recalls</a>
-      <a href="/import">Import</a>
-      <a href="/connectors">Connectors</a>
-      <a href="/audit">Audit</a>
-    </nav>
-    <% if (typeof userId !== 'undefined' && userId) { %>
-      <form method="post" action="/signout" style="margin:0">
-        <input type="hidden" name="_csrf" value="<%= csrfToken %>">
-        <button class="signout-btn" type="submit">Sign out</button>
-      </form>
-    <% } %>
-    <button id="themeToggle" class="theme-toggle" aria-label="Toggle theme" title="Toggle dark/light">
-      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
-        <circle cx="12" cy="12" r="4"></circle>
-        <path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M4.93 19.07l1.41-1.41m11.32-11.32l1.41-1.41"></path>
-      </svg>
-    </button>
-  </header>
-  <main>
+  <div class="applayout">
+    <aside class="sidebar glass">
+      <div class="brand">
+        <a href="/">AbramsOS</a>
+        <span class="version">v0.1</span>
+      </div>
+      <nav class="sidenav">
+        <a href="/">Home</a>
+        <a href="/settlements">Settlements</a>
+        <a href="/claims">Claims</a>
+        <a href="/deadlines">Deadlines</a>
+        <a href="/bills">Bills</a>
+        <a href="/assets">Assets</a>
+        <a href="/neighborhood">Watch</a>
+        <a href="/warranties">Warranties</a>
+        <a href="/reorders">Reorders</a>
+        <a href="/savings">Savings</a>
+        <a href="/health">Health</a>
+        <a href="/biometrics">Biometrics</a>
+        <a href="/medications">Meds</a>
+        <a href="/prescriptions">Rx</a>
+        <a href="/household">Household</a>
+        <a href="/purchases">Purchases</a>
+        <a href="/recalls">Recalls</a>
+        <a href="/import">Import</a>
+        <a href="/connectors">Connectors</a>
+        <a href="/audit">Audit</a>
+      </nav>
+      <div class="side-actions">
+        <% if (typeof userId !== 'undefined' && userId) { %>
+          <form method="post" action="/signout" style="margin:0">
+            <input type="hidden" name="_csrf" value="<%= csrfToken %>">
+            <button class="signout-btn" type="submit">Sign out</button>
+          </form>
+        <% } %>
+        <button id="themeToggle" class="theme-toggle" aria-label="Toggle theme" title="Toggle dark/light">
+          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+            <circle cx="12" cy="12" r="4"></circle>
+            <path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M4.93 19.07l1.41-1.41m11.32-11.32l1.41-1.41"></path>
+          </svg>
+        </button>
+      </div>
+      <script>
+        (function(){ try { var p = location.pathname;
+          document.querySelectorAll('.sidenav a').forEach(function(a){
+            var h = a.getAttribute('href');
+            if (h === p || (h !== '/' && p.indexOf(h) === 0)) a.classList.add('active');
+          }); } catch(e){} })();
+      </script>
+    </aside>
+    <div class="content-wrap">
+    <main>

← ae4ebab settlements: remove duplicate claim-and-go (keep the payment  ·  back to AbramsOS  ·  AbramsOS sidebar: group nav into Money&Claims / Health / Hom b3ececa →