diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-15 17:04:07 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-15 17:04:07 +0200 |
| commit | fea331158915713d980bafde6c38a6954d5c233b (patch) | |
| tree | 7d1e4ffa274814b904bf924d6d642c61536be860 | |
| parent | a90fac477be6db6cbae563d1a29645e5eb215852 (diff) | |
| download | waybar-theme-udt-fea331158915713d980bafde6c38a6954d5c233b.tar.gz waybar-theme-udt-fea331158915713d980bafde6c38a6954d5c233b.zip | |
feat: move the desktop bar to DP-1, and add the mail module
The two bars were both on DP-3, which put the workspaces and the window list
on a rotated 1080px screen while 2560px sat unused next to it. Status stays on
DP-3 alone; the desktop itself moved to DP-1, where the window list has room.
This replaces the stock bar rather than sitting beside it, so hyprland's
autostart now launches this config instead of a bare waybar. ~/.config/waybar
is left on disk, but nothing reads it.
Mail comes over from the stock bar as the same notmuch watcher, minus the
glyph: the envelope is a CSS background and the unread count stays text,
because the count is the content rather than decoration, exactly like the
clock. Its format carries a trailing space so the pill survives the empty
state, since the watcher emits an empty text when nothing is unread and
waybar draws no widget at all for a custom module whose output is empty.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| -rw-r--r-- | README.md | 24 | ||||
| -rw-r--r-- | SPEC.md | 22 | ||||
| -rwxr-xr-x | bin/wb-icon | 2 | ||||
| -rw-r--r-- | config.jsonc | 14 | ||||
| -rwxr-xr-x | install.sh | 15 | ||||
| -rw-r--r-- | modules/custom/mail.jsonc | 27 | ||||
| -rw-r--r-- | styles/modules.css | 30 | ||||
| -rw-r--r-- | styles/pills.css | 8 |
8 files changed, 111 insertions, 31 deletions
@@ -4,19 +4,23 @@ Two waybar bars for DP-3: pill clusters, icons from the desktop's own icon theme instead of font glyphs, and colours driven by [unified-desktop-theme](../unified-desktop-theme). - top [📅 Wed 15/09] [🕑 14:32] [●●] [S] [●] [🔊] [tray] [⏻] [🇮🇹] - bottom [1..8] [ open windows ] + DP-3 [📅 Wed 15/09] [🕑 14:32] [●] [S] [●] [✉ 9] [🔊] [tray] [⏻] [🇮🇹] + DP-1 [1..8] [ open windows ] Each bracket is a pill. Pills group into clusters with gaps between them, so the bars read as a few objects rather than one strip. Hover cross-fades background and text over 0.3s; taskbar buttons underline in the accent. -DP-3 is rotated, so a bar there is 1080px wide rather than 1920, and one bar -holding everything was too crowded. Status sits on top, the desktop itself -(workspaces and open windows) along the bottom. Both bars are one waybar +DP-3 is rotated, so a bar there is only 1080px wide, which is why it carries +status alone. The desktop itself, the workspaces and the window list, sits on +DP-1 where there are 2560px to spread them across. Both bars are one waybar process reading one stylesheet: waybar takes a top-level array of bars, so they cannot drift apart. +This replaces the stock bar. Hyprland starts it from +`~/.config/hypr/sections/autostart.lua`; `~/.config/waybar/` is left on disk +but nothing reads it. + ## Install ./install.sh @@ -74,11 +78,11 @@ their national colours. | Bar | Cluster | Modules | | --- | --- | --- | -| top | left | date, time, VM dots | -| top | centre | launcher | -| top | right | privacy dots, volume drawer, tray, presentation mode, language | -| bottom | left | workspaces | -| bottom | right | open windows | +| DP-3 | left | date, time, VM dots | +| DP-3 | centre | launcher | +| DP-3 | right | privacy dots, mail, volume drawer, tray, presentation mode, language | +| DP-1 | left | workspaces | +| DP-1 | right | open windows | No battery, temperature, CPU, memory or backlight: this is a desktop. @@ -23,17 +23,22 @@ pointed at DP-3. ## Layout - top [📅 Wed 15/09] [🕑 14:32] [●●] [S] [●] [🔊] [tray] [⏻] [🇮🇹] - date time vm launcher priv vol tray present lang + DP-3 [📅 Wed 15/09] [🕑 14:32] [●] [S] [●] [✉ 9] [🔊] [tray] [⏻] [🇮🇹] + date time vm launcher priv mail vol tray present lang - bottom [1..8] [ open windows ] - workspaces taskbar + DP-1 [1..8] [ open windows ] + workspaces taskbar -DP-3 is rotated, so a bar there is 1080px wide rather than 1920. One bar -holding every module was too crowded at that width, so status sits on top and -the desktop itself along the bottom. Both are one waybar process reading one +DP-3 is rotated, so a bar there is only 1080px wide. One bar holding every +module was too crowded at that width, so status stays on DP-3 alone and the +desktop itself, the workspaces and the window list, moved to DP-1 where there +are 2560px to spread them across. Both are one waybar process reading one stylesheet: waybar takes a top-level array of bars. +This replaces the stock bar rather than sitting beside it. Hyprland starts it +from `~/.config/hypr/sections/autostart.lua`, which used to launch a bare +`waybar`; `~/.config/waybar/` is left on disk but nothing reads it. + Each bracket is one pill. Neighbouring pills in a cluster share a background and weld together with asymmetric corner radii; clusters are separated by transparent gaps, so the bar reads as groups rather than a continuous strip. @@ -50,7 +55,8 @@ transparent gaps, so the bar reads as groups rather than a continuous strip. | center | `wlr/taskbar` | `icon-theme` config key | Per-window application icons. | | right | `group/wireplumber` | `image` module | Drawer group kept as it is today. | | right | `tray` | application-provided | | -| right | `custom/presentation` | CSS, keyed on the module's class | Presentation mode, the same `statusctl`-backed module the DP-1 bar runs. It already emits an empty text and a state class, so the icon is chosen in CSS and the glyphs are simply dropped. | +| right | `custom/mail` | CSS, plus the count as text | Unread mail, the same notmuch watcher the stock bar ran. The envelope is a CSS background; the count stays text, because it is content rather than decoration, exactly like the clock. | +| right | `custom/presentation` | CSS, keyed on the module's class | Presentation mode, the same `statusctl`-backed module the stock bar ran. It already emits an empty text and a state class, so the icon is chosen in CSS and the glyphs are simply dropped. | | right | `image#lang` | `flag-it.svg` / `flag-gb.svg`, shipped here | An `image` module: `hyprland/language` styles as `#language` only, with no per-language class, so a flag cannot be selected in CSS. | Dropped from the current bar: `custom/breaktimer`, `custom/mail`, diff --git a/bin/wb-icon b/bin/wb-icon index b8f91cc..9e011b9 100755 --- a/bin/wb-icon +++ b/bin/wb-icon @@ -119,10 +119,12 @@ def selftest(): "x-office-presentation", # on "dialog-warning", # no state file ] + mail_icons = ["mail-unread"] names = sorted( {n for group in ICONS.values() for n in group.values()} | set(workspace_icons) | set(clock_icons) | set(presentation_icons) + | set(mail_icons) ) missing = [n for n in names if not lookup(n)] for n in names: diff --git a/config.jsonc b/config.jsonc index a7c5ff9..1d94a39 100644 --- a/config.jsonc +++ b/config.jsonc @@ -1,13 +1,13 @@ -// waybar-theme-udt: two bars on DP-3. +// waybar-theme-udt: the status bar on DP-3, the desktop bar on DP-1. // Copyright (C) 2026 Danilo M. <danix@danix.xyz> // Licensed under the GNU General Public License v2 only. // // A top-level array is how waybar takes more than one bar. Both bars are one // process reading one stylesheet, so the pills stay consistent between them. // -// DP-3 is rotated, so the bar is 1080px rather than 1920: one bar holding -// everything was too crowded at that width. Status lives on top, the desktop -// (workspaces and open windows) along the bottom. +// DP-3 is rotated and only 1080px wide, which is why it carries status alone. +// The desktop itself, the workspaces and the window list, sits on DP-1 where +// there are 2560px to spread them across. // // One file per module, included explicitly: wildcard `include` has been broken // since waybar v0.14.0, so every module file has to be listed by name. @@ -18,6 +18,7 @@ "$HOME/.config/waybar-udt/modules/custom/vmdot.jsonc", "$HOME/.config/waybar-udt/modules/image/launcher.jsonc", "$HOME/.config/waybar-udt/modules/custom/privacy_dots.jsonc", + "$HOME/.config/waybar-udt/modules/custom/mail.jsonc", "$HOME/.config/waybar-udt/modules/image/volume.jsonc", "$HOME/.config/waybar-udt/modules/extras/tray.jsonc", "$HOME/.config/waybar-udt/modules/custom/presentation.jsonc", @@ -34,6 +35,7 @@ ], "modules-right": [ "custom/privacy_dots", + "custom/mail", "group/volume", "tray", "custom/presentation", @@ -64,8 +66,8 @@ ], "layer": "top", - "output": "DP-3", - "position": "bottom", + "output": "DP-1", + "position": "top", "height": 0, "width": 0, "margin": 0, @@ -3,10 +3,13 @@ # Copyright (C) 2026 Danilo M. <danix@danix.xyz> # Licensed under the GNU General Public License v2 only. # -# This installs a SECOND bar, at ~/.config/waybar-udt/. The existing bar at -# ~/.config/waybar/ is left alone, so DP-1 keeps working while this one is -# tried on DP-3. Nothing is started: the command to run it is printed at the -# end. +# Installs to ~/.config/waybar-udt/, which is a separate config directory from +# the stock ~/.config/waybar/: that one is left on disk untouched, so its +# modules and scripts stay available to go back to. +# +# Nothing is started here. Hyprland launches the bar on login from +# ~/.config/hypr/sections/autostart.lua; the command is printed at the end for +# starting it by hand. set -euo pipefail repo="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -86,7 +89,7 @@ ln -sfn "$repo/config.jsonc" "$target/config.jsonc" for f in modules/clock.jsonc \ modules/hyprland/workspaces.jsonc \ modules/custom/vmdot.jsonc modules/custom/privacy_dots.jsonc \ - modules/custom/presentation.jsonc \ + modules/custom/presentation.jsonc modules/custom/mail.jsonc \ modules/extras/taskbar.jsonc modules/extras/tray.jsonc \ modules/image/volume.jsonc modules/image/language.jsonc; do ln -sfn "$repo/$f" "$target/$f" @@ -146,4 +149,4 @@ ln -sfn "$repo/bin/wb-lang" "$HOME/bin/wb-lang" echo echo "installed to $target" echo "run it with: waybar -c $target/config.jsonc -s $target/styles/style.css" -echo "your existing bar on DP-1 is untouched." +echo "hyprland starts it on login; see ~/.config/hypr/sections/autostart.lua" diff --git a/modules/custom/mail.jsonc b/modules/custom/mail.jsonc new file mode 100644 index 0000000..65cd9e8 --- /dev/null +++ b/modules/custom/mail.jsonc @@ -0,0 +1,27 @@ +// Unread mail, the same watcher the DP-1 bar runs. +// +// The count is read from the local notmuch index rather than polled from the +// Gmail API, so it drops the moment mail is read in qtmaildir and rises the +// moment mbsync commits. No "interval": the script runs in continuous mode, +// printing one JSON line per notmuch commit, and waybar owns the watcher +// process, which is why there is no daemon to supervise. +// +// The envelope is a CSS background rather than the DP-1 bar's glyph, but the +// count stays text: it is the content, not decoration, exactly like the clock. +// +// The format keeps a trailing space so it is never empty. The script emits +// {"text":""} with class "empty" when nothing is unread, and waybar draws no +// widget at all for a custom module whose formatted output is empty: not an +// empty pill, no pill. The space keeps the envelope on the bar at zero unread. +// +// See ~/Programming/GIT/quickshell/desktop/modules/mail/README.md +{ + "custom/mail": { + "format": "{} ", + "return-type": "json", + "exec": "$HOME/Programming/GIT/quickshell/desktop/modules/mail/waybar-mail.sh", + "on-click": "qs -p $HOME/Programming/GIT/quickshell/desktop ipc call drawer open mail", + "on-click-right": "$HOME/bin/mailsync.sh", + "tooltip": false + } +} diff --git a/styles/modules.css b/styles/modules.css index 4d3d38e..9044455 100644 --- a/styles/modules.css +++ b/styles/modules.css @@ -106,6 +106,36 @@ min-width: 22px; } +/* ------------------------------------------------------ * + * Mail: envelope icon, unread count as text. * + * * + * The count is content rather than decoration, so it stays * + * text like the clock. The state comes from the watcher's * + * class: nothing unread is dim, a dead watcher is loud. * + * ------------------------------------------------------ */ + +#custom-mail { + background-image: url("@ICONS@/actions/22/mail-unread.svg"); + background-repeat: no-repeat; + background-position: 10px center; + background-size: 16px 16px; + padding-left: 32px; + min-height: 16px; +} + +#custom-mail.empty { + color: @main-fg; + opacity: 0.45; +} + +#custom-mail.unread { + color: @main-fg; +} + +#custom-mail.error { + color: @critical; +} + /* ------------------------------------------- * * Dots: coloured by their scripts, not by CSS. * * ------------------------------------------- */ diff --git a/styles/pills.css b/styles/pills.css index 40c6629..93a8855 100644 --- a/styles/pills.css +++ b/styles/pills.css @@ -19,6 +19,7 @@ #custom-vmdot, #taskbar, #custom-privacy_dots, +#custom-mail, #volume, #tray, #custom-presentation, @@ -38,6 +39,7 @@ #clock.time:hover, #custom-vmdot:hover, #custom-privacy_dots:hover, +#custom-mail:hover, #volume:hover, #tray:hover, #custom-presentation:hover, @@ -78,11 +80,15 @@ margin-left: 6px; } -/* Right: privacy | volume | tray | presentation | language */ +/* Right: privacy | mail | volume | tray | presentation | language */ #custom-privacy_dots { margin-right: 6px; } +#custom-mail { + margin-right: 6px; +} + #volume { margin-right: 6px; } |
