All checks were successful
Check / eval (push) Successful in 4m9s
Two hardware-reported contrast bugs, both the same family: surfaces
that fell back to something designed on dark.
1. Inactive workspace numbers unreadable on every light theme.
- Generated bar: the @muted dim role is floor-gated at only 2.0:1 —
fine as "dim" on dark, washed out at number size on light. Light
mode now promotes inactive buttons to @subtext (3.0 floor,
typically 4-7:1); dark themes keep @muted.
- boreal-dawn + kiln-clay whole-swaps: same @muted -> @subtext
(6.4:1 / 6.6:1).
- summer-day whole-swap: had NO button color rule at all — the
container's @fg does not inherit into GTK buttons, so the numbers
took the GTK default over the cream chip. Explicit @fg_dim
(= the palette's subtext, 4.0:1) added.
- executive-ivory already used @subtext; untouched.
2. Notification popup unreadable on hover (bg turns dark, text stays
dark). Root cause found by probing, not guessing: the popup body is
one big GTK button (.notification-default-action) and swaync's
DEFAULT stylesheet — still loaded under our style.css — hovers it to
rgb(56,56,56). Our sheet never overrode that node (only the
control-center row), so the default bled through; on light themes
dark @text sat on it. Now the body + action buttons + close button
are re-pinned to the palette's alpha(@text) tint construction —
mode-proof by construction. The first fix attempt (row-level hover)
was probed, SHOWN insufficient, and replaced.
Verification: V2. nix flake check --no-build, theme-wholeswap,
theme-contrast green. §3 evidence viewed: a purpose-built VM hover
probe under summer-day (notify-send -u critical, cursor parked ON the
popup, screenshot) — before: dark card, drowned text (reproduces the
report exactly, /nix/store/q1qf67fl...notify-shot-summer-day); after:
cream card + faint tint, fully readable (shot-notify2). Bar renders
verified under catppuccin-latte (generated light path incl. the mode
branch) and summer-day (edited whole-swap). An inactive-number visual
needs two live workspaces — VM shows one — so the on-hardware
confirmation is queued (HARDWARE-QUEUE light-theme refits entry);
the ratio change itself is machine-checked.
Bookkeeping riding along: BACKLOG #152 deleted (shipped in d79ad35).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
135 lines
4.3 KiB
Nix
135 lines
4.3 KiB
Nix
# swaync — notification daemon + control centre, themed from
|
|
# state.json. Until this shipped, nothing rendered notify-send at
|
|
# all: the theme-switch progress toasts, the CLI's font warnings and the
|
|
# live ISO's welcome message were all invisible.
|
|
{ config, lib, ... }:
|
|
|
|
let
|
|
cfg = config.nomarchy;
|
|
t = cfg.theme;
|
|
c = t.colors;
|
|
r = toString t.ui.rounding;
|
|
in
|
|
{
|
|
config = lib.mkIf cfg.swaync.enable {
|
|
services.swaync = {
|
|
enable = true;
|
|
|
|
settings = {
|
|
positionX = "right";
|
|
positionY = "top";
|
|
control-center-margin-top = t.ui.gapsOut;
|
|
control-center-margin-right = t.ui.gapsOut;
|
|
control-center-width = 420;
|
|
notification-window-width = 400;
|
|
notification-icon-size = 48;
|
|
timeout = 6;
|
|
timeout-low = 3;
|
|
timeout-critical = 0; # critical stays until dismissed
|
|
};
|
|
|
|
style = ''
|
|
/* Palette baked from state.json. Only roles guaranteed to
|
|
contrast @base in EVERY palette are used: subtext/surface mean
|
|
"on-surface" in some light themes (summer-day: subtext==base,
|
|
surface==text — body text was invisible on hardware, item 25).
|
|
Chips/hovers are alpha(@text) tints — contrast by construction.
|
|
tools/check-theme-contrast.py guards the hex-on-hex pairings. */
|
|
@define-color base ${c.base};
|
|
@define-color text ${c.text};
|
|
@define-color accent ${c.accent};
|
|
@define-color bad ${c.bad};
|
|
|
|
.notification {
|
|
background: alpha(@base, 0.95);
|
|
border: ${toString t.ui.borderSize}px solid alpha(@accent, 0.4);
|
|
border-radius: ${r}px;
|
|
color: @text;
|
|
font-family: "${t.fonts.ui}", "${t.fonts.mono}";
|
|
font-size: ${toString t.fonts.size}pt;
|
|
}
|
|
|
|
.notification-content .summary {
|
|
color: @text;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.notification-content .body {
|
|
color: @text;
|
|
}
|
|
|
|
.notification.critical {
|
|
border-color: @bad;
|
|
}
|
|
|
|
.control-center {
|
|
background: alpha(@base, 0.95);
|
|
border: ${toString t.ui.borderSize}px solid alpha(@accent, 0.4);
|
|
border-radius: ${r}px;
|
|
color: @text;
|
|
font-family: "${t.fonts.ui}", "${t.fonts.mono}";
|
|
font-size: ${toString t.fonts.size}pt;
|
|
}
|
|
|
|
/* Unscoped on purpose: the floating popup wraps .notification in
|
|
a .notification-row too, and swaync's DEFAULT stylesheet (still
|
|
loaded underneath this one) paints that row dark on hover — on
|
|
light themes the theme's dark @text then sat on the default's
|
|
dark hover, unreadable. The same alpha(@text) tint as
|
|
everywhere else overrides it in both surfaces. */
|
|
.notification-row:focus,
|
|
.notification-row:hover {
|
|
background: alpha(@text, 0.1);
|
|
border-radius: ${r}px;
|
|
}
|
|
|
|
/* The REAL popup-hover culprit: the notification body is one big
|
|
GTK button (.notification-default-action), and the default
|
|
sheet hovers IT to rgb(56,56,56) — on light themes that put
|
|
dark @text on a dark chip (unreadable, hardware report
|
|
2026-07-18). Re-pin body + action buttons to the palette's
|
|
tint construction; hover stays a tint of @text, so it works
|
|
in both modes by construction. */
|
|
.notification-default-action,
|
|
.notification-action {
|
|
background: transparent;
|
|
color: @text;
|
|
}
|
|
.notification-default-action:hover,
|
|
.notification-action:hover {
|
|
background: alpha(@text, 0.08);
|
|
}
|
|
|
|
/* Same default-stylesheet leak: swaync ships a dark close-button
|
|
chip; re-pin both ends to the palette's tint construction. */
|
|
.close-button {
|
|
background: alpha(@text, 0.1);
|
|
color: @text;
|
|
border-radius: ${r}px;
|
|
}
|
|
.close-button:hover {
|
|
background: alpha(@text, 0.2);
|
|
color: @text;
|
|
}
|
|
|
|
.widget-title {
|
|
color: @text;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.widget-title > button {
|
|
background: alpha(@text, 0.1);
|
|
color: @text;
|
|
border: none;
|
|
border-radius: ${r}px;
|
|
}
|
|
|
|
.widget-title > button:hover {
|
|
background: @accent;
|
|
color: @base;
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
}
|