fix(scm): seat the History chevron on the change groups' column

The History header now draws its chevron in the change groups' own box
and size, so its title starts where Staged Changes and Untracked do.
Folded, the header drops to 24px with even padding instead of the
expanded section's taller band.
This commit is contained in:
l0ng-ai
2026-09-27 09:16:55 +08:00
parent 3269f5dd7d
commit f03d20d1ea
2 changed files with 34 additions and 17 deletions
+33 -16
View File
@@ -63,6 +63,7 @@ use crate::ui::app::{CONTENT_INSET, Tty7App};
use crate::ui::i18n::{L10nKey, t};
use crate::ui::presets::{ActiveLanes, LANE_SLOTS, Lanes};
use crate::ui::right_panel::{META, META_MONO, ROW_INSET, TEXT, TEXT_INSET, info_chip};
use crate::ui::scm::panel::GROUP_CHEVRON;
use crate::ui::scm::path::{elide_middle, relative_time};
use crate::ui::scm::state::RepoKey;
@@ -100,6 +101,12 @@ const GRAPH_WINDOW_MARGIN: usize = 4;
/// the section starts, and it wants more air than a row of it.
const GRAPH_HEADER_H: f32 = 32.;
/// The header's height while the section is folded. With no rows under it
/// the bar is a single line at the window's foot, and the expanded header's
/// band plus its padding made a strip twice the height of a group header for
/// one word of content.
const GRAPH_HEADER_FOLDED_H: f32 = 24.;
/// The header's controls: the filter tile and the scope picker beside it.
///
/// An 18px square with a 12px glyph, sized against the [`META`] title beside
@@ -613,14 +620,18 @@ impl Tty7App {
// section of its own. It is also the last thing in the window, so
// it takes some air under it: flush against the bottom edge it
// sat in the window's rounded corner like a clipped row.
//
// The same air on both sides, though, not the expanded section's
// 4/12: that bottom pad is room under a scrolled list's last row,
// and under a lone title it left the bar bottom-heavy — the title
// hugging the rule with a dead band beneath it.
return Some(
div()
.flex_none()
.pt(px(GRAPH_PAD_TOP))
.pb(px(GRAPH_PAD_BOTTOM))
.py(px(GRAPH_PAD_TOP))
.border_t_1()
.border_color(cx.theme().border)
.child(self.graph_header(repo, None, cx))
.child(self.graph_header(repo, None, GRAPH_HEADER_FOLDED_H, cx))
.into_any_element(),
);
}
@@ -633,7 +644,7 @@ impl Tty7App {
let height = self.scm.graph.height.get().clamp(GRAPH_H_MIN, ceiling);
let page = self.scm.graph.page.clone();
let header = self.graph_header(repo, page.as_deref(), cx);
let header = self.graph_header(repo, page.as_deref(), GRAPH_HEADER_H, cx);
let search = self.graph_search(cx);
let naming = self.graph_naming_row(repo, cx);
let query = self.graph_query(cx);
@@ -1286,6 +1297,7 @@ impl Tty7App {
&self,
repo: &RepoKey,
page: Option<&CommitPage>,
height: f32,
cx: &mut Context<Self>,
) -> AnyElement {
let expanded = self.scm.graph.expanded;
@@ -1300,7 +1312,7 @@ impl Tty7App {
.flex_none()
.items_center()
.gap(px(GRAPH_HEADER_GAP))
.h(px(GRAPH_HEADER_H))
.h(px(height))
.pl(px(TEXT_INSET))
.pr(px(TEXT_INSET - GRAPH_SCOPE_PAD))
.child(
@@ -1312,17 +1324,22 @@ impl Tty7App {
.min_w(px(0.))
.cursor_pointer()
.child(
// A hair under the title it opens: the chevron is a
// mark, not a word, and at the label's own size it
// starts competing with it for the corner. `.xsmall()`
// is that size exactly, which is why this one is still
// a number.
Icon::new(match expanded {
true => IconName::ChevronDown,
false => IconName::ChevronRight,
})
.size(px(11.))
.text_color(muted),
// The change groups' own chevron, in their own box: the
// same mark on the same text column, so "History" starts
// where "Staged Changes" and "Untracked" do above it.
div()
.flex_none()
.w(px(GROUP_CHEVRON))
.flex()
.justify_center()
.text_color(muted)
.child(
Icon::new(match expanded {
true => IconName::ChevronDown,
false => IconName::ChevronRight,
})
.size(px(GROUP_CHEVRON)),
),
)
.child(
div()
+1 -1
View File
@@ -55,7 +55,7 @@ const BADGE_W: f32 = 10.;
/// The group header's disclosure chevron: an 8px mark in an 8px box, so the
/// label after it lands `8 + 6` = 14px past the text column.
const GROUP_CHEVRON: f32 = 8.;
pub(crate) const GROUP_CHEVRON: f32 = 8.;
const _: () = assert!(GROUP_CHEVRON <= BADGE_W && BADGE_W - GROUP_CHEVRON <= 2.);
/// The key context the message box installs, and the one `ScmCommit` is