From 234ab50a2c9289b32ddd4f915d9d3697900db2d9 Mon Sep 17 00:00:00 2001 From: Nickolaj Jepsen Date: Wed, 21 Jan 2026 00:07:34 +0100 Subject: [PATCH] refactor: centralize theme --- modules/base/default.nix | 1 + modules/base/theme.nix | 61 ++++++++++++++ modules/desktop/default.nix | 2 +- modules/desktop/dms/theme.nix | 37 ++++----- modules/desktop/gtk.nix | 138 ++++++++++++++++++++++++++++++++ modules/desktop/gtk/default.nix | 54 ------------- modules/desktop/gtk/theme.css | 78 ------------------ modules/desktop/niri.nix | 7 +- modules/homelab/glance.nix | 9 ++- modules/programs/ghostty.nix | 46 ++++++----- 10 files changed, 253 insertions(+), 180 deletions(-) create mode 100644 modules/base/theme.nix create mode 100644 modules/desktop/gtk.nix delete mode 100644 modules/desktop/gtk/default.nix delete mode 100644 modules/desktop/gtk/theme.css diff --git a/modules/base/default.nix b/modules/base/default.nix index 2dd40bf..a0f78e6 100644 --- a/modules/base/default.nix +++ b/modules/base/default.nix @@ -8,5 +8,6 @@ _: { ./home-manager.nix ./nix.nix ./secrets.nix + ./theme.nix ]; } diff --git a/modules/base/theme.nix b/modules/base/theme.nix new file mode 100644 index 0000000..20659f5 --- /dev/null +++ b/modules/base/theme.nix @@ -0,0 +1,61 @@ +# Centralized theme configuration (Flexoki-inspired) +# See: https://stephango.com/flexoki +{lib, ...}: { + options.fireproof.theme = let + mkColorOption = default: description: + lib.mkOption { + type = lib.types.str; + inherit default description; + example = default; + }; + in { + colors = { + # Background colors + bg = mkColorOption "1C1B1A" "Primary background color"; + bgAlt = mkColorOption "282726" "Alternative background color"; + + # Foreground colors + fg = mkColorOption "DAD8CE" "Primary foreground/text color"; + fgAlt = mkColorOption "B7B5AC" "Alternative foreground color"; + + # UI colors + muted = mkColorOption "878580" "Muted/disabled text color"; + ui = mkColorOption "343331" "UI element background"; + uiAlt = mkColorOption "403E3C" "Alternative UI element background"; + + # Base colors + black = mkColorOption "100F0F" "Black (darkest)"; + white = mkColorOption "DAD8CE" "White (same as fg)"; + whiteAlt = mkColorOption "F2F0E5" "Bright white"; + + # Accent color + accent = mkColorOption "CF6A4C" "Primary accent color"; + + # Semantic colors + red = mkColorOption "D14D41" "Red (errors, destructive)"; + redAlt = mkColorOption "AF3029" "Dark red"; + orange = mkColorOption "DA702C" "Orange (warnings)"; + orangeAlt = mkColorOption "BC5215" "Dark orange"; + yellow = mkColorOption "D0A215" "Yellow (caution)"; + yellowAlt = mkColorOption "AD8301" "Dark yellow"; + green = mkColorOption "879A39" "Green (success)"; + greenAlt = mkColorOption "66800B" "Dark green"; + cyan = mkColorOption "3AA99F" "Cyan"; + cyanAlt = mkColorOption "24837B" "Dark cyan"; + blue = mkColorOption "4385BE" "Blue (info, links)"; + blueAlt = mkColorOption "205EA6" "Dark blue"; + purple = mkColorOption "8B7EC8" "Purple"; + purpleAlt = mkColorOption "5E409D" "Dark purple"; + magenta = mkColorOption "CE5D97" "Magenta"; + magentaAlt = mkColorOption "A02F6F" "Dark magenta"; + }; + + # HSL variants for tools that need them (like Glance) + hsl = { + bg = mkColorOption "30 4 11" "Background in HSL"; + accent = mkColorOption "14 56 55" "Accent in HSL"; + green = mkColorOption "72 59 38" "Green in HSL"; + red = mkColorOption "5 64 54" "Red in HSL"; + }; + }; +} diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix index d8849e3..0e369cc 100644 --- a/modules/desktop/default.nix +++ b/modules/desktop/default.nix @@ -19,7 +19,7 @@ ./greetd.nix ./niri.nix ./qt.nix - ./gtk/default.nix + ./gtk.nix ./dms/default.nix ]; } diff --git a/modules/desktop/dms/theme.nix b/modules/desktop/dms/theme.nix index b10882f..cf8dc7e 100644 --- a/modules/desktop/dms/theme.nix +++ b/modules/desktop/dms/theme.nix @@ -4,29 +4,30 @@ ... }: let inherit (config.fireproof) username; + c = config.fireproof.theme.colors; in { config = lib.mkIf config.fireproof.desktop.enable { fireproof.home-manager = { home.file.".config/DankMaterialShell/colors.json".text = builtins.toJSON { name = "custom"; - primary = "#CF6A4C"; - primaryText = "#F2F0E5"; - primaryContainer = "#403E3C"; - secondary = "#CE5D97"; - surface = "#343331"; - surfaceText = "#DAD8CE"; - surfaceVariant = "#1C1B1A"; - surfaceVariantText = "#B7B5AC"; - surfaceTint = "#CF6A4C"; - background = "#100F0F"; - backgroundText = "#F2F0E5"; - outline = "#878580"; - surfaceContainer = "#1C1B1A"; - surfaceContainerHigh = "#282726"; - surfaceContainerHighest = "#403E3C"; - error = "#D14D41"; - warning = "#D0A215"; - info = "#4385BE"; + primary = "#${c.accent}"; + primaryText = "#${c.whiteAlt}"; + primaryContainer = "#${c.uiAlt}"; + secondary = "#${c.magenta}"; + surface = "#${c.ui}"; + surfaceText = "#${c.fg}"; + surfaceVariant = "#${c.bg}"; + surfaceVariantText = "#${c.fgAlt}"; + surfaceTint = "#${c.accent}"; + background = "#${c.black}"; + backgroundText = "#${c.whiteAlt}"; + outline = "#${c.muted}"; + surfaceContainer = "#${c.bg}"; + surfaceContainerHigh = "#${c.bgAlt}"; + surfaceContainerHighest = "#${c.uiAlt}"; + error = "#${c.red}"; + warning = "#${c.yellow}"; + info = "#${c.blue}"; matugen_type = "scheme-expressive"; }; diff --git a/modules/desktop/gtk.nix b/modules/desktop/gtk.nix new file mode 100644 index 0000000..956e196 --- /dev/null +++ b/modules/desktop/gtk.nix @@ -0,0 +1,138 @@ +{ + config, + lib, + pkgs, + ... +}: let + c = config.fireproof.theme.colors; + + # Generate GTK CSS from centralized theme + themeCss = '' + @define-color bg #${c.bg}; + @define-color bg-alt #${c.bgAlt}; + @define-color fg #${c.fg}; + @define-color fg-alt #${c.fgAlt}; + @define-color muted #${c.muted}; + @define-color ui #${c.ui}; + @define-color ui-alt #${c.uiAlt}; + @define-color black #${c.black}; + @define-color accent #${c.accent}; + @define-color red #${c.red}; + @define-color red-alt #${c.redAlt}; + @define-color orange #${c.orange}; + @define-color orange-alt #${c.orangeAlt}; + @define-color yellow #${c.yellow}; + @define-color yellow-alt #${c.yellowAlt}; + @define-color green #${c.green}; + @define-color green-alt #${c.greenAlt}; + @define-color cyan #${c.cyan}; + @define-color cyan-alt #${c.cyanAlt}; + @define-color blue #${c.blue}; + @define-color blue-alt #${c.blueAlt}; + @define-color purple #${c.purple}; + @define-color purple-alt #${c.purpleAlt}; + @define-color magenta #${c.magenta}; + @define-color magenta-alt #${c.magentaAlt}; + @define-color white #${c.white}; + @define-color white-alt #${c.whiteAlt}; + + /* Adwaita stuff */ + @define-color accent_color @accent; + @define-color accent_bg_color @accent; + @define-color accent_fg_color @fg; + + @define-color window_bg_color @bg; + @define-color window_fg_color @fg; + + @define-color headerbar_bg_color @bg-alt; + @define-color headerbar_fg_color @fg; + + @define-color popover_bg_color @bg-alt; + @define-color popover_fg_color @fg; + + @define-color dialog_bg_color @popover_bg_color; + @define-color dialog_fg_color @popover_fg_color; + + @define-color sidebar_bg_color @bg-alt; + @define-color sidebar_fg_color @fg; + @define-color sidebar_backdrop_color @bg-alt; + @define-color sidebar_shade_color rgba(0, 0, 0, 0.25); + @define-color sidebar_border_color rgba(0, 0, 0, 0.36); + + @define-color secondary_sidebar_bg_color @sidebar_backdrop_color; + @define-color secondary_sidebar_fg_color @fg; + @define-color secondary_sidebar_backdrop_color @sidebar_backdrop_color; + @define-color secondary_sidebar_shade_color @sidebar_shade_color; + @define-color secondary_sidebar_border_color @sidebar_border_color; + + @define-color view_bg_color @bg; + @define-color view_fg_color @fg; + + @define-color card_bg_color @bg-alt; + @define-color card_fg_color @fg; + + @define-color thumbnail_bg_color @bg-alt; + @define-color thumbnail_fg_color @fg; + + @define-color warning_bg_color @red; + @define-color warning_fg_color @fg; + @define-color warning_color @red; + @define-color error_bg_color @red; + @define-color error_fg_color @fg; + @define-color error_color @red; + @define-color success_bg_color @green; + @define-color success_fg_color @fg; + @define-color success_color @green; + @define-color destructive_bg_color @red; + @define-color destructive_fg_color @fg; + @define-color destructive_color @red; + ''; +in { + config = lib.mkIf config.fireproof.desktop.enable { + environment.systemPackages = with pkgs; [ + nautilus + gnome-photos + ]; + + services.gvfs.enable = true; + programs = { + dconf.enable = true; + nautilus-open-any-terminal.enable = true; + seahorse.enable = true; + evince.enable = true; + }; + + services.gnome.sushi.enable = true; + + fireproof.home-manager = { + home.pointerCursor = { + gtk.enable = true; + name = "Adwaita"; + package = pkgs.adwaita-icon-theme; + size = 24; + }; + + gtk = { + enable = true; + theme = { + name = "adw-gtk3-dark"; + package = pkgs.adw-gtk3; + }; + iconTheme = { + name = "Qogir-dark"; + package = pkgs.qogir-icon-theme; + }; + + gtk3.extraConfig = {gtk-application-prefer-dark-theme = true;}; + gtk3.extraCss = themeCss; + + gtk4.extraConfig = {gtk-application-prefer-dark-theme = true;}; + gtk4.extraCss = themeCss; + }; + dconf = { + enable = true; + settings."org/gnome/desktop/interface".color-scheme = "prefer-dark"; + }; + }; + }; +} diff --git a/modules/desktop/gtk/default.nix b/modules/desktop/gtk/default.nix deleted file mode 100644 index 50efd7c..0000000 --- a/modules/desktop/gtk/default.nix +++ /dev/null @@ -1,54 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: { - config = lib.mkIf config.fireproof.desktop.enable { - environment.systemPackages = with pkgs; [ - nautilus - gnome-photos - ]; - - services.gvfs.enable = true; - programs = { - dconf.enable = true; - nautilus-open-any-terminal.enable = true; - seahorse.enable = true; - evince.enable = true; - }; - - services.gnome.sushi.enable = true; - - fireproof.home-manager = { - home.pointerCursor = { - gtk.enable = true; - name = "Adwaita"; - package = pkgs.adwaita-icon-theme; - size = 24; - }; - - gtk = { - enable = true; - theme = { - name = "adw-gtk3-dark"; - package = pkgs.adw-gtk3; - }; - iconTheme = { - name = "Qogir-dark"; - package = pkgs.qogir-icon-theme; - }; - - gtk3.extraConfig = {gtk-application-prefer-dark-theme = true;}; - gtk3.extraCss = builtins.readFile ./theme.css; - - gtk4.extraConfig = {gtk-application-prefer-dark-theme = true;}; - gtk4.extraCss = builtins.readFile ./theme.css; - }; - dconf = { - enable = true; - settings."org/gnome/desktop/interface".color-scheme = "prefer-dark"; - }; - }; - }; -} diff --git a/modules/desktop/gtk/theme.css b/modules/desktop/gtk/theme.css deleted file mode 100644 index bbd6ab9..0000000 --- a/modules/desktop/gtk/theme.css +++ /dev/null @@ -1,78 +0,0 @@ -@define-color bg #1C1B1A; -@define-color bg-alt #282726; -@define-color fg #DAD8CE; -@define-color fg-alt #B7B5AC; -@define-color muted #878580; -@define-color ui #343331; -@define-color ui-alt #403E3C; -@define-color black #100F0F; -@define-color accent #CF6A4C; -@define-color red #D14D41; -@define-color red-alt #AF3029; -@define-color orange #DA702C; -@define-color orange-alt #BC5215; -@define-color yellow #D0A215; -@define-color yellow-alt #AD8301; -@define-color green #879A39; -@define-color green-alt #66800B; -@define-color cyan #3AA99F; -@define-color cyan-alt #24837B; -@define-color blue #4385BE; -@define-color blue-alt #205EA6; -@define-color purple #8B7EC8; -@define-color purple-alt #5E409D; -@define-color magenta #CE5D97; -@define-color magenta-alt #A02F6F; -@define-color white #DAD8CE; -@define-color white-alt #F2F0E5; - -/* Adwaita stuff */ -@define-color accent_color @accent; -@define-color accent_bg_color @accent; -@define-color accent_fg_color @fg; - -@define-color window_bg_color @bg; -@define-color window_fg_color @fg; - -@define-color headerbar_bg_color @bg-alt; -@define-color headerbar_fg_color @fg; - -@define-color popover_bg_color @bg-alt; -@define-color popover_fg_color @fg; - -@define-color dialog_bg_color @popover_bg_color; -@define-color dialog_fg_color @popover_fg_color; - -@define-color sidebar_bg_color @bg-alt; -@define-color sidebar_fg_color @fg; -@define-color sidebar_backdrop_color @bg-alt; -@define-color sidebar_shade_color rgba(0, 0, 0, 0.25); -@define-color sidebar_border_color rgba(0, 0, 0, 0.36); - -@define-color secondary_sidebar_bg_color @sidebar_backdrop_color; -@define-color secondary_sidebar_fg_color @fg; -@define-color secondary_sidebar_backdrop_color @sidebar_backdrop_color; -@define-color secondary_sidebar_shade_color @sidebar_shade_color; -@define-color secondary_sidebar_border_color @sidebar_border_color; - -@define-color view_bg_color @bg; -@define-color view_fg_color @fg; - -@define-color card_bg_color @bg-alt; -@define-color card_fg_color @fg; - -@define-color thumbnail_bg_color @bg-alt; -@define-color thumbnail_fg_color @fg; - -@define-color warning_bg_color @red; -@define-color warning_fg_color @fg; -@define-color warning_color @red; -@define-color error_bg_color @red; -@define-color error_fg_color @fg; -@define-color error_color @red; -@define-color success_bg_color @green; -@define-color success_fg_color @fg; -@define-color success_color @green; -@define-color destructive_bg_color @red; -@define-color destructive_fg_color @fg; -@define-color destructive_color @red; diff --git a/modules/desktop/niri.nix b/modules/desktop/niri.nix index 1ecf98d..117b1f1 100644 --- a/modules/desktop/niri.nix +++ b/modules/desktop/niri.nix @@ -5,6 +5,7 @@ inputs, ... }: let + c = config.fireproof.theme.colors; hasMonitors = config.monitors != []; primaryMonitorName = if hasMonitors @@ -41,12 +42,12 @@ in { layout = { gaps = 10; focus-ring.enable = false; - insert-hint.display.color = "#CF6A4C"; + insert-hint.display.color = "#${c.accent}"; border = { enable = true; width = 2; - active.color = "#CF6A4C"; - inactive.color = "#343331"; + active.color = "#${c.accent}"; + inactive.color = "#${c.ui}"; }; tab-indicator = { hide-when-single-tab = true; diff --git a/modules/homelab/glance.nix b/modules/homelab/glance.nix index c90651b..57f7383 100644 --- a/modules/homelab/glance.nix +++ b/modules/homelab/glance.nix @@ -5,6 +5,7 @@ ... }: lib.mkIf config.fireproof.homelab.enable (let + hsl = config.fireproof.theme.hsl; domain = "glance.nickolaj.com"; port = 8088; @@ -50,10 +51,10 @@ in { base-url = "https://${domain}"; }; theme = { - background-color = "30 4 11"; # #1C1B1A (HSL) - primary-color = "14 56 55"; # #CF6A4C accent (HSL) - positive-color = "72 59 38"; # #879A39 green (HSL) - negative-color = "5 64 54"; # #D14D41 red (HSL) + background-color = hsl.bg; + primary-color = hsl.accent; + positive-color = hsl.green; + negative-color = hsl.red; contrast-multiplier = 1.1; text-saturation-multiplier = 1.0; custom-css-file = "https://${domain}/custom.css"; diff --git a/modules/programs/ghostty.nix b/modules/programs/ghostty.nix index f8dfaaa..284bdbb 100644 --- a/modules/programs/ghostty.nix +++ b/modules/programs/ghostty.nix @@ -4,7 +4,9 @@ lib, pkgs, ... -}: { +}: let + c = config.fireproof.theme.colors; +in { config = lib.mkIf config.fireproof.desktop.enable { environment.systemPackages = with pkgs; [ ghostty @@ -22,29 +24,29 @@ }; themes = { fireproof = { - background = "1C1B1A"; - cursor-color = "DAD8CE"; - foreground = "DAD8CE"; + background = c.bg; + cursor-color = c.fg; + foreground = c.fg; palette = [ - "0=#100F0F" - "1=#AF3029" - "2=#66800B" - "3=#AD8301" - "4=#205EA6" - "5=#A02F6F" - "6=#24837B" - "7=#DAD8CE" - "8=#878580" - "9=#D14D41" - "10=#879A39" - "11=#D0A215" - "12=#4385BE" - "13=#CE5D97" - "14=#3AA99F" - "15=#F2F0E5" + "0=#${c.black}" + "1=#${c.redAlt}" + "2=#${c.greenAlt}" + "3=#${c.yellowAlt}" + "4=#${c.blueAlt}" + "5=#${c.magentaAlt}" + "6=#${c.cyanAlt}" + "7=#${c.fg}" + "8=#${c.muted}" + "9=#${c.red}" + "10=#${c.green}" + "11=#${c.yellow}" + "12=#${c.blue}" + "13=#${c.magenta}" + "14=#${c.cyan}" + "15=#${c.whiteAlt}" ]; - selection-background = "403E3C"; - selection-foreground = "DAD8CE"; + selection-background = c.uiAlt; + selection-foreground = c.fg; }; }; };