feat: icon themes — Papirus, resolved from the JSON, for GTK + rofi

Ships papirus-icon-theme and resolves an icon-theme name once in
theme.nix → nomarchy.theme.iconTheme: the JSON's optional `icons` field,
else Papirus-Dark/Light picked by `mode`. That single value feeds:
- Stylix `stylix.icons` → gtk.iconTheme (Thunar and GTK apps)
- rofi `show-icons` + `icon-theme` (the launcher now shows app icons)

A preset or theme-state.json can set `icons` to any theme in the icon
package to override per theme.

Verified: flake check green; iconTheme resolves Papirus-Dark for
tokyo-night and Papirus-Light for summer-day; gtk.enable true with
gtk.iconTheme.name set; papirus in home.packages and the live ISO
closure; rofi config.rasi carries icon-theme + show-icons:true. The
rendered icons need a real session to see.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-13 16:12:19 +01:00
parent 520c878bb3
commit f97054c804
4 changed files with 34 additions and 9 deletions

View File

@@ -280,8 +280,8 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot.
follow-ups (claude-code in nixpkgs is unfree — allowUnfree is on) follow-ups (claude-code in nixpkgs is unfree — allowUnfree is on)
- planned binds: `SUPER+Space``rofi -dmenu`/quick-launch and - planned binds: `SUPER+Space``rofi -dmenu`/quick-launch and
`SUPER+M``nomarchy-menu` (main menu); `SUPER+D` stays `-show drun` `SUPER+M``nomarchy-menu` (main menu); `SUPER+D` stays `-show drun`
- launcher icons: `show-icons` is off until the icon-theme item below - launcher icons: `show-icons` on, drawing from the theme's icon set
lands (rofi needs an installed icon theme to show app icons) (Papirus, via the icon-themes work below)
- decision record: resolves the old Walker/Lua question — no GTK4 - decision record: resolves the old Walker/Lua question — no GTK4
launcher, no second theming pipeline; the dispatcher owns the menu launcher, no second theming pipeline; the dispatcher owns the menu
structure, so the renderer stays swappable (we moved fuzzel → rofi 2.0 structure, so the renderer stays swappable (we moved fuzzel → rofi 2.0
@@ -317,11 +317,11 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot.
via a synchronous tag, so a multi-minute switch never reads as a failed via a synchronous tag, so a multi-minute switch never reads as a failed
selection. (An honest indeterminate indicator — HM gives no % — a selection. (An honest indeterminate indicator — HM gives no % — a
literal progress widget would be cosmetic; revisit only if wanted.) literal progress widget would be cosmetic; revisit only if wanted.)
- **Icon themes:** add `icon` to `theme-state.json`, have Stylix/GTK and - **Icon themes:** ✓ ships `papirus-icon-theme`; the resolved name lives on
rofi (`show-icons`) consume it, and ensure the chosen icon theme is `nomarchy.theme.iconTheme` (the JSON's optional `icons` field, else
pulled into the closure per active theme (a dark/light pair, e.g. Papirus-Dark/Light by `mode`) and feeds both Stylix's `gtk.iconTheme`
Papirus-Dark/Light, picked to match `mode`). Unblocks rofi launcher (Thunar/GTK apps) and rofi's `show-icons`. Remaining (optional): per-theme
icons and tidies Thunar/GTK app icons. `icons` overrides for the presets, or shipping more icon packs.
- **Nicer shell out of the box:** ship and default-configure a prompt - **Nicer shell out of the box:** ship and default-configure a prompt
(starship, themed from the JSON) plus modern-CLI ergonomics — (starship, themed from the JSON) plus modern-CLI ergonomics —
`bat`→cat, `eza`→ls, `ripgrep`→grep, `fd`→find, `zoxide`→cd — wired as `bat`→cat, `eza`→ls, `ripgrep`→grep, `fd`→find, `zoxide`→cd — wired as

View File

@@ -131,7 +131,8 @@ in
extraConfig = { extraConfig = {
modi = "drun,run"; modi = "drun,run";
show-icons = false; # no icon theme shipped yet — clean text list show-icons = true; # app icons via the theme's icon set
icon-theme = t.iconTheme; # resolved in theme.nix (Papirus-*/per-theme)
drun-display-format = "{name}"; drun-display-format = "{name}";
display-drun = "apps"; display-drun = "apps";
display-run = "run"; display-run = "run";

View File

@@ -55,6 +55,17 @@ in
size = lib.mkDefault 24; size = lib.mkDefault 24;
}; };
# GTK/file-manager/rofi icon theme, resolved from the JSON in
# theme.nix (per-theme `icons`, else Papirus-Dark/Light by mode).
# Stylix sets gtk.iconTheme from this; both dark/light point at the
# already-mode-resolved name.
icons = {
enable = true;
package = lib.mkDefault pkgs.papirus-icon-theme;
dark = t.iconTheme;
light = t.iconTheme;
};
fonts = { fonts = {
monospace = { monospace = {
name = t.fonts.mono; name = t.fonts.mono;

View File

@@ -44,11 +44,24 @@ let
blur = true; blur = true;
shadow = true; shadow = true;
}; };
# 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 = "";
}; };
parsed = lib.recursiveUpdate defaults themeState;
# 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.
iconTheme =
if parsed.icons != "" then parsed.icons
else if parsed.mode == "light" then "Papirus-Light"
else "Papirus-Dark";
in in
{ {
config = { config = {
nomarchy.theme = lib.recursiveUpdate defaults themeState; nomarchy.theme = parsed // { inherit iconTheme; };
nomarchy.lib = { nomarchy.lib = {
# "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax) # "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax)