thunderbird-patch-review

Easy-to-use patch review interface for Thunderbird

Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht

git clone git://mccd.space/thunderbird-patch-review

commit 893b7a0be9f0f09f676f66ca9a3d530f17291e75
parent 0a3e906c666337b0a51a6b16f1391c300e41a127
Author: Pi Agent <agent@pi.local>
Date:   Sat, 18 Jul 2026 12:52:11 +0200

review: group the patch list and commit message into one box

Merge the series selector and the commit-message block into a single
bordered box: <nav id="series-nav"> is removed from the page and
rendered inside renderPatch, with the commit message (and any general
patch comment) as siblings beneath it. The pills now live in a
.series-nav footer-row inside the shared .patch-box, and the commit
message drops its own border/background since the box provides them.

Diffstat:
Mextension/review/review.css | 31+++++++++++++++++++++----------
Mextension/review/review.html | 2--
Mextension/review/review.js | 22++++++++++++++++------
3 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/extension/review/review.css b/extension/review/review.css
@@ -157,14 +157,25 @@ button.primary:hover { color: #fff; opacity: 0.9; }
   color: var(--fg);
 }
 
-#series-nav {
+.patch-box {
+  margin: 0.6rem 0 1rem;
+  border: 1px solid var(--border);
+  border-radius: 6px;
+  background: var(--surface);
+  overflow: hidden;
+}
+
+.series-nav {
   display: flex;
-  gap: 0.4rem;
+  align-items: center;
+  justify-content: center;
+  gap: 0.5rem;
   flex-wrap: wrap;
-  padding: 0.6rem 1rem;
+  padding: 0.4rem 0.6rem;
+  border-bottom: 1px solid var(--border);
 }
 
-#series-nav .pill {
+.series-nav .pill {
   padding: 0.2rem 0.7rem;
   border: 1px solid var(--border);
   border-radius: 999px;
@@ -172,13 +183,13 @@ button.primary:hover { color: #fff; opacity: 0.9; }
   color: var(--muted);
 }
 
-#series-nav .pill.active {
+.series-nav .pill.active {
   border-color: var(--accent);
   color: var(--accent);
   font-weight: 600;
 }
 
-#series-nav .pill .badge {
+.series-nav .pill .badge {
   display: inline-block;
   min-width: 1.2em;
   margin-left: 0.35em;
@@ -193,11 +204,11 @@ button.primary:hover { color: #fff; opacity: 0.9; }
 
 .commit-message {
   position: relative;
-  margin: 0.5rem 0 1rem;
+  margin: 0;
   padding: 0.8rem 1rem;
-  border: 1px solid var(--border);
-  border-radius: 6px;
-  background: var(--surface);
+  border: 0;
+  border-radius: 0;
+  background: transparent;
   white-space: pre-wrap;
   font-family: ui-monospace, monospace;
 }
diff --git a/extension/review/review.html b/extension/review/review.html
@@ -37,8 +37,6 @@
     </div>
   </header>
 
-  <nav id="series-nav"></nav>
-
   <main id="content"></main>
 
   <div id="status" hidden>
diff --git a/extension/review/review.js b/extension/review/review.js
@@ -64,7 +64,6 @@ async function init() {
     $("#srht-status").hidden = false;
   }
 
-  renderNav();
   renderPatch();
   updateCount();
 }
@@ -73,7 +72,8 @@ async function init() {
 // Rendering
 
 function renderNav() {
-  const nav = $("#series-nav");
+  const nav = state.navEl;
+  if (!nav) return;
   nav.textContent = "";
   state.series.forEach((patch, i) => {
     const pill = document.createElement("span");
@@ -93,7 +93,6 @@ function renderNav() {
     pill.title = patch.subject;
     pill.addEventListener("click", () => {
       state.current = i;
-      renderNav();
       renderPatch();
     });
     nav.appendChild(pill);
@@ -107,6 +106,17 @@ function renderPatch() {
   const patch = state.series[i];
   const parsed = state.parsed[i];
 
+  // The patch list and the commit message share one box so the series
+  // selector reads as a header to the message it selects.
+  const box = document.createElement("div");
+  box.className = "patch-box";
+
+  const nav = document.createElement("nav");
+  nav.className = "series-nav";
+  box.appendChild(nav);
+  state.navEl = nav;
+  renderNav();
+
   // Commit message (or cover letter text) with a whole-patch comment. Never
   // fall back to the raw body for a patch — that would print the whole diff
   // above the interactive one (common case: single-line commit messages,
@@ -121,12 +131,13 @@ function renderPatch() {
   generalBtn.textContent = state.comments[i][store.GENERAL] ? "Edit comment" : "Comment on patch";
   generalBtn.addEventListener("click", () => openGeneralEditor(msg));
   msg.appendChild(generalBtn);
-  content.appendChild(msg);
+  box.appendChild(msg);
 
   const existingGeneral = state.comments[i][store.GENERAL];
   if (existingGeneral) {
-    content.appendChild(commentCard(existingGeneral.text, () => openGeneralEditor(msg)));
+    box.appendChild(commentCard(existingGeneral.text, () => openGeneralEditor(msg)));
   }
+  content.appendChild(box);
 
   parsed.files.forEach((file, fileIndex) => {
     const details = document.createElement("details");
@@ -299,7 +310,6 @@ function editorBox(initial, loc, close) {
       textarea.value
     );
     close();
-    renderNav();
     renderPatch();
     updateCount();
   };