From a56d4d1c2001a748fde5db79e83febe4ecc0ec48 Mon Sep 17 00:00:00 2001 From: Makesesama Date: Mon, 5 Oct 2026 12:30:43 +0200 Subject: [PATCH] fix: light mode theming --- sims/modules/bar.py | 6 ++-- sims/modules/notmuch.py | 2 +- sims/modules/stylix.py | 80 +++++++++++++++++++++++++++++++++++++++++ sims/styles/bar.css | 2 ++ sims/styles/notmuch.css | 3 ++ sims/styles/org.css | 2 ++ 6 files changed, 92 insertions(+), 3 deletions(-) diff --git a/sims/modules/bar.py b/sims/modules/bar.py index e1202fd..767bf24 100644 --- a/sims/modules/bar.py +++ b/sims/modules/bar.py @@ -1,6 +1,5 @@ from fabric.widgets.box import Box from fabric.widgets.label import Label -from fabric.widgets.image import Image from fabric.widgets.overlay import Overlay from fabric.widgets.datetime import DateTime from fabric.widgets.centerbox import CenterBox @@ -142,7 +141,10 @@ class StatusBar(Window): center_children.append(self.active_window) start_container_children = [ - Image(name="nixos-label", icon_name="nix-snowflake-white", icon_size=20), + # Nerd Font glyph (nf-linux-nixos) rather than the nix-snowflake-white + # icon: that SVG is hard-coded white and vanishes on light themes, + # while a glyph follows the CSS `color`. + Label(name="nixos-label", label="\uf313"), self.workspaces, self.player_small, ] diff --git a/sims/modules/notmuch.py b/sims/modules/notmuch.py index 0c036a5..b6cbc6b 100644 --- a/sims/modules/notmuch.py +++ b/sims/modules/notmuch.py @@ -137,7 +137,7 @@ class NotmuchService: class NotmuchWidget(Button): def __init__(self, **kwargs): # Create the widget content - self.icon = Image(icon_name="mail-unread-symbolic", icon_size=16) + self.icon = Image(name="notmuch-icon", icon_name="mail-unread-symbolic", icon_size=16) self.label = Label("0", name="unread-count") # Container for icon and label diff --git a/sims/modules/stylix.py b/sims/modules/stylix.py index 92dd0dc..fce4d74 100644 --- a/sims/modules/stylix.py +++ b/sims/modules/stylix.py @@ -60,6 +60,58 @@ 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): @@ -170,8 +222,36 @@ def generate_stylix_css(mode: str | None = None) -> str | None: /* 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"]}; diff --git a/sims/styles/bar.css b/sims/styles/bar.css index 352edfd..0054b7b 100644 --- a/sims/styles/bar.css +++ b/sims/styles/bar.css @@ -125,6 +125,8 @@ #nixos-label { color: var(--blue); + font-size: 20px; + margin: 0 2px 0 4px; } #capture-widget { diff --git a/sims/styles/notmuch.css b/sims/styles/notmuch.css index 8a7d0b9..2f70ae8 100644 --- a/sims/styles/notmuch.css +++ b/sims/styles/notmuch.css @@ -46,8 +46,11 @@ 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); } \ No newline at end of file diff --git a/sims/styles/org.css b/sims/styles/org.css index 5d97dc7..e29388b 100644 --- a/sims/styles/org.css +++ b/sims/styles/org.css @@ -38,7 +38,9 @@ min-width: 16px; } +#org-widget.has-next #org-icon, #org-widget.has-next #org-count, +#org-widget.has-in-progress #org-icon, #org-widget.has-in-progress #org-count { color: var(--background); }