feat: unified bar styling
- semantic tokens (accent/surface/hairline/text-muted) derived from the palette so they follow stylix in light and dark mode - every bar module is a uniform 28px rounded chip; one accent for active state, tints for attention, solid fill only for mail-debt alarm - workspaces as dots with a stretching accent pill - mic/cpu-ram/tray/battery grouped into one chip; cpu/ram as concentric rings with tooltip; clock split into bold time + muted date - stylix provider only sets palette + font; scope its font-size so the bar's own CSS sizes are no longer flattened - drop inline widget styles, 16px tray icons, fix broken menu.css selector
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@ from gi.repository import GLib, Gtk
|
||||
from fabric.notifications import Notifications
|
||||
|
||||
|
||||
tray = SystemTray(name="system-tray", spacing=4)
|
||||
tray = SystemTray(name="system-tray", spacing=2, icon_size=16)
|
||||
get_i3_connection()
|
||||
# Subscribe before the main loop runs so fenster's replayed capture state
|
||||
# (sent right after SUBSCRIBE) is not missed.
|
||||
|
||||
+48
-23
@@ -1,8 +1,10 @@
|
||||
import time
|
||||
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.overlay import Overlay
|
||||
from fabric.widgets.datetime import DateTime
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.utils import invoke_repeater
|
||||
from sims.modules.player import Player, PlayerSmall
|
||||
from sims.modules.battery import Battery
|
||||
from sims.modules.control_center import ControlCenter
|
||||
@@ -55,12 +57,10 @@ class StatusBar(Window):
|
||||
spacing=4,
|
||||
)
|
||||
|
||||
datetime_widget = DateTime(name="date-time", formatters="%d %b - %H:%M")
|
||||
self.date_time = Button(
|
||||
name="date-time-button",
|
||||
child=datetime_widget,
|
||||
child=Clock(),
|
||||
on_clicked=self._on_date_time_clicked,
|
||||
style="background: transparent; border: none; padding: 0; margin: 0; box-shadow: none;",
|
||||
)
|
||||
self.control_center = control_center
|
||||
|
||||
@@ -69,22 +69,21 @@ class StatusBar(Window):
|
||||
self.active_window = FensterActiveWindow(
|
||||
name="active-window",
|
||||
max_length=50,
|
||||
style="font-size: 14px; font-weight: bold;",
|
||||
)
|
||||
|
||||
# CPU/RAM as concentric "activity rings": outer = RAM, inner = CPU.
|
||||
ring = dict(line_width=3, start_angle=-90, end_angle=270,
|
||||
h_align="center", v_align="center")
|
||||
self.ram_progress_bar = CircularProgressBar(
|
||||
name="ram-progress-bar", pie=True, size=24
|
||||
name="ram-progress-bar", size=18, **ring
|
||||
)
|
||||
self.cpu_progress_bar = CircularProgressBar(
|
||||
name="cpu-progress-bar", pie=True, size=24
|
||||
)
|
||||
|
||||
self.progress_label = Label(
|
||||
"", style="margin: 0px 6px 0px 0px; font-size: 12px"
|
||||
name="cpu-progress-bar", size=8, **ring
|
||||
)
|
||||
self.progress_bars_overlay = Overlay(
|
||||
name="system-stats",
|
||||
child=self.ram_progress_bar,
|
||||
overlays=[self.cpu_progress_bar, self.progress_label],
|
||||
overlays=[self.cpu_progress_bar],
|
||||
)
|
||||
self.player = Player()
|
||||
self.player_small = PlayerSmall(monitor=monitor)
|
||||
@@ -110,11 +109,18 @@ class StatusBar(Window):
|
||||
|
||||
self.microphone = MicrophoneWidget()
|
||||
|
||||
# One chip for the ambient system state; attention items (org,
|
||||
# mail, screen share) stay separate so they can light up.
|
||||
status_children = [self.microphone, self.progress_bars_overlay]
|
||||
if self.system_tray:
|
||||
status_children.append(self.system_tray)
|
||||
if self.battery:
|
||||
status_children.append(self.battery)
|
||||
self.status_container = Box(
|
||||
name="widgets-container",
|
||||
spacing=4,
|
||||
spacing=6,
|
||||
orientation="h",
|
||||
children=[self.microphone, self.progress_bars_overlay],
|
||||
children=status_children,
|
||||
)
|
||||
|
||||
end_container_children = []
|
||||
@@ -122,17 +128,11 @@ class StatusBar(Window):
|
||||
if self.org is not None:
|
||||
end_container_children.append(self.org)
|
||||
|
||||
end_container_children.append(self.status_container)
|
||||
if self.system_tray:
|
||||
end_container_children.append(self.system_tray)
|
||||
|
||||
if self.battery:
|
||||
end_container_children.append(self.battery)
|
||||
|
||||
if self.notmuch:
|
||||
end_container_children.append(self.notmuch)
|
||||
|
||||
end_container_children.append(self.capture)
|
||||
end_container_children.append(self.status_container)
|
||||
|
||||
end_container_children.append(self.date_time)
|
||||
|
||||
@@ -155,7 +155,7 @@ class StatusBar(Window):
|
||||
name="sims-inner",
|
||||
start_children=Box(
|
||||
name="start-container",
|
||||
spacing=6,
|
||||
spacing=8,
|
||||
orientation="h",
|
||||
children=start_container_children,
|
||||
),
|
||||
@@ -167,7 +167,7 @@ class StatusBar(Window):
|
||||
),
|
||||
end_children=Box(
|
||||
name="end-container",
|
||||
spacing=4,
|
||||
spacing=6,
|
||||
orientation="h",
|
||||
children=end_container_children,
|
||||
),
|
||||
@@ -218,7 +218,32 @@ class StatusBar(Window):
|
||||
def update_progress_bars(self, service, cpu_percent, memory_percent):
|
||||
self.cpu_progress_bar.value = cpu_percent
|
||||
self.ram_progress_bar.value = memory_percent
|
||||
self.progress_bars_overlay.set_tooltip_text(
|
||||
f"CPU {cpu_percent * 100:.0f}% · RAM {memory_percent * 100:.0f}%"
|
||||
)
|
||||
|
||||
def _on_date_time_clicked(self, _button=None):
|
||||
if self.control_center is not None:
|
||||
self.control_center.toggle()
|
||||
|
||||
|
||||
class Clock(Box):
|
||||
"""Bold time + muted date, e.g. `20:26 Mon 22 Jul`."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._time = Label(name="clock-time")
|
||||
self._date = Label(name="clock-date")
|
||||
super().__init__(
|
||||
name="date-time",
|
||||
orientation="h",
|
||||
spacing=8,
|
||||
children=[self._time, self._date],
|
||||
**kwargs,
|
||||
)
|
||||
invoke_repeater(1000, self._update)
|
||||
|
||||
def _update(self) -> bool:
|
||||
now = time.localtime()
|
||||
self._time.set_label(time.strftime("%H:%M", now))
|
||||
self._date.set_label(time.strftime("%a %d %b", now))
|
||||
return True
|
||||
|
||||
@@ -27,7 +27,6 @@ class MicrophoneWidget(Box):
|
||||
name="microphone-button",
|
||||
child=self.icon_label,
|
||||
on_clicked=self.on_clicked,
|
||||
style="background: transparent; border: none; margin: 0; box-shadow: none;",
|
||||
)
|
||||
self.add(self.button)
|
||||
|
||||
|
||||
+13
-253
@@ -60,58 +60,6 @@ def resolve_colors(mode: str | None = None) -> dict[str, str]:
|
||||
return colors
|
||||
|
||||
|
||||
def is_light(colors: dict[str, str]) -> bool:
|
||||
"""Whether the palette is a light one, judged by base00's relative
|
||||
luminance (so light base schemes work without `variants` too)."""
|
||||
|
||||
def channel(c: int) -> float:
|
||||
c = c / 255
|
||||
return c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4
|
||||
|
||||
hex_bg = colors["base00"].lstrip("#")
|
||||
r, g, b = (channel(int(hex_bg[i : i + 2], 16)) for i in (0, 2, 4))
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.5
|
||||
|
||||
|
||||
# Accent "status pills": (widget selector, child selectors, base16 slot). Later
|
||||
# entries win over earlier ones at equal specificity, mirroring org.css and
|
||||
# notmuch.css (debt state overrides unread, in-progress+next overrides both).
|
||||
ACCENT_PILLS = [
|
||||
("#org-widget.has-in-progress", ("#org-icon", "#org-count"), "base0E"),
|
||||
("#org-widget.has-next", ("#org-icon", "#org-count"), "base0D"),
|
||||
("#org-widget.has-in-progress.has-next", ("#org-icon", "#org-count"), "base0C"),
|
||||
("#notmuch-widget.has-unread", ("#notmuch-icon", "#unread-count"), "base0D"),
|
||||
("#notmuch-widget.debt-warn", ("#notmuch-icon", "#unread-count"), "base09"),
|
||||
("#notmuch-widget.debt-alarm", ("#notmuch-icon", "#unread-count"), "base08"),
|
||||
]
|
||||
|
||||
|
||||
def accent_pill_css(colors: dict[str, str]) -> str:
|
||||
"""Org/notmuch alert pills. Dark palettes get a solid accent fill with
|
||||
background-colored text (pastel accents carry that well); light palettes
|
||||
get a pale accent tint with accent-colored text, since a solid fill of a
|
||||
light scheme's saturated accents is far louder than the rest of the bar."""
|
||||
light = is_light(colors)
|
||||
rules = []
|
||||
for widget, children, slot in ACCENT_PILLS:
|
||||
accent = f"#{colors[slot]}"
|
||||
if light:
|
||||
bg, hover_bg, fg = (
|
||||
f"alpha({accent}, 0.18)",
|
||||
f"alpha({accent}, 0.30)",
|
||||
accent,
|
||||
)
|
||||
else:
|
||||
bg, hover_bg, fg = accent, f"shade({accent}, 1.12)", f"#{colors['base00']}"
|
||||
child_sel = ",\n".join(f"{widget} {c}" for c in children)
|
||||
rules.append(
|
||||
f"{widget} {{\n background-color: {bg};\n}}\n\n"
|
||||
f"{widget}:hover {{\n background-color: {hover_bg};\n}}\n\n"
|
||||
f"{child_sel} {{\n color: {fg};\n}}\n"
|
||||
)
|
||||
return "\n".join(rules)
|
||||
|
||||
|
||||
def generate_stylix_css(mode: str | None = None) -> str | None:
|
||||
"""Generate CSS using Stylix colors (for `mode`, if variants are set)"""
|
||||
if not STYLIX.get("enable", False):
|
||||
@@ -144,129 +92,27 @@ def generate_stylix_css(mode: str | None = None) -> str | None:
|
||||
|
||||
{palette}
|
||||
|
||||
/* Apply Stylix font */
|
||||
/* Apply Stylix font. This provider sits in front of main.css and GTK lets
|
||||
the first provider that sets a property win regardless of selector
|
||||
specificity, so a blanket `* {{ font-size }}` here would flatten every
|
||||
size in the bar's own CSS. The bar (window#sims) therefore only gets the
|
||||
size on its toplevel and inherits it; other windows keep the blanket
|
||||
rule they were designed against. */
|
||||
* {{
|
||||
font-family: "{font_family}", sans-serif;
|
||||
}}
|
||||
|
||||
window,
|
||||
tooltip {{
|
||||
font-size: {font_size}px;
|
||||
}}
|
||||
|
||||
/* Bar styling */
|
||||
#sims-inner {{
|
||||
padding: 4px;
|
||||
border-bottom: solid 2px;
|
||||
border-color: #{colors["base02"]};
|
||||
background-color: #{colors["base00"]};
|
||||
border-radius: 0;
|
||||
transition: border-radius 200ms ease;
|
||||
}}
|
||||
|
||||
#sims-inner.rounded-bottom {{
|
||||
border-radius: 0 0 28px 28px;
|
||||
}}
|
||||
|
||||
#center-container {{
|
||||
color: #{colors["base05"]};
|
||||
}}
|
||||
|
||||
.active-window {{
|
||||
color: #{colors["base05"]};
|
||||
font-weight: bold;
|
||||
}}
|
||||
|
||||
/* Battery */
|
||||
#battery-widget {{
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
}}
|
||||
|
||||
#bat-icon {{
|
||||
color: #{colors["base0D"]};
|
||||
margin-right: 2px;
|
||||
}}
|
||||
|
||||
#bat-label {{
|
||||
color: #{colors["base05"]};
|
||||
window:not(#sims) * {{
|
||||
font-size: {font_size}px;
|
||||
}}
|
||||
|
||||
#bat-label.battery-low {{
|
||||
color: #{colors["base08"]};
|
||||
font-weight: bold;
|
||||
}}
|
||||
|
||||
/* Progress bars */
|
||||
#cpu-progress-bar,
|
||||
#ram-progress-bar,
|
||||
#volume-progress-bar {{
|
||||
color: transparent;
|
||||
background-color: transparent;
|
||||
}}
|
||||
|
||||
#cpu-progress-bar {{
|
||||
border: solid 0px alpha(#{colors["base0E"]}, 0.8);
|
||||
}}
|
||||
|
||||
#ram-progress-bar,
|
||||
#volume-progress-bar {{
|
||||
border: solid 0px #{colors["base0D"]};
|
||||
}}
|
||||
|
||||
/* Widgets container */
|
||||
#widgets-container {{
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 2px;
|
||||
border-radius: 16px;
|
||||
}}
|
||||
|
||||
/* NixOS label */
|
||||
#nixos-label {{
|
||||
color: #{colors["base0D"]};
|
||||
font-size: 20px;
|
||||
}}
|
||||
|
||||
/* CPU/RAM pies: the RAM pie (underneath) draws a faint full-circle track in
|
||||
`color` so the usage wedge reads as a pie instead of a stray triangle; the
|
||||
CPU pie on top keeps a transparent track. */
|
||||
#ram-progress-bar {{
|
||||
color: alpha(#{colors["base03"]}, 0.4);
|
||||
}}
|
||||
|
||||
/* System tray: match the other bar pills */
|
||||
#system-tray {{
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 2px 6px;
|
||||
border-radius: 12px;
|
||||
}}
|
||||
|
||||
/* Org / notmuch pills */
|
||||
#org-widget,
|
||||
#notmuch-widget {{
|
||||
background-color: #{colors["base01"]};
|
||||
}}
|
||||
|
||||
#org-widget:hover,
|
||||
#notmuch-widget:hover {{
|
||||
background-color: #{colors["base02"]};
|
||||
}}
|
||||
|
||||
{accent_pill_css(colors)}
|
||||
|
||||
/* Date time */
|
||||
#date-time {{
|
||||
color: #{colors["base05"]};
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
}}
|
||||
|
||||
#date-time-button {{
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
}}
|
||||
/* Bar widgets are styled purely in the static styles/ css through the palette
|
||||
above (see styles/colors.css for the semantic tokens). */
|
||||
|
||||
/* Generic popup styling */
|
||||
.popup-window,
|
||||
@@ -370,92 +216,6 @@ def generate_stylix_css(mode: str | None = None) -> str | None:
|
||||
opacity: 0.8;
|
||||
}}
|
||||
|
||||
/* Tooltips */
|
||||
tooltip {{
|
||||
border: solid 2px;
|
||||
border-color: #{colors["base02"]};
|
||||
background-color: #{colors["base00"]};
|
||||
color: #{colors["base05"]};
|
||||
border-radius: 16px;
|
||||
}}
|
||||
|
||||
tooltip>* {{
|
||||
padding: 2px 4px;
|
||||
}}
|
||||
|
||||
/* Workspaces */
|
||||
#workspaces {{
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 6px 6px;
|
||||
border-radius: 16px;
|
||||
}}
|
||||
|
||||
#workspaces>button {{
|
||||
background-color: #{colors["base05"]};
|
||||
}}
|
||||
|
||||
#workspaces>button.empty:not(.active):not(.visible) {{
|
||||
background-color: #{colors["base03"]};
|
||||
}}
|
||||
|
||||
#workspaces>button.visible:not(.active) {{
|
||||
background-color: #{colors["base0E"]};
|
||||
}}
|
||||
|
||||
#workspaces>button.active {{
|
||||
background-color: #{colors["base0D"]};
|
||||
}}
|
||||
|
||||
#workspaces>button.urgent {{
|
||||
background-color: #{colors["base08"]};
|
||||
}}
|
||||
|
||||
/* Workspace shown on a different monitor than this bar — dim it. */
|
||||
#workspaces>button.foreign {{
|
||||
opacity: 0.45;
|
||||
}}
|
||||
|
||||
#workspaces>button>label {{
|
||||
font-size: 0px;
|
||||
}}
|
||||
|
||||
/* Compact MPRIS player */
|
||||
#player-small {{
|
||||
background-color: #{colors["base01"]};
|
||||
padding: 6px;
|
||||
border-radius: 100px;
|
||||
}}
|
||||
|
||||
#compact-mpris-icon,
|
||||
#compact-mpris-button {{
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 4px;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}}
|
||||
|
||||
#compact-mpris-button-icon,
|
||||
#compact-mpris-fallback {{
|
||||
color: #{colors["base05"]};
|
||||
}}
|
||||
|
||||
#compact-mpris-button:hover #compact-mpris-button-icon {{
|
||||
color: #{colors["base0D"]};
|
||||
}}
|
||||
|
||||
#compact-mpris-fallback {{
|
||||
opacity: 0.7;
|
||||
}}
|
||||
|
||||
#compact-mpris-label {{
|
||||
color: #{colors["base05"]};
|
||||
font-size: {font_size}px;
|
||||
margin: 0 6px;
|
||||
}}
|
||||
|
||||
/* Quick Menu styling */
|
||||
#quick-menu-container {{
|
||||
background-color: #{colors["base00"]};
|
||||
|
||||
+150
-81
@@ -1,8 +1,18 @@
|
||||
/* ------------------------------------------------------------------------
|
||||
Bar shell
|
||||
|
||||
One visual language for every module:
|
||||
- "chips": --surface fill, same height (bar height minus the 6px
|
||||
vertical padding below), fully rounded, 10px side padding.
|
||||
- a single accent color for "this is active" (workspace, play state),
|
||||
tinted chips for "needs attention", solid fill only for alarms.
|
||||
- text is foreground / --text-muted, icons are 16px.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#sims-inner {
|
||||
padding: 4px;
|
||||
border-bottom: solid 2px;
|
||||
border-color: var(--border-color);
|
||||
padding: 6px 12px;
|
||||
background-color: var(--window-bg);
|
||||
border-bottom: solid 1px var(--hairline);
|
||||
border-radius: 0;
|
||||
transition: border-radius 200ms ease;
|
||||
}
|
||||
@@ -11,19 +21,31 @@
|
||||
border-radius: 0 0 28px 28px;
|
||||
}
|
||||
|
||||
#center-container {
|
||||
color: var(--foreground);
|
||||
/* Shared chip look (workspaces.css applies the same to #workspaces) */
|
||||
#player-small,
|
||||
#widgets-container,
|
||||
#org-widget,
|
||||
#notmuch-widget,
|
||||
#date-time {
|
||||
min-height: 28px;
|
||||
padding: 0 10px;
|
||||
border-radius: 14px;
|
||||
background-color: var(--surface);
|
||||
transition: background-color 150ms ease;
|
||||
}
|
||||
|
||||
.active-window {
|
||||
color: var(--foreground);
|
||||
font-weight: bold;
|
||||
#org-widget:hover,
|
||||
#notmuch-widget:hover,
|
||||
#date-time-button:hover #date-time {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
#battery-widget {
|
||||
background-color: var(--module-bg);
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
/* ---- left ------------------------------------------------------------- */
|
||||
|
||||
#nixos-label {
|
||||
color: var(--accent);
|
||||
font-size: 18px;
|
||||
padding: 0 6px 0 2px;
|
||||
}
|
||||
|
||||
#buddy-container,
|
||||
@@ -34,125 +56,172 @@
|
||||
#buddy-button {
|
||||
padding: 0;
|
||||
margin: 0 2px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#bat-icon {
|
||||
color: var(--blue);
|
||||
margin-right: 2px;
|
||||
/* Compact player chip: circular cover hugging the left edge */
|
||||
#player-small {
|
||||
padding: 0 6px 0 3px;
|
||||
}
|
||||
|
||||
#bat-label {
|
||||
#compact-mpris-icon,
|
||||
#compact-mpris-button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#compact-mpris-label {
|
||||
color: var(--foreground);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
#bat-label.battery-low {
|
||||
color: var(--red);
|
||||
font-weight: bold;
|
||||
#compact-mpris-fallback {
|
||||
color: var(--text-muted);
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
#microphone-icon {
|
||||
color: var(--foreground);
|
||||
font-size: 20px;
|
||||
#compact-mpris-button-icon {
|
||||
color: var(--text-muted);
|
||||
transition: color 150ms ease;
|
||||
}
|
||||
|
||||
#compact-mpris-button:hover #compact-mpris-button-icon {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ---- center ----------------------------------------------------------- */
|
||||
|
||||
#active-window,
|
||||
.active-window {
|
||||
color: var(--text-muted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* ---- right ------------------------------------------------------------ */
|
||||
|
||||
/* System cluster: mic, cpu/ram rings, tray, battery in one chip */
|
||||
#widgets-container {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
#microphone-button {
|
||||
min-width: 28px;
|
||||
padding: 0 6px;
|
||||
padding: 0 4px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#microphone-icon {
|
||||
color: var(--text-muted);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#microphone-button:hover #microphone-icon {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
#microphone-icon.muted {
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
#cpu-progress-bar,
|
||||
/* CPU / RAM "activity rings": outer ring = RAM, inner ring = CPU.
|
||||
CircularProgressBar draws its track with `color` and progress with
|
||||
`border-color`; the border *width* must stay 0 or it inflates the line. */
|
||||
#system-stats {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
#ram-progress-bar,
|
||||
#volume-progress-bar {
|
||||
color: transparent;
|
||||
background-color: transparent
|
||||
#cpu-progress-bar {
|
||||
background-color: transparent;
|
||||
color: alpha(var(--foreground), 0.12);
|
||||
border: solid 0 transparent;
|
||||
}
|
||||
|
||||
#ram-progress-bar {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
#cpu-progress-bar {
|
||||
border: solid 0px alpha(var(--violet), 0.8);
|
||||
border-color: var(--violet);
|
||||
}
|
||||
|
||||
#ram-progress-bar,
|
||||
#volume-progress-bar {
|
||||
border: solid 0px var(--blue);
|
||||
#system-tray {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
#widgets-container {
|
||||
background-color: var(--module-bg);
|
||||
padding: 2px;
|
||||
#system-tray > button {
|
||||
padding: 0 3px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
#player-small {
|
||||
background-color: var(--module-bg);
|
||||
padding: 6px;
|
||||
border-radius: 100px;
|
||||
#system-tray > button:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
#compact-mpris-icon,
|
||||
#compact-mpris-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 4px;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
#battery-widget {
|
||||
padding: 0 2px 0 4px;
|
||||
}
|
||||
|
||||
#compact-mpris-button-icon {
|
||||
#bat-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
#bat-label {
|
||||
color: var(--foreground);
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
#compact-mpris-button:hover #compact-mpris-button-icon {
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
#compact-mpris-fallback {
|
||||
color: var(--foreground);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#compact-mpris-label {
|
||||
color: var(--foreground);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#nixos-label {
|
||||
color: var(--blue);
|
||||
font-size: 20px;
|
||||
margin: 0 2px 0 4px;
|
||||
#bat-icon.battery-low,
|
||||
#bat-label.battery-low {
|
||||
color: var(--red);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Screen-share indicator: a bare red dot, only visible while sharing */
|
||||
#capture-widget {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 6px;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#capture-dot {
|
||||
color: var(--red);
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#capture-summary {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
tooltip {
|
||||
border: solid 2px;
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--window-bg);
|
||||
/* Clock: bold time, muted date */
|
||||
#date-time-button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
tooltip>* {
|
||||
padding: 2px 4px
|
||||
#date-time {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
#clock-time {
|
||||
font-weight: bold;
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
#clock-date {
|
||||
color: var(--text-muted);
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
/* ---- tooltips --------------------------------------------------------- */
|
||||
|
||||
tooltip {
|
||||
background-color: var(--window-bg);
|
||||
border: solid 1px var(--hairline);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
tooltip > * {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
/* Calendar widget styling */
|
||||
|
||||
/* Date time button */
|
||||
#date-time-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#date-time {
|
||||
color: var(--foreground);
|
||||
background-color: var(--module-bg);
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* Calendar event items */
|
||||
.event-item {
|
||||
border-radius: 8px;
|
||||
|
||||
+17
-6
@@ -17,13 +17,24 @@
|
||||
--violet: #AD60FF;
|
||||
--red: #FC3F2C;
|
||||
|
||||
--window-bg: alpha(var(--background), 0.9);
|
||||
/* Semantic tokens. Surfaces/text are derived from --foreground so they
|
||||
work on both dark and light palettes (stylix redefines the base
|
||||
colors at runtime and these follow). */
|
||||
--accent: var(--blue);
|
||||
--surface: alpha(var(--foreground), 0.06);
|
||||
--surface-hover: alpha(var(--foreground), 0.11);
|
||||
--surface-active: alpha(var(--foreground), 0.16);
|
||||
--hairline: alpha(var(--foreground), 0.08);
|
||||
--text-muted: alpha(var(--foreground), 0.62);
|
||||
--text-faint: alpha(var(--foreground), 0.38);
|
||||
|
||||
--window-bg: alpha(var(--background), 0.94);
|
||||
--module-bg: alpha(var(--mid-bg), 0.8);
|
||||
--border-color: var(--light-bg);
|
||||
--ws-active: var(--blue);
|
||||
--ws-visible: var(--violet);
|
||||
--ws-inactive: var(--light-grey);
|
||||
--ws-empty: var(--dark-grey);
|
||||
--ws-hover: var(--turquoise);
|
||||
--ws-active: var(--accent);
|
||||
--ws-visible: alpha(var(--accent), 0.5);
|
||||
--ws-inactive: alpha(var(--foreground), 0.55);
|
||||
--ws-empty: alpha(var(--foreground), 0.18);
|
||||
--ws-hover: alpha(var(--foreground), 0.85);
|
||||
--ws-urgent: var(--red);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,16 @@
|
||||
@import url("./media.css");
|
||||
|
||||
|
||||
/* unset so we can style everything from the ground up. */
|
||||
/* unset so we can style everything from the ground up. `all: unset`
|
||||
makes font-size/font-family inherit, so the base font is set once on the
|
||||
toplevels and any widget rule (e.g. icon sizes) can still override it. */
|
||||
* {
|
||||
all: unset;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
window,
|
||||
tooltip {
|
||||
font-size: 16px;
|
||||
font-family: "Jost*", sans-serif;
|
||||
}
|
||||
|
||||
+19
-27
@@ -1,38 +1,30 @@
|
||||
#date-time,
|
||||
menu>menuitem>label,
|
||||
#date-time>label,
|
||||
/* system tray */
|
||||
#system-tray {
|
||||
padding: 2px 4px;
|
||||
background-color: var(--module-bg);
|
||||
}
|
||||
|
||||
/* menu and menu items (written for the system tray) */
|
||||
/* Context menus (system tray) */
|
||||
menu {
|
||||
border: solid 2px;
|
||||
border-radius: 10px;
|
||||
border-color: var(--border-color);
|
||||
padding: 4px;
|
||||
border: solid 1px var(--hairline);
|
||||
border-radius: 12px;
|
||||
background-color: var(--window-bg);
|
||||
}
|
||||
|
||||
menu>menuitem {
|
||||
border-radius: 0px;
|
||||
background-color: var(--module-bg);
|
||||
padding: 6px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
menu > menuitem {
|
||||
padding: 6px 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
menu>menuitem:first-child {
|
||||
margin-top: 1px;
|
||||
border-radius: 8px 8px 0px 0px;
|
||||
menu > menuitem:hover {
|
||||
background-color: alpha(var(--accent), 0.18);
|
||||
}
|
||||
|
||||
menu>menuitem:last-child {
|
||||
margin-bottom: 1px;
|
||||
border-radius: 0px 0px 8px 8px;
|
||||
menu > menuitem:hover > label {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
menu>menuitem:hover {
|
||||
background-color: var(--pink);
|
||||
menu > menuitem:disabled > label {
|
||||
color: var(--text-faint);
|
||||
}
|
||||
|
||||
menu > separator {
|
||||
min-height: 1px;
|
||||
margin: 4px 6px;
|
||||
background-color: var(--hairline);
|
||||
}
|
||||
|
||||
+24
-27
@@ -1,34 +1,42 @@
|
||||
/* Notmuch email widget styling */
|
||||
/* Notmuch unread badge. Base chip look lives in bar.css.
|
||||
Calm by default; tinted when there is unread mail, solid red only when
|
||||
the email debt timer is in alarm. */
|
||||
|
||||
#notmuch-widget {
|
||||
background-color: var(--module-bg);
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
transition: background-color 0.2s ease;
|
||||
#notmuch-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
#notmuch-widget:hover {
|
||||
background-color: var(--light-bg);
|
||||
#unread-count {
|
||||
color: var(--foreground);
|
||||
font-weight: bold;
|
||||
font-feature-settings: "tnum";
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
#notmuch-widget.has-unread {
|
||||
background-color: var(--blue);
|
||||
background-color: alpha(var(--accent), 0.18);
|
||||
}
|
||||
|
||||
#notmuch-widget.has-unread:hover {
|
||||
background-color: var(--turquoise);
|
||||
background-color: alpha(var(--accent), 0.28);
|
||||
}
|
||||
|
||||
#notmuch-widget.no-unread {
|
||||
background-color: var(--module-bg);
|
||||
#notmuch-widget.has-unread #notmuch-icon,
|
||||
#notmuch-widget.has-unread #unread-count {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
#notmuch-widget.debt-warn {
|
||||
background-color: var(--orange);
|
||||
background-color: alpha(var(--orange), 0.2);
|
||||
}
|
||||
|
||||
#notmuch-widget.debt-warn:hover {
|
||||
background-color: var(--gold);
|
||||
background-color: alpha(var(--orange), 0.3);
|
||||
}
|
||||
|
||||
#notmuch-widget.debt-warn #notmuch-icon,
|
||||
#notmuch-widget.debt-warn #unread-count {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
#notmuch-widget.debt-alarm {
|
||||
@@ -36,21 +44,10 @@
|
||||
}
|
||||
|
||||
#notmuch-widget.debt-alarm:hover {
|
||||
background-color: var(--pink);
|
||||
background-color: shade(var(--red), 1.1);
|
||||
}
|
||||
|
||||
#unread-count {
|
||||
color: var(--foreground);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
#notmuch-widget.has-unread #notmuch-icon,
|
||||
#notmuch-widget.has-unread #unread-count,
|
||||
#notmuch-widget.debt-warn #notmuch-icon,
|
||||
#notmuch-widget.debt-warn #unread-count,
|
||||
#notmuch-widget.debt-alarm #notmuch-icon,
|
||||
#notmuch-widget.debt-alarm #unread-count {
|
||||
color: var(--background);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-27
@@ -1,48 +1,43 @@
|
||||
/* Org-agenda bar widget + dropdown */
|
||||
/* Org-agenda bar widget + dropdown. Base chip look lives in bar.css. */
|
||||
|
||||
#org-widget {
|
||||
background-color: var(--module-bg);
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
transition: background-color 0.2s ease;
|
||||
#org-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
#org-widget:hover {
|
||||
background-color: var(--light-bg);
|
||||
#org-count {
|
||||
font-weight: bold;
|
||||
font-feature-settings: "tnum";
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
#org-widget.empty {
|
||||
background-color: var(--module-bg);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#org-widget.has-next {
|
||||
background-color: var(--blue);
|
||||
background-color: alpha(var(--accent), 0.18);
|
||||
}
|
||||
|
||||
#org-widget.has-next:hover {
|
||||
background-color: var(--turquoise);
|
||||
}
|
||||
|
||||
#org-widget.has-in-progress {
|
||||
background-color: var(--violet);
|
||||
}
|
||||
|
||||
#org-widget.has-in-progress.has-next {
|
||||
background-color: var(--turquoise);
|
||||
}
|
||||
|
||||
#org-count {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
min-width: 16px;
|
||||
background-color: alpha(var(--accent), 0.28);
|
||||
}
|
||||
|
||||
#org-widget.has-next #org-icon,
|
||||
#org-widget.has-next #org-count,
|
||||
#org-widget.has-next #org-count {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
#org-widget.has-in-progress {
|
||||
background-color: alpha(var(--violet), 0.2);
|
||||
}
|
||||
|
||||
#org-widget.has-in-progress:hover {
|
||||
background-color: alpha(var(--violet), 0.3);
|
||||
}
|
||||
|
||||
#org-widget.has-in-progress #org-icon,
|
||||
#org-widget.has-in-progress #org-count {
|
||||
color: var(--background);
|
||||
color: var(--violet);
|
||||
}
|
||||
|
||||
/* Dropdown */
|
||||
|
||||
+25
-21
@@ -1,50 +1,54 @@
|
||||
/* Workspace rail: small dots, the focused one stretches into an accent pill.
|
||||
The chip is 28px tall; 10px vertical padding leaves 8px dots. */
|
||||
#workspaces {
|
||||
padding: 6px;
|
||||
min-width: 0px;
|
||||
background-color: var(--module-bg);
|
||||
min-height: 8px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 14px;
|
||||
background-color: var(--surface);
|
||||
}
|
||||
|
||||
#workspaces>button {
|
||||
padding: 8px;
|
||||
transition: padding 0.05s steps(8), background-color 0.15s ease;
|
||||
#workspaces > button {
|
||||
min-width: 8px;
|
||||
min-height: 8px;
|
||||
border-radius: 99px;
|
||||
background-color: var(--ws-inactive);
|
||||
border-radius: 100px;
|
||||
transition: min-width 200ms cubic-bezier(0.4, 0, 0.2, 1),
|
||||
background-color 150ms ease;
|
||||
}
|
||||
|
||||
#workspaces>button>label {
|
||||
#workspaces > button > label {
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
#workspaces>button:hover {
|
||||
background-color: var(--ws-hover);
|
||||
}
|
||||
|
||||
#workspaces>button.empty {
|
||||
#workspaces > button.empty {
|
||||
background-color: var(--ws-empty);
|
||||
}
|
||||
|
||||
#workspaces>button.visible {
|
||||
#workspaces > button.visible {
|
||||
background-color: var(--ws-visible);
|
||||
}
|
||||
|
||||
#workspaces>button.active {
|
||||
padding: 8px 32px;
|
||||
#workspaces > button:hover {
|
||||
background-color: var(--ws-hover);
|
||||
}
|
||||
|
||||
#workspaces > button.active {
|
||||
min-width: 24px;
|
||||
background-color: var(--ws-active);
|
||||
}
|
||||
|
||||
#workspaces>button.urgent {
|
||||
#workspaces > button.urgent {
|
||||
background-color: var(--ws-urgent);
|
||||
color: var(--foreground);
|
||||
font-weight: bold;
|
||||
animation: urgent-blink 1s infinite;
|
||||
}
|
||||
|
||||
#workspaces>button.foreign {
|
||||
/* Workspace shown on a different monitor than this bar */
|
||||
#workspaces > button.foreign {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
@keyframes urgent-blink {
|
||||
0% { opacity: 1.0; }
|
||||
50% { opacity: 0.5; }
|
||||
50% { opacity: 0.4; }
|
||||
100% { opacity: 1.0; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user