From 7c34eed2caccee6a1ab2f4531ec7343752286438 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Sat, 13 Jun 2026 20:32:18 +0100 Subject: [PATCH] fix(theme): solid per-theme hyprland borders, matching legacy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1 forced an accent→accentAlt 45deg gradient on every theme's window border; the legacy identity themes all used a *solid* border — accent for nord/retro-82/lumon, the text tone for kanagawa/summer-day/summer-night. Add a palette-resolved `border` field ({active, inactive}, each a palette key or literal hex) to the theme schema with accent/overlay defaults in theme.nix, consume it solid in hyprland.nix, and declare it in every preset (and the live state). Declaring it everywhere is required because `nomarchy-theme-sync apply` deep-merges presets — an omitted field would stick across switches, like colors already are fully specified per theme. All six identity themes resolve to their exact legacy active border (verified: nord #81a1c1, retro-82 #faa968, lumon #f2fcff, kanagawa #dcd7ba, summer-night #d3c6aa, summer-day #5c6a72). nix flake check passes. Co-Authored-By: Claude Opus 4.8 --- .claude/settings.local.json | 4 +++- README.md | 11 +++++++---- modules/home/hyprland.nix | 6 ++++-- modules/home/theme.nix | 16 +++++++++++++++- theme-state.json | 4 ++++ themes/catppuccin-latte.json | 4 ++++ themes/catppuccin.json | 4 ++++ themes/ethereal.json | 4 ++++ themes/everforest.json | 4 ++++ themes/flexoki-light.json | 4 ++++ themes/gruvbox.json | 4 ++++ themes/hackerman.json | 4 ++++ themes/kanagawa.json | 4 ++++ themes/lumon.json | 4 ++++ themes/matte-black.json | 4 ++++ themes/miasma.json | 4 ++++ themes/nord.json | 4 ++++ themes/osaka-jade.json | 4 ++++ themes/retro-82.json | 4 ++++ themes/ristretto.json | 4 ++++ themes/rose-pine.json | 4 ++++ themes/summer-day.json | 4 ++++ themes/summer-night.json | 4 ++++ themes/tokyo-night.json | 4 ++++ themes/vantablack.json | 4 ++++ themes/white.json | 4 ++++ 26 files changed, 117 insertions(+), 8 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 1323d91..014fdd9 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -262,7 +262,9 @@ "Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-night --no-switch)", "Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-day --no-switch)", "Bash(xargs cat)", - "Bash(nix-instantiate --parse modules/home/rofi.nix)" + "Bash(nix-instantiate --parse modules/home/rofi.nix)", + "Bash(nix-instantiate --parse modules/home/shell.nix)", + "Bash(command -v nix)" ] } } diff --git a/README.md b/README.md index 6e9c7e5..a82de75 100644 --- a/README.md +++ b/README.md @@ -379,10 +379,13 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot. - ✓ **Enable nix-ld by default:** `programs.nix-ld.enable` is on distro-wide (`modules/nixos/default.nix`), so prebuilt/foreign dynamically-linked binaries run out of the box. -- **Hyprland border colors off for some themes:** the active/inactive border - colors don't match the legacy branch for several themes — audit - `col.active_border`/`col.inactive_border` generation in - `modules/home/hyprland.nix` against legacy. +- ✓ **Hyprland border colors off for some themes:** the cause was v1 + forcing an `accent→accentAlt` gradient on every theme; legacy used a + *solid* border (accent for nord/retro-82/lumon, the text tone for + kanagawa/summer-day/summer-night). Added a palette-resolved `border` + field (`{active, inactive}`) to the theme schema (`theme.nix`), consumed + solid in `hyprland.nix`, and declared it in every preset so a switch + always replaces it. All six identity themes now match legacy exactly. - **Waybar shows non-existent workspaces:** in summer-night/summer-day the bar renders every workspace icon up-front via `persistent-workspaces` / `all-outputs` in `themes/summer-{day,night}/waybar.jsonc`. Restore the diff --git a/modules/home/hyprland.nix b/modules/home/hyprland.nix index d7a2f1d..ca36114 100644 --- a/modules/home/hyprland.nix +++ b/modules/home/hyprland.nix @@ -65,8 +65,10 @@ in gaps_in = t.ui.gapsIn; gaps_out = t.ui.gapsOut; border_size = t.ui.borderSize; - "col.active_border" = "${rgb c.accent} ${rgb c.accentAlt} 45deg"; - "col.inactive_border" = rgb c.overlay; + # Solid borders from theme.border (per-theme, palette-resolved) — + # matches the legacy identity themes, which never used a gradient. + "col.active_border" = rgb t.border.active; + "col.inactive_border" = rgb t.border.inactive; layout = lib.mkDefault "dwindle"; resize_on_border = lib.mkDefault true; }; diff --git a/modules/home/theme.nix b/modules/home/theme.nix index 72420f2..8221f19 100644 --- a/modules/home/theme.nix +++ b/modules/home/theme.nix @@ -47,10 +47,24 @@ let # Icon theme name; "" means "pick by mode" (resolved below). A preset # or the state file can name any theme in the shipped icon package. icons = ""; + # Window border colors. Values are palette keys (resolved against + # `colors` below) or literal #rrggbb. Solid, not a gradient — every + # legacy identity theme used a solid border (accent for most, the text + # tone for kanagawa/summer-*). Each preset declares its own so a theme + # switch always replaces it (deep_merge would otherwise leave it stuck). + border = { active = "accent"; inactive = "overlay"; }; }; parsed = lib.recursiveUpdate defaults themeState; + # A border value is a palette key (look it up in colors) unless it's + # already a literal hex; unknown keys fall through to the raw string. + resolveColor = v: if lib.hasPrefix "#" v then v else parsed.colors.${v} or v; + border = { + active = resolveColor parsed.border.active; + inactive = resolveColor parsed.border.inactive; + }; + # Resolve the icon theme once and expose it on nomarchy.theme so both # the GTK side (stylix.nix) and rofi (rofi.nix) agree. The shipped # package (papirus-icon-theme) carries the Dark/Light pair. @@ -61,7 +75,7 @@ let in { config = { - nomarchy.theme = parsed // { inherit iconTheme; }; + nomarchy.theme = parsed // { inherit iconTheme border; }; nomarchy.lib = { # "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax) diff --git a/theme-state.json b/theme-state.json index 635e11d..04b0e7b 100644 --- a/theme-state.json +++ b/theme-state.json @@ -18,6 +18,10 @@ "warn": "#e0af68", "bad": "#f7768e" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#32344a", "#f7768e", diff --git a/themes/catppuccin-latte.json b/themes/catppuccin-latte.json index a6565d7..321a28e 100644 --- a/themes/catppuccin-latte.json +++ b/themes/catppuccin-latte.json @@ -18,6 +18,10 @@ "warn": "#df8e1d", "bad": "#d20f39" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#bcc0cc", "#d20f39", diff --git a/themes/catppuccin.json b/themes/catppuccin.json index da34057..c7cb9f9 100644 --- a/themes/catppuccin.json +++ b/themes/catppuccin.json @@ -18,6 +18,10 @@ "warn": "#f9e2af", "bad": "#f38ba8" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#45475a", "#f38ba8", diff --git a/themes/ethereal.json b/themes/ethereal.json index 2b8fdc0..2ac204b 100644 --- a/themes/ethereal.json +++ b/themes/ethereal.json @@ -18,6 +18,10 @@ "warn": "#E9BB4F", "bad": "#ED5B5A" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#060B1E", "#ED5B5A", diff --git a/themes/everforest.json b/themes/everforest.json index 054406e..e604bbd 100644 --- a/themes/everforest.json +++ b/themes/everforest.json @@ -18,6 +18,10 @@ "warn": "#dbbc7f", "bad": "#e67e80" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#475258", "#e67e80", diff --git a/themes/flexoki-light.json b/themes/flexoki-light.json index e972540..4be4409 100644 --- a/themes/flexoki-light.json +++ b/themes/flexoki-light.json @@ -18,6 +18,10 @@ "warn": "#D0A215", "bad": "#D14D41" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#100F0F", "#D14D41", diff --git a/themes/gruvbox.json b/themes/gruvbox.json index a95691d..fd8c94a 100644 --- a/themes/gruvbox.json +++ b/themes/gruvbox.json @@ -18,6 +18,10 @@ "warn": "#d8a657", "bad": "#ea6962" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#3c3836", "#ea6962", diff --git a/themes/hackerman.json b/themes/hackerman.json index 39bd534..04d6518 100644 --- a/themes/hackerman.json +++ b/themes/hackerman.json @@ -18,6 +18,10 @@ "warn": "#50f7d4", "bad": "#50f872" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#0B0C16", "#50f872", diff --git a/themes/kanagawa.json b/themes/kanagawa.json index 96076d0..6bc93bb 100644 --- a/themes/kanagawa.json +++ b/themes/kanagawa.json @@ -18,6 +18,10 @@ "warn": "#c0a36e", "bad": "#c34043" }, + "border": { + "active": "text", + "inactive": "overlay" + }, "ansi": [ "#090618", "#c34043", diff --git a/themes/lumon.json b/themes/lumon.json index e8558df..554c34b 100644 --- a/themes/lumon.json +++ b/themes/lumon.json @@ -18,6 +18,10 @@ "warn": "#6fa4c9", "bad": "#4d86b0" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#1b2d40", "#4d86b0", diff --git a/themes/matte-black.json b/themes/matte-black.json index 714b5f2..a5432d2 100644 --- a/themes/matte-black.json +++ b/themes/matte-black.json @@ -18,6 +18,10 @@ "warn": "#b91c1c", "bad": "#D35F5F" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#333333", "#D35F5F", diff --git a/themes/miasma.json b/themes/miasma.json index bcc23cf..910f279 100644 --- a/themes/miasma.json +++ b/themes/miasma.json @@ -18,6 +18,10 @@ "warn": "#b36d43", "bad": "#685742" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#000000", "#685742", diff --git a/themes/nord.json b/themes/nord.json index 6c12550..b3f7910 100644 --- a/themes/nord.json +++ b/themes/nord.json @@ -18,6 +18,10 @@ "warn": "#ebcb8b", "bad": "#bf616a" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#3b4252", "#bf616a", diff --git a/themes/osaka-jade.json b/themes/osaka-jade.json index e794f56..78fc5ee 100644 --- a/themes/osaka-jade.json +++ b/themes/osaka-jade.json @@ -18,6 +18,10 @@ "warn": "#459451", "bad": "#FF5345" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#23372B", "#FF5345", diff --git a/themes/retro-82.json b/themes/retro-82.json index a5c9177..ccd05b6 100644 --- a/themes/retro-82.json +++ b/themes/retro-82.json @@ -18,6 +18,10 @@ "warn": "#e97b3c", "bad": "#f85525" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#00172e", "#f85525", diff --git a/themes/ristretto.json b/themes/ristretto.json index 528d5aa..eab2487 100644 --- a/themes/ristretto.json +++ b/themes/ristretto.json @@ -18,6 +18,10 @@ "warn": "#f9cc6c", "bad": "#fd6883" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#72696a", "#fd6883", diff --git a/themes/rose-pine.json b/themes/rose-pine.json index b11da41..9ada386 100644 --- a/themes/rose-pine.json +++ b/themes/rose-pine.json @@ -18,6 +18,10 @@ "warn": "#ea9d34", "bad": "#b4637a" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#f2e9e1", "#b4637a", diff --git a/themes/summer-day.json b/themes/summer-day.json index 29132ad..da9124a 100644 --- a/themes/summer-day.json +++ b/themes/summer-day.json @@ -18,6 +18,10 @@ "warn": "#dfa000", "bad": "#f85552" }, + "border": { + "active": "text", + "inactive": "overlay" + }, "ansi": [ "#5c6a72", "#f85552", diff --git a/themes/summer-night.json b/themes/summer-night.json index 488d3b1..99b07cf 100644 --- a/themes/summer-night.json +++ b/themes/summer-night.json @@ -18,6 +18,10 @@ "warn": "#d9bb80", "bad": "#e68183" }, + "border": { + "active": "text", + "inactive": "overlay" + }, "ansi": [ "#3c474d", "#e68183", diff --git a/themes/tokyo-night.json b/themes/tokyo-night.json index aa7b209..e60a0d4 100644 --- a/themes/tokyo-night.json +++ b/themes/tokyo-night.json @@ -18,6 +18,10 @@ "warn": "#e0af68", "bad": "#f7768e" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#32344a", "#f7768e", diff --git a/themes/vantablack.json b/themes/vantablack.json index fada473..ef3e4ca 100644 --- a/themes/vantablack.json +++ b/themes/vantablack.json @@ -18,6 +18,10 @@ "warn": "#cecece", "bad": "#a4a4a4" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#0d0d0d", "#a4a4a4", diff --git a/themes/white.json b/themes/white.json index b65f62f..97dff38 100644 --- a/themes/white.json +++ b/themes/white.json @@ -18,6 +18,10 @@ "warn": "#4a4a4a", "bad": "#2a2a2a" }, + "border": { + "active": "accent", + "inactive": "overlay" + }, "ansi": [ "#ffffff", "#2a2a2a",