feat(themes): add Boreal + make theme appearance per-theme
All checks were successful
Check / eval (push) Successful in 3m1s
All checks were successful
Check / eval (push) Successful in 3m1s
Boreal — a Nord × Everforest × Dracula dark theme: a boreal forest at night under the aurora. Nord's frost bones, Everforest's comfort, Dracula's jewel-tone violet/cyan as the aurora light. Palette (WCAG-checked, all 24 themes × 7 pairings pass): frost-slate base, soft-vivid violet accent (#B79BE8, 6.35 on base) + frost-cyan accentAlt (#86C7C0, 7.84 AAA), sage-green/gold/coral semantics, text 10.66 AAA. Bespoke, non-standard surfaces: - Waybar whole-swap (jsonc + css): a floating "aurora frost" bar of three frosted-glass pills; launcher+clock left, workspaces centre, and the whole right side is ONE continuous pill — the system tray shares its glass with the status modules, no separators (the seamless-tray requirement). Full module set (parity). GeistMono. - Rofi: a frosted list base (used by every menu), plus a 4×3 large-icon grid for the app launcher only. - Typography GeistMono Nerd Font (57 MB, new); Iosevka was rejected at 1.1 GB. Per-theme appearance (new): a preset now carries a full fonts+ui block, like border, so a theme can ship a bespoke font / terminal opacity / border thickness / rounding and a switch always replaces it — no leak into the next theme (verified: boreal→everforest resets mono/rounding/opacity). All 23 other presets get the current defaults (idempotent — zero visual change). Boreal runs GeistMono + 0.90 terminal opacity + 3px borders + 12px rounding. Grid launcher (new, backward-compatible): drun renders via `-theme launcher`; HM writes ~/.local/share/rofi/themes/launcher.rasi which defaults to `@import "custom.rasi"` (every other theme's launcher = its list, unchanged), and a theme may override it (Boreal's grid). Text menus keep the base list. Wallpaper: an original procedurally-generated aurora-over-treeline (ImageMagick), palette-matched. V1: nix flake check --no-build green; strict JSON on every preset; contrast checker green; the real rofi binary parses the base rasi and resolves `-theme launcher` + @import + grid overlay; end-to-end eval with boreal active resolves the waybar whole-swap (tray in the right cluster), the rofi grid launcher, and the bespoke fonts/opacity/geometry reaching nomarchy.theme, with no cross-theme contamination. NOT done: on-screen render of the desktop (V2/V3) and preview.png (deferred to on-hardware capture). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
BIN
themes/boreal/backgrounds/aurora-boreal.png
Normal file
BIN
themes/boreal/backgrounds/aurora-boreal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 MiB |
37
themes/boreal/launcher.rasi
Normal file
37
themes/boreal/launcher.rasi
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Boreal — app-launcher override (themes/<slug>/launcher.rasi).
|
||||
* Installed to ~/.local/share/rofi/themes/launcher.rasi and used only by
|
||||
* `rofi -show drun` (the SUPER+Space / SUPER+D launcher). It inherits the
|
||||
* frosted aurora panel from the sibling custom.rasi (the active theme),
|
||||
* then reshapes the list into a 4×3 grid of large application icons.
|
||||
* Text menus keep the list — they don't use this theme.
|
||||
*/
|
||||
|
||||
@import "custom.rasi"
|
||||
|
||||
window { width: 780px; }
|
||||
|
||||
listview {
|
||||
columns: 4;
|
||||
lines: 3;
|
||||
fixed-columns: true;
|
||||
spacing: 10px;
|
||||
padding: 6px 0px 0px 0px;
|
||||
}
|
||||
|
||||
element {
|
||||
orientation: vertical;
|
||||
padding: 16px 8px;
|
||||
spacing: 10px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
size: 56px;
|
||||
horizontal-align: 0.5;
|
||||
}
|
||||
|
||||
element-text {
|
||||
horizontal-align: 0.5;
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
116
themes/boreal/rofi.rasi
Normal file
116
themes/boreal/rofi.rasi
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Boreal — rofi whole-swap (themes/<slug>/rofi.rasi).
|
||||
* The base theme: a frosted aurora panel used by every menu (and, as a
|
||||
* list, the fallback launcher). The app launcher reshapes this into a
|
||||
* grid via themes/boreal/launcher.rasi, which @imports this file. The
|
||||
* `configuration {}` block is omitted on purpose — it comes from
|
||||
* modules/home/rofi.nix. Element structure mirrors the generated theme
|
||||
* so the theme-grid picker's per-invocation -theme-str still lays out.
|
||||
*/
|
||||
|
||||
* {
|
||||
base: #21272F;
|
||||
glassBg: #21272FE6;
|
||||
surface: #303A46;
|
||||
overlay: #404D5C;
|
||||
text: #D3DAE0;
|
||||
subtext: #97A3B2;
|
||||
muted: #5E6A78;
|
||||
accent: #B79BE8;
|
||||
accentAlt: #86C7C0;
|
||||
accentSoft: #B79BE83B;
|
||||
frostEdge: #86C7C05C;
|
||||
|
||||
font: "GeistMono Nerd Font 11";
|
||||
background-color: transparent;
|
||||
text-color: @text;
|
||||
}
|
||||
|
||||
window {
|
||||
background-color: @glassBg;
|
||||
border: 1px;
|
||||
border-color: @frostEdge;
|
||||
border-radius: 14px;
|
||||
width: 620px;
|
||||
location: center;
|
||||
anchor: center;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
mainbox {
|
||||
background-color: transparent;
|
||||
children: [ inputbar, message, listview ];
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
inputbar {
|
||||
children: [ prompt, entry ];
|
||||
background-color: @surface;
|
||||
text-color: @text;
|
||||
border-radius: 10px;
|
||||
padding: 12px 16px;
|
||||
spacing: 10px;
|
||||
}
|
||||
|
||||
prompt { text-color: @accent; }
|
||||
|
||||
entry {
|
||||
text-color: @text;
|
||||
cursor: text;
|
||||
placeholder: "Search…";
|
||||
placeholder-color: @muted;
|
||||
}
|
||||
|
||||
listview {
|
||||
background-color: transparent;
|
||||
columns: 1;
|
||||
lines: 8;
|
||||
dynamic: true;
|
||||
scrollbar: false;
|
||||
spacing: 6px;
|
||||
padding: 4px 0px 0px 0px;
|
||||
}
|
||||
|
||||
element {
|
||||
background-color: transparent;
|
||||
text-color: @text;
|
||||
orientation: horizontal;
|
||||
border-radius: 10px;
|
||||
padding: 10px 14px;
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
element normal.normal,
|
||||
element alternate.normal {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Selected row lifts on a soft aurora-violet wash. */
|
||||
element selected.normal {
|
||||
background-color: @accentSoft;
|
||||
text-color: @text;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
background-color: transparent;
|
||||
size: 30px;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
element-text {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
highlight: bold;
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
message { padding: 0px; }
|
||||
|
||||
textbox {
|
||||
background-color: @surface;
|
||||
text-color: @text;
|
||||
border-radius: 10px;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
scrollbar { width: 0px; }
|
||||
152
themes/boreal/waybar.css
Normal file
152
themes/boreal/waybar.css
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Boreal — 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 floating "aurora frost" bar — three frosted-glass pills
|
||||
* (launcher+clock · workspaces · status) over the wallpaper's blur. The
|
||||
* whole right side is ONE continuous pill: the system tray shares its
|
||||
* glass with the status modules, no separators, no boxes. Companion:
|
||||
* waybar.jsonc.
|
||||
*/
|
||||
|
||||
@define-color base #21272F;
|
||||
@define-color mantle #1A1F26;
|
||||
@define-color surface #303A46;
|
||||
@define-color overlay #404D5C;
|
||||
@define-color text #D3DAE0;
|
||||
@define-color subtext #97A3B2;
|
||||
@define-color muted #5E6A78;
|
||||
@define-color accent #B79BE8;
|
||||
@define-color accentAlt #86C7C0;
|
||||
@define-color good #A3CF88;
|
||||
@define-color warn #E6C384;
|
||||
@define-color bad #E2818A;
|
||||
|
||||
* {
|
||||
font-family: "GeistMono Nerd Font", "Symbols Nerd Font";
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* The bar itself is invisible — the pills float over the wallpaper. */
|
||||
window#waybar {
|
||||
background: transparent;
|
||||
color: @text;
|
||||
}
|
||||
|
||||
/* ── The three frosted-glass pills ────────────────────────────────────
|
||||
Global blur turns the translucent @base into frosted glass; a faint
|
||||
frost-cyan edge lifts each pill off the wallpaper. */
|
||||
.modules-left,
|
||||
.modules-center,
|
||||
.modules-right {
|
||||
background: alpha(@base, 0.72);
|
||||
border: 1px solid alpha(@accentAlt, 0.14);
|
||||
border-radius: 14px;
|
||||
padding: 0 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Every module sits ON its pill: transparent, so nothing boxes the tray
|
||||
off from the status icons — the seamless-cluster requirement. */
|
||||
#custom-nomarchy,
|
||||
#clock,
|
||||
#custom-recording,
|
||||
#custom-updates,
|
||||
#custom-doctor,
|
||||
#idle_inhibitor,
|
||||
#custom-nightlight,
|
||||
#language,
|
||||
#custom-vpn,
|
||||
#pulseaudio,
|
||||
#battery,
|
||||
#custom-powerprofile,
|
||||
#tray,
|
||||
#custom-notification,
|
||||
#custom-powermenu {
|
||||
background: transparent;
|
||||
color: alpha(@text, 0.9);
|
||||
padding: 0 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ── Launcher — the aurora-violet monogram opens the pill ─────────────*/
|
||||
#custom-nomarchy {
|
||||
color: @accent;
|
||||
font-size: 16px;
|
||||
padding: 0 12px 0 14px;
|
||||
}
|
||||
#custom-nomarchy:hover { color: @accentAlt; }
|
||||
|
||||
/* ── Clock — mono digits align; date recedes to frost-grey ───────────*/
|
||||
#clock {
|
||||
color: @text;
|
||||
font-weight: 600;
|
||||
padding-left: 4px;
|
||||
}
|
||||
#clock.date { color: @subtext; font-weight: 500; }
|
||||
|
||||
/* ── Workspaces — dots that bloom to an aurora pill when active ───────*/
|
||||
#workspaces { padding: 0 2px; }
|
||||
|
||||
#workspaces button {
|
||||
color: @muted;
|
||||
padding: 0 9px;
|
||||
margin: 3px 1px;
|
||||
border-radius: 9px;
|
||||
transition: color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
#workspaces button:hover {
|
||||
color: @text;
|
||||
background: alpha(@overlay, 0.5);
|
||||
}
|
||||
#workspaces button.active {
|
||||
color: @base;
|
||||
background: @accent;
|
||||
}
|
||||
#workspaces button.urgent {
|
||||
color: @base;
|
||||
background: @bad;
|
||||
}
|
||||
|
||||
/* ── Status semantics (neutral until a state fires) ──────────────────*/
|
||||
#custom-recording.recording { color: @bad; }
|
||||
#custom-updates.available { color: @accent; }
|
||||
#custom-doctor { color: @bad; }
|
||||
#idle_inhibitor.activated { color: @warn; }
|
||||
#custom-nightlight.on { color: @warn; }
|
||||
#custom-vpn.on { color: @good; }
|
||||
#pulseaudio.muted { color: @muted; }
|
||||
|
||||
#battery.charging { color: @good; }
|
||||
#battery.warning:not(.charging) { color: @warn; }
|
||||
#battery.critical:not(.charging) { color: @bad; }
|
||||
|
||||
/* Power-profile speedometer renders small in its em box — size it up. */
|
||||
#custom-powerprofile { font-size: 16px; }
|
||||
|
||||
#custom-notification.notification { color: @accent; }
|
||||
#custom-notification.dnd-none,
|
||||
#custom-notification.dnd-notification { color: @muted; }
|
||||
|
||||
/* Tray shares the pill's glass — same transparent background, its own
|
||||
modest padding so nm-applet & friends breathe with the status icons. */
|
||||
#tray { padding: 0 6px; }
|
||||
#tray > .passive { -gtk-icon-effect: dim; }
|
||||
#tray > .needs-attention { -gtk-icon-effect: highlight; }
|
||||
|
||||
/* Power button closes the pill on the right; warms to alert on hover. */
|
||||
#custom-powermenu { color: @subtext; padding: 0 12px 0 8px; }
|
||||
#custom-powermenu:hover { color: @bad; }
|
||||
|
||||
/* ── Tooltips — frosted, frost-cyan edge ─────────────────────────────*/
|
||||
tooltip {
|
||||
background: alpha(@base, 0.96);
|
||||
border: 1px solid alpha(@accentAlt, 0.3);
|
||||
border-radius: 10px;
|
||||
}
|
||||
tooltip label { color: @text; }
|
||||
160
themes/boreal/waybar.jsonc
Normal file
160
themes/boreal/waybar.jsonc
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"margin-top": 8,
|
||||
"margin-left": 14,
|
||||
"margin-right": 14,
|
||||
"margin-bottom": 0,
|
||||
"height": 38,
|
||||
"layer": "top",
|
||||
"position": "top",
|
||||
"spacing": 4,
|
||||
"reload_style_on_change": true,
|
||||
|
||||
"modules-left": ["custom/nomarchy", "clock", "clock#date"],
|
||||
"modules-center": ["hyprland/workspaces"],
|
||||
"modules-right": ["custom/recording", "custom/updates", "custom/doctor", "idle_inhibitor", "custom/nightlight", "hyprland/language", "custom/vpn", "pulseaudio", "battery", "custom/powerprofile", "tray", "custom/notification", "custom/powermenu"],
|
||||
|
||||
"custom/nomarchy": {
|
||||
"interval": "once",
|
||||
"format": "",
|
||||
"on-click": "nomarchy-menu",
|
||||
"tooltip-format": "Nomarchy menu"
|
||||
},
|
||||
|
||||
"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
|
||||
},
|
||||
|
||||
"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"
|
||||
},
|
||||
|
||||
"custom/recording": {
|
||||
"return-type": "json",
|
||||
"interval": 10,
|
||||
"signal": 8,
|
||||
"exec": "nomarchy-record status",
|
||||
"on-click": "nomarchy-record stop"
|
||||
},
|
||||
|
||||
"custom/updates": {
|
||||
"return-type": "json",
|
||||
"interval": 1800,
|
||||
"signal": 9,
|
||||
"exec": "nomarchy-updates status",
|
||||
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
|
||||
},
|
||||
|
||||
"custom/doctor": {
|
||||
"return-type": "json",
|
||||
"interval": 300,
|
||||
"exec": "nomarchy-doctor-status",
|
||||
"on-click": "nomarchy-menu doctor"
|
||||
},
|
||||
|
||||
"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/vpn": {
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-vpn-status",
|
||||
"on-click": "nomarchy-vpn"
|
||||
},
|
||||
|
||||
"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}%"
|
||||
},
|
||||
|
||||
"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/powerprofile": {
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-powerprofile-status",
|
||||
"on-click": "nomarchy-powerprofile-cycle"
|
||||
},
|
||||
|
||||
"tray": {
|
||||
"icon-size": 15,
|
||||
"spacing": 10
|
||||
},
|
||||
|
||||
"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": ""
|
||||
}
|
||||
},
|
||||
|
||||
"custom/powermenu": {
|
||||
"format": "",
|
||||
"on-click": "nomarchy-menu power",
|
||||
"tooltip": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user