fix(panel): redraw the right panel's tab icons and put the tree glyph on the tile ladder (#578)

* fix(panel): redraw the right panel's three tab icons

The tiles render at 13px (`TILE_GLYPH`), and at that size the set had
three problems, none of them about style:

- `info` and `folder-closed` were both a rounded body split by a
  horizontal rule at nearly the same proportions, so the first and third
  tile could only be told apart by a notch a pixel and a half wide.
- `git-branch` drew its three nodes as filled r=2.5 discs — 2.7px across
  at render size — which buried the 2.1 strokes between them and left
  the glyph reading as three dots.
- The interior detail was too dense to survive: `info` carried two rules
  4.8 units apart and `folder-closed` a divider 3.2 units below its
  front edge, both under 2.6px once rendered.

Same three metaphors, same 2.1 pen, same rounded joins — only the
geometry moves. The nodes go hollow so the branch is drawn with one pen
rather than two. The crowded interior rules go, which leaves the folder
a clean body and makes the notch the thing that separates it from
`info`, rather than a second rule at a slightly different height. And
each mark grows into the height `panel-right` already occupies beside
them: the three had the width of that box and sat two units short of its
height, which on a row of tiles reads as three smaller icons rather than
as three different ones.

Measured as rendered ink, stroke included, on the 24 grid:

| glyph                               | before      | after       |
| ----------------------------------- | ----------- | ----------- |
| `panel-right` (unchanged reference) | 19.3 x 19.3 | —           |
| `info`                              | 19.3 x 17.3 | 19.3 x 18.1 |
| `folder-closed`                     | 19.3 x 17.3 | 19.3 x 17.7 |
| `git-branch`                        | 18.5 x 17.3 | 18.3 x 18.9 |

All three stay centred on 12, 12.

* fix(files): size the tree row's glyph off the tile ladder, not the rem one

Glyphs in this window come from the pixel ladder in `app.rs` —
`TILE_GLYPH` 13 for a chrome tile, `TILE_GLYPH_XS` 11 for the tiles a row
reveals on hover — while text comes from the rem ramp. The file tree's
leading folder/file mark was the one place drawing its size from
gpui-component's rem sizes instead, and those two systems cannot meet:
at the default `ui_font_size` of 16 the rem ladder offers `xsmall` 12 and
`small` 14 and nothing in between, so the mark was always a step under
the tab tiles above it — a speck beside a 14px name — or a step over
them, which is a row of content outsizing the navigation that owns it.

`ROW_GLYPH` is that size named once, in pixels, next to the panel's type
ramp and defined as the tab tile's own glyph, so the two now agree by
construction rather than by coincidence.

* fix(icons): put the tree's collapsed folder on the set's box

`folder.svg` is the one folder the set never squared up. It inks
19.9 x 16.1 where every other mark in the row is 19.3 wide, because its
top edge overshoots the box by 0.6 on the right — which also leaves the
whole glyph 0.3 off-centre that way, and 0.2 low.

Nothing showed while the tree drew it a step under the chrome. It is on
`ROW_GLYPH` now, the same 13px as the Files tab tile above it, and it
swaps in place with `folder-open` — already on the box — every time a
directory opens or closes, so the overhang is a shift in a fixed column
rather than a number in a file.

Same folder, same 2.8 corners, same 1.7 shoulder: the top edge gives
back the 0.6 it overshot and the body takes the 1.2 of height that puts
it on 19.3 x 17.3, centred on 12, 12, which is where `folder-open` and
the rest of the row already are.

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
This commit is contained in:
l0ng-ai
2026-08-13 15:00:24 +08:00
committed by GitHub
co-authored by l0ng-ai
parent 3c5f14f71c
commit bed3c856ed
6 changed files with 20 additions and 7 deletions
+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><path d="M3.4 7.2A2.8 2.8 0 0 1 6.2 4.4h3a2.8 2.8 0 0 1 2.24 1.12l.74.99a1.7 1.7 0 0 0 1.36.69h4.26a2.8 2.8 0 0 1 2.8 2.8v6.8a2.8 2.8 0 0 1-2.8 2.8H6.2a2.8 2.8 0 0 1-2.8-2.8Z"/><path d="M5.6 10.4h12.8"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><path d="M3.4 7A2.8 2.8 0 0 1 6.2 4.2h2.9a2.8 2.8 0 0 1 2.24 1.12l.72.96a1.7 1.7 0 0 0 1.34.92H17.8a2.8 2.8 0 0 1 2.8 2.8V17a2.8 2.8 0 0 1-2.8 2.8H6.2a2.8 2.8 0 0 1-2.8-2.8Z"/></svg>

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 366 B

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><path d="M3.4 8A2.8 2.8 0 0 1 6.2 5.2h3a2.8 2.8 0 0 1 2.24 1.12l.74.99a1.7 1.7 0 0 0 1.36.69h4.86a2.8 2.8 0 0 1 2.8 2.8v5.6a2.8 2.8 0 0 1-2.8 2.8H6.2a2.8 2.8 0 0 1-2.8-2.8Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><path d="M3.4 7.2A2.8 2.8 0 0 1 6.2 4.4h3a2.8 2.8 0 0 1 2.24 1.12l.74.99a1.7 1.7 0 0 0 1.36.69h4.26a2.8 2.8 0 0 1 2.8 2.8v6.8a2.8 2.8 0 0 1-2.8 2.8H6.2a2.8 2.8 0 0 1-2.8-2.8Z"/></svg>

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 367 B

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><path d="M5.3 8.35v7.3"/><path d="M5.3 12h10.5a3 3 0 0 0 3-3"/><circle cx="5.3" cy="5.85" r="2.5" fill="currentColor" stroke="none"/><circle cx="5.3" cy="18.15" r="2.5" fill="currentColor" stroke="none"/><circle cx="18.8" cy="6.4" r="2.5" fill="currentColor" stroke="none"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><circle cx="6.3" cy="6" r="2.4"/><circle cx="6.3" cy="18" r="2.4"/><circle cx="17.7" cy="6" r="2.4"/><path d="M6.3 8.4v7.2"/><path d="M6.3 12.9h7.2a4.2 4.2 0 0 0 4.2-4.2V8.4"/></svg>

Before

Width:  |  Height:  |  Size: 464 B

After

Width:  |  Height:  |  Size: 366 B

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><rect x="3.4" y="4.4" width="17.2" height="15.2" rx="3.8"/><path d="M3.4 9h17.2"/><path d="M7.2 13.8h9.6"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><rect x="3.4" y="4" width="17.2" height="16" rx="4"/><path d="M3.4 8.7h17.2"/></svg>

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 268 B

+3 -3
View File
@@ -11,7 +11,7 @@ use crate::ui::file_copy;
use crate::ui::host_ops::{ByHost, HostId, HostOps, InFlight, SharedHost, WatchSub};
use crate::ui::host_registry::HostRegistry;
use crate::ui::i18n::{L10nKey, t, t_fmt};
use crate::ui::right_panel::git_badge;
use crate::ui::right_panel::{ROW_GLYPH, git_badge};
use crate::ui::scm::status::{status_color, status_glyph};
use gpui::prelude::*;
use gpui::{
@@ -1798,7 +1798,7 @@ impl Tty7App {
.cursor_pointer()
.when(selected, |d| d.bg(gpui::rgb(sf.selected)))
.when(!selected, |d| d.hover(|s| s.bg(gpui::rgb(sf.hover))))
.child(Icon::new(icon).xsmall().text_color(if is_dir {
.child(Icon::new(icon).size(px(ROW_GLYPH)).text_color(if is_dir {
cx.theme().foreground
} else {
muted
@@ -2081,7 +2081,7 @@ impl gpui::Render for DragGhost {
.border_1()
.border_color(cx.theme().border)
.text_sm()
.child(Icon::new(IconName::File).xsmall())
.child(Icon::new(IconName::File).size(px(ROW_GLYPH)))
.child(SharedString::from(self.name.clone()))
}
}
+13
View File
@@ -46,6 +46,19 @@ pub(crate) const META_MONO: f32 = META - STEP;
/// sidebar's group headings, which are the same thing one panel over.
pub(crate) const HEADING: f32 = 11. * STEP;
/// The leading glyph on a panel row — the file tree's folder and file marks.
///
/// Pixels, not rems, because glyphs in this window are sized off the tile
/// ladder in `app.rs` (`TILE_GLYPH` 13, `TILE_GLYPH_XS` 11) rather than off the
/// text ramp above. A row that reached for gpui-component's rem sizes instead
/// could never agree with the tab tiles it sits under: at the default
/// `ui_font_size` of 16 that ladder offers `xsmall` 12 and `small` 14 and
/// nothing between, so the tree's glyph came out either a step under the
/// chrome — reading as a speck beside a 14px name — or a step over it, which
/// puts a row of content above the navigation that owns it. 13 is the tab
/// tile's own glyph size, so the two agree by construction.
pub(crate) const ROW_GLYPH: f32 = crate::ui::app::TILE_GLYPH;
// The right panel's type ramp: four steps, a point apart, that the Info and
// Source Control tabs both draw from so switching between them does not change
// the apparent size of the panel. The Files tab, in `file_tree.rs`, reaches the