feat: centralize theme palette + add waybar bluetooth module
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>
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user