Collapse three-border header to two rows, one divider
Three header borders read as stripes; the design calls for one — the
section nav's border — with the position token right-aligned in it.
Assisted-by: Claude Sonnet 4.6 via Claude Code
diff --git a/quire-server/src/quire/web/handlers/tree.rs b/quire-server/src/quire/web/handlers/tree.rs
index 42ce017..3f43adb 100644
--- a/quire-server/src/quire/web/handlers/tree.rs
+++ b/quire-server/src/quire/web/handlers/tree.rs
@@ -5,7 +5,7 @@ use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use super::super::db;
-use super::super::templates::{Crumb, PathCommit, TreeEntry, TreeEntryKind, TreeTemplate};
+use super::super::templates::{Crumb, TreeEntry, TreeEntryKind, TreeTemplate};
use super::git::RepoView;
use super::render;
use crate::Quire;
@@ -65,7 +65,6 @@ async fn tree_at_path(quire: Quire, repo: String, path: String) -> Response {
bookmark: tree_data.bookmark,
sha_short: tree_data.sha_short,
entries: tree_data.entries,
- head_commit: tree_data.head_commit,
};
render(&tmpl)
}
@@ -74,7 +73,6 @@ struct TreeData {
bookmark: String,
sha_short: String,
entries: Vec<TreeEntry>,
- head_commit: Option<PathCommit>,
}
fn read_tree_data(reader: &RepoView<'_>, path: &str) -> Option<TreeData> {
@@ -153,28 +151,5 @@ fn read_tree_data(reader: &RepoView<'_>, path: &str) -> Option<TreeData> {
});
}
- let head_commit = {
- let fmt = "--format=%h|%s|%ar|%an";
- let info = if path.is_empty() {
- reader.run(&["log", "-1", fmt, "HEAD"])
- } else {
- reader.run(&["log", "-1", fmt, "HEAD", "--", path])
- };
- info.and_then(|s| {
- let mut it = s.splitn(4, '|');
- Some(PathCommit {
- sha_short: it.next()?.to_string(),
- description: it.next().unwrap_or("").to_string(),
- age: it.next().unwrap_or("").to_string(),
- author: it.next().unwrap_or("").to_string(),
- })
- })
- };
-
- Some(TreeData {
- bookmark,
- sha_short,
- entries,
- head_commit,
- })
+ Some(TreeData { bookmark, sha_short, entries })
}
diff --git a/quire-server/src/quire/web/templates.rs b/quire-server/src/quire/web/templates.rs
index 53a25c6..5e7b087 100644
--- a/quire-server/src/quire/web/templates.rs
+++ b/quire-server/src/quire/web/templates.rs
@@ -381,7 +381,6 @@ pub struct TreeTemplate {
/// Short commit hash for HEAD.
pub sha_short: String,
pub entries: Vec<TreeEntry>,
- pub head_commit: Option<PathCommit>,
}
impl TreeTemplate {
@@ -389,27 +388,6 @@ impl TreeTemplate {
pkg_version()
}
- /// Returns (label, href) pairs for the path breadcrumb.
- /// Root: just the repo name with no link (it's the current location).
- /// Sub-path: repo → each segment, with links on all but the last.
- pub fn path_parts(&self) -> Vec<(String, Option<String>)> {
- if self.path.is_empty() {
- return vec![(self.repo.clone(), None)];
- }
- let mut parts = vec![(self.repo.clone(), Some(format!("/{}/tree", self.repo)))];
- let segments: Vec<&str> = self.path.split('/').collect();
- for (i, seg) in segments.iter().enumerate() {
- let subpath = segments[..=i].join("/");
- let href = if i < segments.len() - 1 {
- Some(format!("/{}/tree/{}", self.repo, subpath))
- } else {
- None
- };
- parts.push((seg.to_string(), href));
- }
- parts
- }
-
pub fn parent_url(&self) -> String {
if self.path.is_empty() {
return format!("/{}", self.repo);
@@ -486,24 +464,6 @@ impl TreeEntry {
}
}
-pub struct PathCommit {
- pub sha_short: String,
- pub description: String,
- pub age: String,
- pub author: String,
-}
-
-impl PathCommit {
- pub fn sha_head(&self) -> &str {
- &self.sha_short[..self.sha_short.len().min(4)]
- }
-
- pub fn sha_tail(&self) -> &str {
- let start = self.sha_short.len().min(4);
- &self.sha_short[start..]
- }
-}
-
// ── Error ──────────────────────────────────────────────────────────
#[derive(Template)]
diff --git a/quire-server/static/style.css b/quire-server/static/style.css
index 8367c92..8b8d625 100644
--- a/quire-server/static/style.css
+++ b/quire-server/static/style.css
@@ -66,7 +66,6 @@ pre { white-space: pre-wrap; word-break: break-word; }
.page-nav {
padding: var(--space-xs) var(--space-xl);
- border-bottom: 1px solid var(--rule);
font-family: var(--font-mono);
font-size: var(--step--1);
font-weight: 500;
@@ -305,44 +304,9 @@ html.dark {
/* ── Repo Home ─────────────────────────────────────────────────── */
-.repo-header {
- padding: 28px 56px 20px;
- border-bottom: 1px solid var(--rule);
-}
-
-.repo-title-row {
- display: flex;
- align-items: baseline;
- gap: var(--space-s);
- flex-wrap: wrap;
-}
-
-.repo-name {
- font-family: var(--font-mono);
- font-size: 20px;
- font-weight: 500;
- letter-spacing: -0.2px;
- margin: 0;
- color: var(--ink);
-}
-
-.repo-meta-row {
- margin-top: 8px;
- font-family: var(--font-mono);
- font-size: 12.5px;
- color: var(--muted);
- display: flex;
- gap: 22px;
- flex-wrap: wrap;
- align-items: center;
-}
-
-.repo-meta-item { display: inline-flex; align-items: baseline; gap: 5px; }
-.repo-meta-label { color: var(--mutedFaint); font-size: 10px; letter-spacing: 0.6px; text-transform: uppercase; }
.repo-meta-sep { color: var(--rule2); }
.repo-meta-dot { color: var(--rule2); }
-.repo-meta-value { color: var(--ink); }
-.ci-inline { align-items: center; gap: 6px; }
+.ci-inline { display: inline-flex; align-items: center; gap: 6px; }
.bookmark-glyph { color: var(--mutedFaint); }
.bookmark-name { color: var(--accent); }
@@ -367,7 +331,7 @@ html.dark {
.repo-section-nav {
display: flex;
- align-items: baseline;
+ align-items: center;
gap: 28px;
padding: 0 56px;
font-family: var(--font-mono);
@@ -375,6 +339,19 @@ html.dark {
border-bottom: 1px solid var(--rule);
}
+.repo-position {
+ margin-left: auto;
+ display: inline-flex;
+ align-items: baseline;
+ gap: 6px;
+ font-size: 12px;
+ color: var(--muted);
+ white-space: nowrap;
+}
+
+.repo-position-age { color: var(--muted); }
+.repo-position-path { color: var(--ink); }
+
.section-link {
display: inline-flex;
align-items: baseline;
@@ -708,7 +685,6 @@ pre code[data-lang] {
.tree-path-crumb {
padding: 10px var(--space-xl);
- border-bottom: 1px solid var(--rule2);
font-family: var(--font-mono);
font-size: 14px;
color: var(--muted);
@@ -791,7 +767,6 @@ pre code[data-lang] {
.tree-commit-strip {
padding: 10px var(--space-xl);
- border-bottom: 1px solid var(--rule2);
font-family: var(--font-mono);
font-size: 12.5px;
display: flex;
diff --git a/quire-server/templates/_repo_section_nav.html b/quire-server/templates/_repo_section_nav.html
index d473dbe..f8ada14 100644
--- a/quire-server/templates/_repo_section_nav.html
+++ b/quire-server/templates/_repo_section_nav.html
@@ -1,8 +1,6 @@
-<nav class="repo-section-nav">
- <a class="section-link {% if active_section == "overview" %}section-link--active{% endif %}" href="/{{ repo }}">overview</a>
- <a class="section-link {% if active_section == "tree" %}section-link--active{% endif %}" href="/{{ repo }}/tree">tree</a>
- <a class="section-link {% if active_section == "log" %}section-link--active{% endif %}" href="/{{ repo }}/log">log</a>
- <a class="section-link {% if active_section == "bookmarks" %}section-link--active{% endif %}" href="/{{ repo }}/bookmarks">bookmarks{% if !bookmarks.is_empty() %} <span class="section-count">{{ bookmarks.len() }}</span>{% endif %}</a>
- <a class="section-link {% if active_section == "tags" %}section-link--active{% endif %}" href="/{{ repo }}/tags">tags{% if !tags.is_empty() %} <span class="section-count">{{ tags.len() }}</span>{% endif %}</a>
- <a class="section-link {% if active_section == "ci" %}section-link--active{% endif %}" href="/{{ repo }}/ci">ci</a>
-</nav>
+<a class="section-link {% if active_section == "overview" %}section-link--active{% endif %}" href="/{{ repo }}">overview</a>
+<a class="section-link {% if active_section == "tree" %}section-link--active{% endif %}" href="/{{ repo }}/tree">tree</a>
+<a class="section-link {% if active_section == "log" %}section-link--active{% endif %}" href="/{{ repo }}/log">log</a>
+<a class="section-link {% if active_section == "bookmarks" %}section-link--active{% endif %}" href="/{{ repo }}/bookmarks">bookmarks{% if !bookmarks.is_empty() %} <span class="section-count">{{ bookmarks.len() }}</span>{% endif %}</a>
+<a class="section-link {% if active_section == "tags" %}section-link--active{% endif %}" href="/{{ repo }}/tags">tags{% if !tags.is_empty() %} <span class="section-count">{{ tags.len() }}</span>{% endif %}</a>
+<a class="section-link {% if active_section == "ci" %}section-link--active{% endif %}" href="/{{ repo }}/ci">ci</a>
diff --git a/quire-server/templates/ci/run_detail.html b/quire-server/templates/ci/run_detail.html
index ef736f6..fdc7797 100644
--- a/quire-server/templates/ci/run_detail.html
+++ b/quire-server/templates/ci/run_detail.html
@@ -7,7 +7,9 @@
{% endblock %}
{% block fullpage %}
-{% include "_repo_section_nav.html" %}
+<nav class="repo-section-nav">
+ {% include "_repo_section_nav.html" %}
+</nav>
<main class="page-main">
<div class="ci-meta">
<div class="ci-meta-primary">
diff --git a/quire-server/templates/ci/run_list.html b/quire-server/templates/ci/run_list.html
index c6741ac..b3d6226 100644
--- a/quire-server/templates/ci/run_list.html
+++ b/quire-server/templates/ci/run_list.html
@@ -7,7 +7,9 @@
{% endblock %}
{% block fullpage %}
-{% include "_repo_section_nav.html" %}
+<nav class="repo-section-nav">
+ {% include "_repo_section_nav.html" %}
+</nav>
<main class="page-main">
<h2 class="ci-heading">ci runs</h2>
<table class="ci-table">
diff --git a/quire-server/templates/repo_home.html b/quire-server/templates/repo_home.html
index 64bddc3..aa250ab 100644
--- a/quire-server/templates/repo_home.html
+++ b/quire-server/templates/repo_home.html
@@ -3,54 +3,35 @@
{% block title %}{{ repo }}{% endblock %}
{% block nav %}
-<nav class="page-nav">
- <div class="nav-bar">
- <a class="nav-wordmark" href="/" aria-label="quire home">
- <svg class="q-mark" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
- <rect x="2" y="2" width="12" height="12" rx="1.2" fill="none" stroke="currentColor" stroke-width="1.2"/>
- <line x1="4.5" y1="6" x2="11.5" y2="6" stroke="currentColor" stroke-width="0.8"/>
- <line x1="4.5" y1="8" x2="11.5" y2="8" stroke="currentColor" stroke-width="0.8"/>
- <line x1="4.5" y1="10" x2="9" y2="10" stroke="currentColor" stroke-width="0.8"/>
- <circle cx="11" cy="11" r="3" fill="none" stroke="currentColor" stroke-width="0.8" stroke-dasharray="1.2 1.2" opacity="0.35"/>
- </svg>
- <span class="nav-wordmark-text">quire</span>
- </a>
- <span class="sep">/</span>
- <span class="nav-repo">{{ repo }}</span>
- </div>
-</nav>
+{% include "_nav.html" %}
{% endblock %}
{% block fullpage %}
-{# ── Repo identity band ─────────────────────────────────────── #}
-<header class="repo-header">
- <div class="repo-meta-row">
- {% if let Some(h) = head %}
- <span class="repo-meta-item">
- <span class="bookmark-glyph">※</span>
- <span class="bookmark-name">{{ h.bookmark }}</span>
- <span class="repo-meta-sep">→</span>
- <a class="change-id" href="/{{ repo }}/log" title="commit {{ h.sha_short() }}">
- <span class="change-head">{{ h.change_head() }}</span><span class="change-tail">{{ h.change_tail() }}</span>
- </a>
- <span class="commit-id-secondary">{{ h.sha_short() }}</span>
- </span>
- <span class="repo-meta-dot">·</span>
- <span class="repo-meta-item">updated <span class="repo-meta-value">{{ h.age }}</span></span>
+{# ── Section nav + position token ───────────────────────────── #}
+<nav class="repo-section-nav">
+ {% include "_repo_section_nav.html" %}
+ {% if let Some(h) = head %}
+ <span class="repo-position">
+ <span class="bookmark-glyph">※</span>
+ <span class="bookmark-name">{{ h.bookmark }}</span>
+ <span class="repo-meta-sep">→</span>
+ <a class="change-id" href="/{{ repo }}/log" title="commit {{ h.sha_short() }}">
+ <span class="change-head">{{ h.change_head() }}</span><span class="change-tail">{{ h.change_tail() }}</span>
+ </a>
+ <span class="commit-id-secondary">{{ h.sha_short() }}</span>
<span class="repo-meta-dot">·</span>
- {% endif %}
+ <span class="repo-position-age">{{ h.age }}</span>
{% if !recent_runs.is_empty() %}
- <span class="repo-meta-item ci-inline">
+ <span class="repo-meta-dot">·</span>
+ <span class="ci-inline">
<span class="ci-status-dot {{ self.latest_ci_state_class() }}"></span>
- ci {{ self.latest_ci_state() }}
+ <span>ci {{ self.latest_ci_state() }}</span>
</span>
{% endif %}
- </div>
-</header>
-
-{# ── Section nav ────────────────────────────────────────────── #}
-{% include "_repo_section_nav.html" %}
+ </span>
+ {% endif %}
+</nav>
{# ── Two-column body ─────────────────────────────────────────── #}
<div class="repo-body">
diff --git a/quire-server/templates/tree.html b/quire-server/templates/tree.html
index 69e7bec..2e80c54 100644
--- a/quire-server/templates/tree.html
+++ b/quire-server/templates/tree.html
@@ -8,48 +8,22 @@
{% block fullpage %}
-{# ── Identity band ──────────────────────────────────────────────── #}
-<header class="repo-header">
- <div class="repo-meta-row">
- <span class="repo-meta-item">
- <span class="bookmark-glyph">※</span>
- <span class="bookmark-name">{{ bookmark }}</span>
- <span class="repo-meta-sep">→</span>
- <span class="change-id" title="{{ sha_short }}">
- <span class="change-head">{{ self.sha_head() }}</span><span class="change-tail">{{ self.sha_tail() }}</span>
- </span>
+{# ── Section nav + position token ───────────────────────────────── #}
+<nav class="repo-section-nav">
+ {% include "_repo_section_nav.html" %}
+ <span class="repo-position">
+ <span class="bookmark-glyph">※</span>
+ <span class="bookmark-name">{{ bookmark }}</span>
+ <span class="repo-meta-sep">→</span>
+ <span class="change-id" title="{{ sha_short }}">
+ <span class="change-head">{{ self.sha_head() }}</span><span class="change-tail">{{ self.sha_tail() }}</span>
</span>
- </div>
-</header>
-
-{# ── Section nav ────────────────────────────────────────────────── #}
-{% include "_repo_section_nav.html" %}
-
-{# ── Path breadcrumb (sub-directories only) ─────────────────────── #}
-{% if !path.is_empty() %}
-<div class="tree-path-crumb">
- {% for (label, href) in self.path_parts() %}
- {% if let Some(url) = href %}
- <a class="tree-breadcrumb-seg tree-breadcrumb-link" href="{{ url }}">{{ label }}</a>
- {% else %}
- <span class="tree-breadcrumb-seg">{{ label }}</span>
- {% endif %}
- {% if !loop.last %}<span class="tree-breadcrumb-sep">/</span>{% endif %}
- {% endfor %}
-</div>
-{% endif %}
-
-{# ── Latest-commit-on-this-path strip ───────────────────────────── #}
-{% if let Some(hc) = head_commit %}
-<div class="tree-commit-strip">
- <a class="change-id tree-commit-id" href="/{{ repo }}/log">
- <span class="change-head">{{ hc.sha_head() }}</span><span class="change-tail">{{ hc.sha_tail() }}</span>
- </a>
- <span class="tree-commit-desc">{{ hc.description }}</span>
- <span class="tree-commit-author">{{ hc.author }}</span>
- <span class="tree-commit-age">{{ hc.age }}</span>
-</div>
-{% endif %}
+ {% if !path.is_empty() %}
+ <span class="repo-meta-dot">·</span>
+ <span class="repo-position-path">{{ path }}</span>
+ {% endif %}
+ </span>
+</nav>
{# ── Two-column body ─────────────────────────────────────────────── #}
<div class="tree-body">