aboutsummaryrefslogtreecommitdiff
path: root/assets/2026-06-19-collapsible-waybar-sides-spec.org
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-27 12:18:04 -0400
committerCraig Jennings <c@cjennings.net>2026-06-27 12:18:04 -0400
commit598e7276bc290ff174839bf6de33713bb7d96516 (patch)
tree791d6e04be3a875f93505605b07c00db9238b9a3 /assets/2026-06-19-collapsible-waybar-sides-spec.org
parentacaf68a5e322cbdf1672ded547408118bd97cb4e (diff)
downloadarchsetup-598e7276bc290ff174839bf6de33713bb7d96516.tar.gz
archsetup-598e7276bc290ff174839bf6de33713bb7d96516.zip
docs: file collapsible-waybar-sides spec to assets, close task
Diffstat (limited to 'assets/2026-06-19-collapsible-waybar-sides-spec.org')
-rw-r--r--assets/2026-06-19-collapsible-waybar-sides-spec.org120
1 files changed, 120 insertions, 0 deletions
diff --git a/assets/2026-06-19-collapsible-waybar-sides-spec.org b/assets/2026-06-19-collapsible-waybar-sides-spec.org
new file mode 100644
index 0000000..b9ddc0d
--- /dev/null
+++ b/assets/2026-06-19-collapsible-waybar-sides-spec.org
@@ -0,0 +1,120 @@
+#+TITLE: Collapsible waybar sides — implementation spec
+#+AUTHOR: Craig Jennings & Claude
+#+DATE: 2026-06-19
+
+* Goal
+Let each side of the waybar collapse to a minimal base set with a click, and
+expand again with another click. Each side carries a small arrowhead that points
+toward the screen edge when expanded (click to collapse outward) and flips to
+point toward center when collapsed (click to expand). Left and right collapse
+independently.
+
+This is dotfiles work (=~/.dotfiles=, =hyprland/= tier). Tracked by the
+=Collapsible waybar sides= task in archsetup =todo.org=.
+
+* Decisions (locked 2026-06-19)
+- *Mechanism*: config-swap + =killall -SIGUSR2 waybar=. NOT state-file + CSS —
+ the spike proved CSS can't collapse native modules (they go invisible but hold
+ their space; GTK3 has no =display:none=). See [[file:spike-findings.org]].
+- *Right base set*: =custom/date=, =custom/worldclock=, =tray= (plus the right
+ arrow). Tray reflows cleanly and survives the reload (spike-confirmed).
+- *Left base set*: =custom/menu=, =hyprland/workspaces= (plus the left arrow).
+- *Per-side*: left and right toggle independently, each with its own arrow.
+- *Per-host*: host-agnostic. The base set is constant; the full set is whatever
+ each host's config already defines. ratio (no battery/touchpad/airplane) needs
+ no special-casing — collapse hides whatever modules that host has. Build once.
+
+* Architecture
+
+** The active-config indirection (the core piece)
+=~/.config/waybar/config= is a stow symlink into the dotfiles, so the toggle
+can't rewrite it in place (that would edit the repo). Instead:
+
+1. *Canonical* config: the committed dotfiles config. Always holds the FULL
+ module arrays. Read-only source of truth. Unchanged by this feature except
+ for adding the two arrow modules and their definitions.
+2. *Active* config: a generated copy at =$XDG_RUNTIME_DIR/waybar/config=. This is
+ what waybar loads (=waybar -c=). The toggle rewrites its =modules-left= /
+ =modules-right= between full and base.
+3. *Launch change* (hyprland.conf exec-once): before launching waybar, generate
+ the active config from the canonical (initial state = expanded/full), then
+ =waybar -c "$XDG_RUNTIME_DIR/waybar/config" -s <style>=.
+
+The style.css stays shared (canonical, stowed) — only the config (module arrays)
+needs the runtime copy.
+
+** Toggle scripts
+=waybar-collapse <side>= where side ∈ {left, right}:
+1. Read per-side state from =$XDG_RUNTIME_DIR/waybar/<side>.state= (expanded |
+ collapsed; absent = expanded).
+2. Flip it.
+3. Regenerate the active config's =modules-<side>= array:
+ - expanded → the canonical full array for that side.
+ - collapsed → the base set for that side (constant in the script) with the
+ arrow module included.
+4. Write the new state file.
+5. =killall -SIGUSR2 waybar=.
+
+The full array is read from the canonical config each time, so the script never
+loses it and stays correct as modules are added/removed upstream. The base set is
+the only constant the script hardcodes (or reads from a tiny sidecar).
+
+** Arrow modules
+Two custom modules, =custom/arrow-left= and =custom/arrow-right=, each an exec
+script (=waybar-arrow left= / =waybar-arrow right=) that:
+- Reads the side's state file.
+- Emits the glyph: expanded → points outward (left side ◀ toward left edge,
+ right side ▶ toward right edge); collapsed → points inward (left ▶, right ◀).
+- =on-click= runs =waybar-collapse <side>=.
+
+The arrow is always in the base set (it's the expand control), so it's present in
+both states. Place the left arrow as the LAST module in =modules-left= (innermost,
+nearest center) and the right arrow as the FIRST module in =modules-right=
+(innermost), so each arrow sits at the inner edge of its side and the collapse
+pulls outward away from it. (Confirm placement during implementation — the glyph
+direction and module order must agree so the arrow visually points the right way.)
+
+** State + reload
+- State dir: =$XDG_RUNTIME_DIR/waybar/= (per-boot, ephemeral — collapse state
+ resets on logout, which is fine).
+- Reload is =SIGUSR2= (full waybar reload). Cost: brief flicker, module state
+ resets, tray re-registers. Acceptable for a click action; spike confirmed tray
+ survives. This cost is per-toggle, never idle.
+
+* Files (all in =~/.dotfiles/hyprland/=)
+- =.local/bin/waybar-collapse= — the toggle (reads canonical, writes active,
+ signals). New.
+- =.local/bin/waybar-arrow= — the arrow module exec (state → glyph + class). New.
+- =.local/bin/waybar-active-config= — generates the active config from canonical
+ at login (used by exec-once and reused by waybar-collapse to resolve the full
+ arrays). New. (Or fold generation into waybar-collapse + a one-shot init call.)
+- =.config/waybar/config= — add =custom/arrow-left= / =custom/arrow-right= module
+ defs + place them in the arrays. Edit.
+- =.config/hypr/hyprland.conf= — exec-once: generate active config, then
+ =waybar -c "$XDG_RUNTIME_DIR/waybar/config"=. Edit.
+- Optional keybinds: =$mod+[= / =$mod+]= to collapse left/right without the mouse.
+
+* TDD plan (per the dotfiles suite)
+- =tests/waybar-collapse/=: full↔base array rewrite against a fixture canonical
+ config; expanded→collapsed→expanded round-trips to the original arrays; state
+ file flips; base set always includes the arrow; SIGUSR2 sent (fake killall).
+ Use a fake canonical config + temp =$XDG_RUNTIME_DIR=, fake killall on PATH
+ (same harness style as tests/waybar-toggle).
+- =tests/waybar-arrow/=: state → correct glyph + class for each side and state;
+ missing state file = expanded glyph (fail-safe).
+- JSON validity of the generated active config (parse it back).
+
+* Open / to-confirm during implementation
+- Exact arrow glyphs (nerd-font triangles) and that order-vs-direction agree.
+- Whether to keep =hyprland/window= (the title) out of the left base set — it's
+ long and variable-width; collapsing the left should drop it (it's not in the
+ base set, so it hides — correct).
+- Animation: none (waybar doesn't animate width; the collapse snaps). Accepted.
+
+* Risks
+- Reload flicker on every toggle. Mitigation: none needed unless it annoys in use.
+- If a future module is added to the canonical config, it lands in the full set
+ automatically (good) but the author should decide if it belongs in a base set.
+- $XDG_RUNTIME_DIR active config must exist before waybar starts; the exec-once
+ ordering must generate it first. waybar-toggle (the crash-relaunch path, mod+B)
+ must also point at the active config, not the canonical — update it to match.