1e3adbc842
Theme centralization: - theme/colors.json is now the single source of truth for the palette. - New theme/generate-theme.py renders, at install time, the three derived artifacts into ~/.config: colors.css (waybar/wofi @import), mako config, and hyprlock-colors.conf (hyprlang $tn_* variables). - theme/colors.css removed from the repo (now generated); install.sh calls the generator instead of the old inline mako snippet. - hyprlock.conf sources the generated color file and uses $tn_* variables instead of hardcoded rgba() values. - Generator covered by theme/test_generate_theme.py. Bluetooth: - Added waybar built-in bluetooth module (config.jsonc + style.css), with bluez/bluez-utils in packages.txt. Includes design spec and implementation plan under docs/superpowers/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
142 lines
6.5 KiB
Markdown
142 lines
6.5 KiB
Markdown
# Theme Centralization & Bluetooth Module — Design
|
|
|
|
Date: 2026-06-07
|
|
Status: Approved (pending spec review)
|
|
|
|
## Summary
|
|
|
|
Two independent enhancements to the niri dotfiles:
|
|
|
|
1. **Theme centralization** — collapse the duplicated color palette into a single
|
|
source of truth (`theme/colors.json`) and generate all derived configs from it
|
|
at install time. Bring `hyprlock` under the shared palette. Leave `alacritty`
|
|
untouched (out of scope).
|
|
2. **Bluetooth module** — add a waybar bluetooth indicator using the
|
|
already-installed `blueman`/`bluez` stack.
|
|
|
|
## Motivation
|
|
|
|
`CLAUDE.md` mandates a single source of truth and warns against duplicating
|
|
configs / hardcoding colors in multiple places. Current state violates this:
|
|
|
|
- `theme/colors.css` (`@define-color` palette) and `theme/colors.json` (same
|
|
palette as JSON) **both** hand-maintain the same 12 colors. Changing a color
|
|
requires editing both files.
|
|
- `hyprlock/hyprlock.conf` hardcodes 7 `rgba(...)` colors, every one of which
|
|
already exists in the palette.
|
|
|
|
Already-correct (not changed by this work):
|
|
|
|
- waybar (`waybar/style.css`) and wofi (`wofi/style.css`) `@import` `colors.css`.
|
|
- mako config is generated from `colors.json` by `install.sh`.
|
|
|
|
## Scope
|
|
|
|
**In scope:** unify the two palette files into one source; generate `colors.css`,
|
|
the mako config, and a hyprlock color file from it; convert `hyprlock.conf` to
|
|
reference the shared palette; add a waybar bluetooth module.
|
|
|
|
**Out of scope:** alacritty terminal colors (needs a full 16-color normal+bright
|
|
set the palette does not currently model — deferred); any change to the
|
|
Tomorrow Night palette values themselves; GTK theming (handled by Materia).
|
|
|
|
## Approach
|
|
|
|
Chosen approach **A**: `theme/colors.json` is the single source of truth;
|
|
everything else is generated at install time. This extends the existing Python
|
|
generation block already in `install.sh` (which generates the mako config).
|
|
Rejected: parsing `colors.css` as the source (fragile regex), and introducing a
|
|
new neutral source format (YAGNI for this scope, discards working JSON+Python).
|
|
|
|
## Detailed Design
|
|
|
|
### 1. Single source of truth
|
|
|
|
`theme/colors.json` remains the only hand-edited palette file. It holds the 12
|
|
base colors (already present). The hand-maintained `theme/colors.css` is
|
|
**deleted from the repo**; it becomes a generated artifact.
|
|
|
|
### 2. Generator: `theme/generate-theme.py`
|
|
|
|
A new standalone script, invoked by `install.sh`, replacing the current inline
|
|
Python mako snippet. Reads `theme/colors.json` and writes three artifacts
|
|
directly into `~/.config` (written, not symlinked — matching how mako is handled
|
|
today):
|
|
|
|
- **`~/.config/theme/colors.css`** — `@define-color` block for all 12 base
|
|
colors, plus the three alpha variants (`tn-bg-a90`, `tn-bg-a95`, `tn-bg-a96`)
|
|
computed from the `background` color at opacities 0.90 / 0.95 / 0.96. This is
|
|
what waybar and wofi already `@import`; their files do **not** change.
|
|
- **`~/.config/mako/config`** — same output as the current inline snippet.
|
|
- **`~/.config/theme/hyprlock-colors.conf`** — hyprlang variable declarations,
|
|
one per needed color, e.g. `$tn_fg = rgba(c5c8c6ff)`. Hex from `colors.json` is
|
|
converted to hyprlock's `rgba(RRGGBBAA)` form with `AA = ff`.
|
|
|
|
The generator must be idempotent and safe to re-run (overwrites its outputs).
|
|
|
|
### 3. hyprlock.conf
|
|
|
|
- Add `source = ~/.config/theme/hyprlock-colors.conf` near the top.
|
|
- Replace the 7 hardcoded `rgba(...)` values with the matching `$tn_*`
|
|
variables. Color → variable mapping (from current values):
|
|
- `rgba(c5c8c6ff)` → `$tn_fg` (foreground)
|
|
- `rgba(969896ff)` → `$tn_fg_dim` (foreground_dim)
|
|
- `rgba(282a2eff)` → `$tn_bg_alt` (background_alt)
|
|
- `rgba(81a2beff)` → `$tn_blue` (blue)
|
|
- `rgba(cc6666ff)` → `$tn_red` (red)
|
|
- `rgba(b5bd68ff)` → `$tn_green` (green)
|
|
- `hyprlock.conf` stays a hand-edited, symlinked file; only its colors come from
|
|
the generated source file.
|
|
|
|
**Risk + fallback:** hyprlock v0.9.5 uses the hyprlang parser, which documents
|
|
support for `$variables` and `source=`. This is verified by documentation, not
|
|
empirically (no dry-run flag; launching hyprlock grabs the screen). The
|
|
implementation plan MUST include an explicit parse test (lock once and confirm
|
|
colors render, or launch with `--grace 0` and watch `--verbose` for parse
|
|
errors). **Fallback if `source=`/variables misbehave:** generate the entire
|
|
`hyprlock.conf` from a `hyprlock/hyprlock.conf.tmpl` template with color
|
|
placeholders, instead of using `source=`. Same single-source outcome, more
|
|
generation.
|
|
|
|
### 4. install.sh changes
|
|
|
|
- Remove the inline `python3 - <<'PYEOF' ... PYEOF` mako block.
|
|
- Add a call to `python3 theme/generate-theme.py` after configs are linked.
|
|
- Remove the `ln -sf .../theme/colors.css ~/.config/theme/colors.css` line
|
|
(colors.css is now generated into that path, not symlinked).
|
|
- Ensure `~/.config/theme` exists before generation (already created).
|
|
|
|
### 5. Bluetooth waybar module
|
|
|
|
- `waybar/config.jsonc`: add `"bluetooth"` to `modules-right` (placed next to
|
|
`network`), with a `bluetooth` module block:
|
|
- `format`, `format-connected`, `format-disabled` using Nerd Font glyphs.
|
|
- `on-click`: `blueman-manager`.
|
|
- `waybar/style.css`: add a `#bluetooth` padding rule (consistent with the other
|
|
right-side modules) plus a connected-state accent color using a palette
|
|
variable (e.g. `@tn-blue`).
|
|
- Dependencies: `blueman` + `bluez`/`bluez-utils` (blueman pulls bluez). Confirm
|
|
`packages.txt` lists what's needed; the waybar bluetooth module requires the
|
|
`bluez` daemon running.
|
|
|
|
## Testing / Verification
|
|
|
|
- **Generator:** run `python3 theme/generate-theme.py`; diff generated
|
|
`~/.config/theme/colors.css` against the previous hand-written file to confirm
|
|
identical palette + alpha variants. Confirm mako config output unchanged.
|
|
- **waybar/wofi:** restart waybar (`waybar-restart`), confirm no CSS errors and
|
|
colors render. Open wofi, confirm styling intact.
|
|
- **hyprlock:** parse test per the fallback note above; confirm lock screen
|
|
colors match before/after.
|
|
- **Bluetooth:** confirm module appears, reflects adapter state, and
|
|
`blueman-manager` opens on click.
|
|
- **Idempotency:** re-run `install.sh`; confirm no errors and stable output.
|
|
|
|
## Rollout Notes
|
|
|
|
- Generated files (`~/.config/theme/colors.css`, `~/.config/theme/hyprlock-colors.conf`)
|
|
are not committed and not symlinked — consistent with the existing mako
|
|
generation. The committed `theme/colors.css` is removed in this change.
|
|
- The two features (theme, bluetooth) are independent and can be implemented and
|
|
verified separately.
|