feat(themes): full revision of executive-slate — palette rebuild + real whole-swap bar
All checks were successful
Check / eval (push) Successful in 3m15s

The executive-slate preset shipped a waybar.css that referenced @base/@accent
with no @define-color block, and no matching waybar.jsonc — so the raw-read
override ran a largely unstyled bar (the item-28 partial-whole-swap defect).
The palette was also flat (base->surface only 1.13x) with a dim accent
(#4D78CC, 3.91 on base).

- Palette: widen surface stepping (base->surface 1.13x -> 1.29x so panels/
  selection/hover separate), brighten the accent (#4D78CC -> #5A8AE6, 3.91 ->
  5.04 on base, now AA text), lift subtext/good/warn/bad a tier, realign ansi,
  soften bright-white (#FFFFFF -> #F0F3F9). text stays 12.5 AAA. Contrast
  checker: all 23 themes x 7 pairings pass.
- Waybar: complete the bespoke bar as a real whole-swap. New waybar.jsonc with
  the full 17-module set (parity with summer-day/night); waybar.css rewritten
  to lead with its own @define-color block and cover every module + state class
  the helper scripts emit (.recording/.activated/.on/.available/.dnd-*/battery).
  Identity: solid, edge-to-edge, sharp corners, accent underline on the active
  workspace.
- Rofi: drop the broken var() idiom for the house *{}/@name convention (split
  border syntax, message/textbox/scrollbar elements for the theme-grid picker).
- CONVENTIONS: Waybar parity rule now names executive-slate as a third
  whole-swap target (was stale at summer-only).

V1: nix flake check --no-build green; strict JSON parse of both files; real
rofi parsed the .rasi cleanly; with executive-slate set active, the module
eval resolves waybar.settings -> the jsonc, waybar.style -> the css, rofi.theme
-> the override rasi, and theme.nix accepts the palette. NOT yet done: on-screen
render of the bar/rofi/desktop (V2/V3) and preview.png (deferred to on-hardware
capture, per the chosen path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-07-06 20:14:30 +01:00
parent 7f10a12ec8
commit 16275947ec
5 changed files with 362 additions and 89 deletions

View File

@@ -5,39 +5,39 @@
"mode": "dark",
"wallpaper": "",
"colors": {
"base": "#1A1D24",
"mantle": "#14161C",
"surface": "#232731",
"overlay": "#333947",
"text": "#D4DAE8",
"subtext": "#8792A6",
"muted": "#525A6E",
"accent": "#4D78CC",
"accentAlt": "#6C92D9",
"good": "#68A06B",
"warn": "#D19C4C",
"bad": "#C95F65"
"base": "#191C24",
"mantle": "#111319",
"surface": "#2A3040",
"overlay": "#3E4759",
"text": "#D7DDEA",
"subtext": "#9AA5BB",
"muted": "#5C6578",
"accent": "#5A8AE6",
"accentAlt": "#86A9F2",
"good": "#6FAE72",
"warn": "#DBA85A",
"bad": "#D06B71"
},
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [
"#232731",
"#C95F65",
"#68A06B",
"#D19C4C",
"#4D78CC",
"#836CC9",
"#4C99A0",
"#D4DAE8",
"#525A6E",
"#D67177",
"#7BB57F",
"#E0AF5E",
"#6C92D9",
"#9A84E0",
"#5FABB3",
"#FFFFFF"
"#2A3040",
"#D06B71",
"#6FAE72",
"#DBA85A",
"#5A8AE6",
"#8C79D6",
"#55A5AE",
"#D7DDEA",
"#5C6578",
"#DE7C82",
"#82BE85",
"#E7BB6E",
"#86A9F2",
"#A594E8",
"#6FBEC6",
"#F0F3F9"
]
}

View File

@@ -1,81 +1,119 @@
/*
* Executive Slate Rofi Theme
* Clean, flat, functional, professional.
/**
* Executive Slate — rofi whole-swap (themes/<slug>/rofi.rasi).
* Identity: a flat, sharp-cornered "control panel". No zebra, no glow —
* a solid slate window, a recessed surface inputbar, and one accent edge
* marking the selected row. The `configuration {}` block is omitted on
* purpose — modi/terminal/show-icons come from modules/home/rofi.nix.
* Element structure mirrors the generated theme so the theme-grid
* picker's per-invocation -theme-str (vertical cards) still lays out.
*/
* {
base: #191C24;
surface: #2A3040;
overlay: #3E4759;
text: #D7DDEA;
subtext: #9AA5BB;
muted: #5C6578;
accent: #5A8AE6;
accentAlt: #86A9F2;
font: "Inter 13";
background-color: transparent;
text-color: var(text, #D4DAE8);
font: "Inter 15";
text-color: @text;
}
window {
width: 600px;
background-color: var(base, #1A1D24);
background-color: @base;
border: 1px;
border-color: var(overlay, #333947);
border-color: @overlay;
border-radius: 4px;
padding: 24px;
width: 40%;
location: center;
anchor: center;
padding: 12px;
}
mainbox {
spacing: 12px;
background-color: transparent;
children: [ inputbar, message, listview ];
spacing: 10px;
}
inputbar {
background-color: var(surface, #232731);
children: [ prompt, entry ];
background-color: @surface;
text-color: @text;
border: 1px;
border-color: var(overlay, #333947);
border-color: @overlay;
border-radius: 4px;
padding: 10px 14px;
spacing: 10px;
children: [ prompt, entry ];
}
prompt {
text-color: var(accent, #4D78CC);
}
prompt { text-color: @accent; }
entry {
placeholder: "Type to filter...";
placeholder-color: var(subtext, #8792A6);
text-color: @text;
cursor: text;
placeholder: "Type to filter…";
placeholder-color: @muted;
}
listview {
lines: 7;
spacing: 4px;
background-color: transparent;
columns: 1;
lines: 8;
dynamic: true;
scrollbar: false;
border: 0px;
spacing: 4px;
padding: 4px 0px 0px 0px;
}
element {
padding: 8px 14px;
background-color: transparent;
text-color: @text;
orientation: horizontal;
border-radius: 4px;
padding: 9px 14px;
spacing: 12px;
}
element normal.normal, element alternate.normal {
element normal.normal,
element alternate.normal {
background-color: transparent;
}
/* Functional highlight: solid surface color with a subtle accent edge */
/* The one highlight: a solid surface row with an accent edge. */
element selected.normal {
background-color: var(surface, #232731);
text-color: var(text, #D4DAE8);
border: 0 0 0 4px;
border-color: var(accent, #4D78CC);
background-color: @surface;
text-color: @text;
border: 0px 0px 0px 3px;
border-color: @accent;
}
element-icon {
size: 24px;
background-color: transparent;
size: 36px;
cursor: inherit;
}
element-text {
background-color: transparent;
text-color: inherit;
highlight: bold;
vertical-align: 0.5;
}
element-text selected {
text-color: var(text, #D4DAE8);
message { padding: 0px; }
textbox {
background-color: @surface;
text-color: @text;
border: 1px;
border-color: @overlay;
border-radius: 4px;
padding: 9px 14px;
}
scrollbar { width: 0px; }

View File

@@ -1,21 +1,42 @@
/* Executive Slate Waybar — Solid, functional, professional */
/*
* Executive Slate — Waybar whole-swap (themes/<slug>/waybar.css).
*
* A theme waybar.css replaces the ENTIRE generated stylesheet and is read
* raw (no palette is prepended), so this file MUST define its own colors.
* Identity: a solid, non-transparent, edge-to-edge status strip — no
* floating island, sharp corners, tight modules, and a single accent
* underline marking the active workspace. Companion: waybar.jsonc.
*/
@define-color base #191C24;
@define-color mantle #111319;
@define-color surface #2A3040;
@define-color overlay #3E4759;
@define-color text #D7DDEA;
@define-color subtext #9AA5BB;
@define-color muted #5C6578;
@define-color accent #5A8AE6;
@define-color accentAlt #86A9F2;
@define-color good #6FAE72;
@define-color warn #DBA85A;
@define-color bad #D06B71;
* {
font-family: "Inter", "Symbols Nerd Font", sans-serif;
font-size: 15px;
font-family: "Inter", "Symbols Nerd Font", "JetBrainsMono Nerd Font", sans-serif;
font-size: 13px;
font-weight: 500;
border: none;
border-radius: 0;
min-height: 0;
}
/* Solid bar, crisp edge against the content below. */
window#waybar {
background: @base;
border-bottom: 1px solid @mantle;
border-bottom: 1px solid @overlay;
color: @text;
}
/* Tightly packed modules for a functional feel */
.modules-left,
.modules-center,
.modules-right {
@@ -23,35 +44,62 @@ window#waybar {
padding: 0;
}
#workspaces button,
#window,
/* Uniform module rhythm; groups get a wider breath below. */
#custom-nomarchy,
#clock,
#tray,
#pulseaudio,
#battery,
#custom-notification,
#custom-vpn,
#custom-powerprofile,
#custom-recording,
#idle_inhibitor,
#custom-nightlight,
#language,
#custom-updates,
#custom-doctor {
padding: 0 12px;
#pulseaudio,
#custom-powerprofile,
#battery,
#custom-vpn,
#custom-doctor,
#custom-notification,
#tray,
#custom-powermenu {
color: @text;
padding: 0 11px;
margin: 0;
border-radius: 0;
}
/* Subtle hover effects */
/* Group heads — a wider gap before each functional cluster of the
right side (media/toggles · stats · status). Self-hiding heads
(e.g. no battery on a desktop) degrade to the uniform spacing. */
#pulseaudio,
#battery,
#custom-vpn { margin-left: 6px; }
/* ── Menu launcher — the one branded accent glyph ────────────────── */
#custom-nomarchy {
color: @accent;
font-size: 15px;
padding: 0 14px;
}
#custom-nomarchy:hover {
background: @surface;
color: @accentAlt;
}
/* ── Workspaces — flat cells, active carries an accent underline ──── */
#workspaces { padding: 0; margin: 0; }
#workspaces button {
color: @subtext;
transition: all 0.2s ease-in-out;
padding: 0 11px;
margin: 0;
border-bottom: 2px solid transparent;
transition: color 0.15s ease-in-out, background 0.15s ease-in-out;
}
#workspaces button:hover {
background: @surface;
color: @text;
border-bottom: 2px solid @overlay;
}
/* Active gets a strong underline instead of a glowing background */
#workspaces button.active {
color: @text;
background: @surface;
@@ -63,23 +111,53 @@ window#waybar {
border-bottom: 2px solid @bad;
}
/* Minimal indicators */
/* ── Clock — time (center) and date (left) share the #clock id ───── */
#clock {
color: @text;
font-weight: 600;
}
/* ── Status cluster: neutral by default, semantic on state ───────── */
#custom-recording.recording { color: @bad; }
#idle_inhibitor.activated { color: @warn; }
#custom-nightlight.on { color: @warn; }
#custom-updates.available { color: @accent; }
/* Power-profile glyph renders small in its em box — size it up. */
#custom-powerprofile { font-size: 16px; }
#pulseaudio.muted { color: @muted; }
#battery.charging { color: @good; }
#battery.warning:not(.charging) { color: @warn; }
#battery.warning:not(.charging) { color: @warn; }
#battery.critical:not(.charging) {
color: @bad;
background: @surface;
border-bottom: 2px solid @bad;
}
#pulseaudio.muted { color: @muted; }
#custom-updates { color: @accentAlt; }
#custom-doctor { color: @bad; }
#custom-vpn { color: @accent; }
#custom-vpn.on { color: @good; }
/* Functional tooltip */
/* Doctor is only rendered when something is ✖, so always the alert. */
#custom-doctor { color: @bad; }
#custom-notification.notification { color: @accent; }
#custom-notification.dnd-none,
#custom-notification.dnd-notification { color: @muted; }
#tray { color: @text; }
#custom-powermenu { color: @subtext; }
#custom-powermenu:hover {
background: @surface;
color: @bad;
}
/* ── Tooltips ─────────────────────────────────────────────────────── */
tooltip {
background: @base;
background: @surface;
border: 1px solid @overlay;
border-radius: 4px;
}

View File

@@ -0,0 +1,157 @@
{
"margin-top": 0,
"margin-left": 0,
"margin-bottom": 0,
"margin-right": 0,
"height": 34,
"layer": "top",
"position": "top",
"spacing": 0,
"reload_style_on_change": true,
"modules-left": ["custom/nomarchy", "hyprland/workspaces", "clock#date"],
"modules-center": ["clock"],
"modules-right": ["custom/recording", "idle_inhibitor", "custom/nightlight", "hyprland/language", "custom/updates", "pulseaudio", "custom/powerprofile", "battery", "custom/vpn", "custom/doctor", "custom/notification", "tray", "custom/powermenu"],
"custom/nomarchy": {
"interval": "once",
"format": "",
"on-click": "nomarchy-menu",
"tooltip-format": "Nomarchy menu"
},
"hyprland/workspaces": {
"disable-scroll": true,
"all-outputs": true,
"on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace r+1",
"on-scroll-down": "hyprctl dispatch workspace r-1"
},
"clock": {
"format": "{:%H:%M}",
"tooltip": true,
"tooltip-format": "{:%Z (UTC%z)}\n<tt><small>{calendar}</small></tt>"
},
"clock#date": {
"format": "{:%a %d %b}",
"tooltip": false
},
"custom/recording": {
"return-type": "json",
"interval": 10,
"signal": 8,
"exec": "nomarchy-record status",
"on-click": "nomarchy-record stop"
},
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
"activated": "󰅶",
"deactivated": "󰾪"
}
},
"custom/nightlight": {
"return-type": "json",
"interval": 3,
"exec": "nomarchy-nightlight status",
"on-click": "nomarchy-nightlight toggle"
},
"hyprland/language": {
"format": "󰌌 {short}",
"tooltip": false
},
"custom/updates": {
"return-type": "json",
"interval": 1800,
"signal": 9,
"exec": "nomarchy-updates status",
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
},
"pulseaudio": {
"scroll-step": 5,
"format": "{icon} {volume}%",
"format-bluetooth": "{icon} {volume}%",
"format-bluetooth-muted": "{icon} muted",
"format-muted": " muted",
"format-icons": {
"headphone": "",
"hands-free": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", "", ""]
},
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
"tooltip-format": "{desc} | {volume}%"
},
"custom/powerprofile": {
"return-type": "json",
"interval": 5,
"exec": "nomarchy-powerprofile-status",
"on-click": "nomarchy-powerprofile-cycle"
},
"battery": {
"interval": 30,
"states": { "warning": 25, "critical": 10 },
"format": "{icon} {capacity}%",
"format-charging": " {capacity}%",
"format-plugged": " {capacity}%",
"format-icons": ["", "", "", "", ""],
"on-click": "nomarchy-menu power",
"tooltip-format": "Battery status"
},
"custom/vpn": {
"return-type": "json",
"interval": 5,
"exec": "nomarchy-vpn-status",
"on-click": "nomarchy-vpn"
},
"custom/doctor": {
"return-type": "json",
"interval": 300,
"exec": "nomarchy-doctor-status",
"on-click": "nomarchy-menu doctor"
},
"custom/notification": {
"format": "{icon}",
"return-type": "json",
"exec": "swaync-client -swb",
"exec-if": "which swaync-client",
"escape": true,
"tooltip": true,
"on-click": "swaync-client -t -sw",
"on-click-right": "swaync-client -d -sw",
"format-icons": {
"none": "",
"notification": "",
"dnd-none": "",
"dnd-notification": "",
"inhibited-none": "",
"inhibited-notification": "",
"dnd-inhibited-none": "",
"dnd-inhibited-notification": ""
}
},
"tray": { "spacing": 8 },
"custom/powermenu": {
"format": "",
"on-click": "nomarchy-menu power",
"tooltip": false
}
}