Update tab styling.
This commit is contained in:
+8
-5
@@ -1998,14 +1998,17 @@ fn applySidebarCollapsed(self: *Window, collapsed: bool) void {
|
||||
for (self.tabs.items) |tab| self.applyRowCollapsed(tab);
|
||||
}
|
||||
|
||||
/// One row's share of the collapse: everything but the emoji (or kind icon)
|
||||
/// goes. The status dot goes too — the bar down the row's leading edge carries
|
||||
/// the state at this width (with a wash behind it for the states that have one),
|
||||
/// and it was designed to be the glanceable half of the pair anyway.
|
||||
/// One row's share of the collapse: the title and the close button go, the
|
||||
/// emoji (or kind icon) and the status dot stay.
|
||||
///
|
||||
/// The dot used to go as well, back when every state also drew a bar down the
|
||||
/// row's leading edge and that bar could carry the state on its own. Only
|
||||
/// "finished" draws one now, so at this width the dot is the whole signal for
|
||||
/// the other three — and a collapsed sidebar is exactly where you are relying on
|
||||
/// a glance rather than on reading anything.
|
||||
fn applyRowCollapsed(self: *Window, tab: *Tab) void {
|
||||
const shown: c_int = @intFromBool(!self.sidebar_collapsed);
|
||||
tab.label.as(gtk.Widget).setVisible(shown);
|
||||
tab.dot.as(gtk.Widget).setVisible(shown);
|
||||
tab.close.as(gtk.Widget).setVisible(shown);
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -184,6 +184,7 @@ pub const Key = enum {
|
||||
accent_muted,
|
||||
|
||||
// ---- status ----
|
||||
busy,
|
||||
ok,
|
||||
warn,
|
||||
err,
|
||||
@@ -226,7 +227,7 @@ pub const Key = enum {
|
||||
.text, .text_dim, .text_faint => .text,
|
||||
.row_hover, .row_selected => .rows,
|
||||
.accent, .accent_strong, .accent_muted => .accents,
|
||||
.ok, .warn, .err => .states,
|
||||
.busy, .ok, .warn, .err => .states,
|
||||
.term_bg, .term_fg, .term_cursor, .term_selection_bg, .term_selection_fg => .terminal,
|
||||
else => .ansi,
|
||||
};
|
||||
@@ -289,6 +290,7 @@ pub const Key = enum {
|
||||
.accent_strong => "Accent, strong",
|
||||
.accent_muted => "Accent, muted",
|
||||
|
||||
.busy => "Working",
|
||||
.ok => "Finished",
|
||||
.warn => "Waiting on you",
|
||||
.err => "Failed",
|
||||
@@ -329,6 +331,7 @@ pub const Key = enum {
|
||||
.text_faint => "Things that are labeled rather than read, like the title of a pane you aren't in",
|
||||
.accent_strong => "Small marks that have to stay legible on a surface: icons, dots, a row's state bar",
|
||||
.accent_muted => "Washes and the border of the focused pane",
|
||||
.busy => "A pane that is still working. Its own color rather than the accent, so it stays distinct from \"finished\" under any accent",
|
||||
.ok => "A pane that finished and hasn't been looked at",
|
||||
.warn => "A pane waiting for you to answer something",
|
||||
.err => "A pane that failed",
|
||||
@@ -493,9 +496,15 @@ const dark: Table = .initDefault(unset, .{
|
||||
.accent_strong = h("#6191f3"),
|
||||
.accent_muted = h("#2f5296"),
|
||||
|
||||
// The three states that are news. Kept away from the accent on purpose: the
|
||||
// accent means "here" and these mean "something happened", and a sidebar
|
||||
// where those are the same color answers neither question.
|
||||
// The states. Kept away from the accent on purpose: the accent means "here"
|
||||
// and these mean "something happened", and a sidebar where those are the
|
||||
// same color answers neither question.
|
||||
//
|
||||
// `busy` starts out where the strong accent does, because that is the blue
|
||||
// this palette was built around — but it is a key of its own so that an
|
||||
// accent moved somewhere else (a green one especially) cannot land it on top
|
||||
// of `ok`, which is the one distinction the dots exist to make.
|
||||
.busy = h("#6191f3"),
|
||||
.ok = h("#3ecf8e"),
|
||||
.warn = h("#f0b849"),
|
||||
.err = h("#f2717b"),
|
||||
@@ -534,6 +543,7 @@ const light: Table = .initDefault(unset, .{
|
||||
.accent_strong = h("#1851b4"),
|
||||
.accent_muted = h("#a9c4f7"),
|
||||
|
||||
.busy = h("#1851b4"),
|
||||
.ok = h("#12805a"),
|
||||
.warn = h("#8a5a00"),
|
||||
.err = h("#c23b47"),
|
||||
|
||||
+34
-33
@@ -191,54 +191,54 @@ button.playpen-header-button:hover,
|
||||
|
||||
/* State on the row itself, not just on its dot.
|
||||
|
||||
A bar down the leading edge, and behind the row a wash of the same color for
|
||||
the two states that actually want you. The dot says what a row is doing once
|
||||
you are reading it; these are what let you sweep a sidebar of a dozen tabs
|
||||
and land on the one that wants you without reading any of them.
|
||||
One bar and two washes, and that is the whole vocabulary. Finished gets the
|
||||
bar down its leading edge; the two states that actually want you get a wash
|
||||
of their own color behind the row. The dot says what a row is doing once you
|
||||
are reading it; these are what let you sweep a sidebar of a dozen tabs and
|
||||
land on the one you care about without reading any of them.
|
||||
|
||||
The bar is an inset shadow rather than a real border because a border takes
|
||||
part in layout: 3px of it would shove every label sideways as a tab changed
|
||||
state, and a sidebar that twitches is worse than one that is hard to read.
|
||||
Only finished carries a bar. Every state used to have one, drawn as an inset
|
||||
shadow, and a shadow is clipped to the row's 8px corners: what landed was a
|
||||
short bar with a curl at each end, four rows deep in slightly different
|
||||
colors. Read as ornament rather than as signal, so it is gone from everything
|
||||
but the one state whose bar is a plain rectangle.
|
||||
|
||||
These come after the :selected rules deliberately. Equal specificity means
|
||||
source order decides, and a state outranks "this is the tab you are on". */
|
||||
|
||||
/* No wash for working. It is the most common state by far, and a sidebar where
|
||||
half the rows are tinted all afternoon teaches you to stop looking. */
|
||||
.playpen-list > row.playpen-attn-busy {
|
||||
box-shadow: inset 3px 0 0 @pp_accent_strong;
|
||||
}
|
||||
/* Working is the dot alone. It is the most common state by far, and a sidebar
|
||||
where half the rows are marked all afternoon teaches you to stop looking. */
|
||||
|
||||
/* No wash for finished either, for a different reason: a tinted row is what
|
||||
selection looks like in this list, so washing the finished ones left "the tab
|
||||
you are on" and "the tab that just finished" saying the same thing. The dot
|
||||
and a bar are enough — nothing here is waiting on you.
|
||||
/* No wash for finished, for a different reason: a tinted row is what selection
|
||||
looks like in this list, so washing the finished ones left "the tab you are
|
||||
on" and "the tab that just finished" saying the same thing. The dot and the
|
||||
bar are enough — nothing here is waiting on you.
|
||||
|
||||
The bar is a background image rather than the inset shadow the other states
|
||||
use, because a shadow is clipped to the row's 8px corners and comes out
|
||||
tapered at both ends. Kept short enough to clear those corners entirely, so
|
||||
what lands is a plain rectangle. */
|
||||
The bar is a background image rather than an inset shadow precisely because
|
||||
it is not clipped to the corners, so it stays a rectangle at any height. Tall
|
||||
enough now to read as a deliberate mark rather than a stray pixel, and still
|
||||
short of the row's full height so it reads as pinned to the middle of the
|
||||
row. */
|
||||
.playpen-list > row.playpen-attn-done {
|
||||
background-image: linear-gradient(@pp_ok, @pp_ok);
|
||||
background-size: 3px 12px;
|
||||
background-size: 3px 18px;
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.playpen-list > row.playpen-attn-input {
|
||||
box-shadow: inset 3px 0 0 @pp_warn;
|
||||
background-color: alpha(@pp_warn, 0.14);
|
||||
}
|
||||
|
||||
.playpen-list > row.playpen-attn-failed {
|
||||
box-shadow: inset 3px 0 0 @pp_err;
|
||||
background-color: alpha(@pp_err, 0.14);
|
||||
}
|
||||
|
||||
/* The current row keeps its own background: the wash and the selection would
|
||||
otherwise blend into a color that reads as neither. The bar survives, which
|
||||
is the part that carries the state. Done is absent because it no longer has a
|
||||
wash to suppress. */
|
||||
otherwise blend into a color that reads as neither, and the dot is left to
|
||||
carry the state on its own — which on the row you are already looking at is
|
||||
enough. Done is absent because it has no wash to suppress, only a bar, and a
|
||||
bar and a selection sit together fine. */
|
||||
.playpen-list > row:selected.playpen-attn-input,
|
||||
.playpen-list > row:selected.playpen-attn-failed {
|
||||
background-color: @pp_row_selected;
|
||||
@@ -256,7 +256,6 @@ button.playpen-header-button:hover,
|
||||
opacity: 0.65;
|
||||
background-color: alpha(@pp_accent_strong, 0.18);
|
||||
background-image: none;
|
||||
box-shadow: inset 3px 0 0 @pp_accent_strong;
|
||||
}
|
||||
|
||||
/* The copy of that row traveling with the pointer, which GTK draws into a
|
||||
@@ -384,16 +383,18 @@ dnd.playpen-tab-drag {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Working: the same accent as an active pane's border, so "busy" reads as
|
||||
ordinary activity rather than something gone wrong. */
|
||||
/* Working: blue, and pulsing. Its own palette color rather than the accent —
|
||||
the accent is whatever the theme is built around, and a green one put "still
|
||||
working" in the same color as "finished", which is the one distinction this
|
||||
whole indicator exists to make. The pulse carries the rest of it: a mark that
|
||||
moves reads as something in progress before you have registered its color. */
|
||||
.playpen-status-busy {
|
||||
color: @pp_accent_strong;
|
||||
color: @pp_busy;
|
||||
animation: playpen-pulse 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Finished while you were elsewhere. Green rather than the accent so it is
|
||||
distinct from still-working at a glance, which is the one distinction this
|
||||
whole indicator exists to make. */
|
||||
/* Finished while you were elsewhere. Green, and still — the dot that has
|
||||
stopped moving is the one that has stopped working. */
|
||||
.playpen-status-done {
|
||||
color: @pp_ok;
|
||||
}
|
||||
|
||||
+12
-7
@@ -270,6 +270,7 @@ const dark_stops: Stops = .initDefault(inherited, .{
|
||||
.accent_strong = accent(0.0742, 0.797),
|
||||
.accent_muted = accent(-0.1450, 0.610),
|
||||
|
||||
.busy = named(0.6682, 0.1549, 263.2),
|
||||
.ok = named(0.7624, 0.1544, 159.4),
|
||||
.warn = named(0.8142, 0.1403, 81.3),
|
||||
.err = named(0.7043, 0.1588, 17.3),
|
||||
@@ -324,6 +325,7 @@ const light_stops: Stops = .initDefault(inherited, .{
|
||||
.accent_strong = accent(-0.1040, 0.812),
|
||||
.accent_muted = accent(0.2529, 0.377),
|
||||
|
||||
.busy = named(0.4613, 0.1680, 260.8),
|
||||
.ok = named(0.5329, 0.1101, 163.1),
|
||||
.warn = named(0.5078, 0.1080, 73.3),
|
||||
.err = named(0.5530, 0.1708, 19.9),
|
||||
@@ -527,12 +529,15 @@ test "a gray base makes a gray theme, and keeps the status colors apart" {
|
||||
try testing.expect(oklab.fromRgb(derive(key, scheme, tint)).c < 0.01);
|
||||
}
|
||||
|
||||
// The three states still have to be three states.
|
||||
const ok = derive(.ok, scheme, tint);
|
||||
const warn = derive(.warn, scheme, tint);
|
||||
const err = derive(.err, scheme, tint);
|
||||
try testing.expect(drift(ok, warn) > 20);
|
||||
try testing.expect(drift(warn, err) > 20);
|
||||
try testing.expect(drift(ok, err) > 20);
|
||||
// The four states still have to be four states. `busy` against `ok` is
|
||||
// the pair that matters most — a working tab and a finished one are what
|
||||
// the dots are read for — but a gray theme is where any two of these
|
||||
// would collapse if they were going to.
|
||||
const states = [_]Key{ .busy, .ok, .warn, .err };
|
||||
for (states, 0..) |a, i| {
|
||||
for (states[i + 1 ..]) |b| {
|
||||
try testing.expect(drift(derive(a, scheme, tint), derive(b, scheme, tint)) > 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user