Flake for my NixOS devices
1{inputs, ...}: {
2 config,
3 lib,
4 pkgs,
5 ...
6}: {
7 options.cow.waybar.enable =
8 lib.mkEnableOption "Waybar + customizations"
9 // {
10 default = config.cow.gdi.enable;
11 };
12
13 config = let
14 catppuccinCss = pkgs.fetchurl {
15 url = "https://github.com/catppuccin/waybar/raw/refs/heads/main/themes/mocha.css";
16 hash = "sha256-puMFl8zIKOiYhE6wzqnffXOHn/VnKmpVDzrMJMk+3Rc=";
17 };
18 in
19 lib.mkIf config.cow.waybar.enable {
20 programs.waybar = {
21 enable = true;
22 systemd.enable = true;
23 style = ''
24 @import "${catppuccinCss}";
25
26 * {
27 font-family: sans-serif;
28 }
29
30 window#waybar {
31 background: rgba(49, 50, 68, 0.65);
32 color: @text;
33 }
34
35 .modules-left > * > *,
36 .modules-right > * > * {
37 font-size: 1.5rem;
38 background: @crust;
39 border: 2px solid @base;
40 border-radius: 5rem;
41 padding: 5px 15px;
42 margin: 5px 2px;
43 }
44
45 #bluetooth.disabled {
46 border-color: @red;
47 }
48
49 #waybar .modules-left > *:first-child > * {
50 margin-left: 25px;
51 }
52
53 #waybar .modules-right > *:last-child > * {
54 margin-right: 25px;
55 }
56
57 #waybar .modules-left,
58 #waybar .modules-right {
59 margin-top: 10px;
60 margin-bottom: 5px;
61 }
62
63 #waybar .modules-center {
64 margin-top: 5px;
65 margin-bottom: 5px;
66 }
67
68 #battery.warning {
69 border-color: @yellow;
70 }
71
72 #battery.critical {
73 border-color: @red;
74 }
75
76 * > #battery.charging {
77 border-color: @green;
78 }
79
80 #taskbar,
81 #workspaces {
82 padding: 10px;
83 border-radius: 5rem;
84 border: none;
85 background: none;
86 }
87
88 #taskbar button,
89 #workspaces button {
90 color: @text;
91 border-radius: 5rem;
92 padding: 5px 15px;
93 margin: 0 5px;
94 background: @crust;
95 border: 2px solid @base;
96 }
97
98 #taskbar button:hover, #workspaces button:hover {
99 background: @mantle;
100 }
101
102 #workspaces button {
103 font-size: 1.5rem;
104 }
105
106 #cpu,
107 #memory,
108 #temperature {
109 font-size: 1.5rem;
110 padding: 10px 25px;
111 }
112
113 #cpu.warning,
114 #memory.warning {
115 border-color: @yellow;
116 }
117
118 #cpu.critical,
119 #memory.critical,
120 #temperature.critical {
121 border-color: @red;
122 }
123
124 #workspaces button.active {
125 border: 2px solid @sapphire;
126 }
127
128 #taskbar button.active {
129 border: 2px solid @sapphire;
130 }
131
132 #idle_inhibitor.activated {
133 border-color: @mauve;
134 }
135
136 #custom-notification.notification {
137 border-color: @sapphire;
138 }
139
140 #custom-notification.dnd-none,
141 #custom-notification.dnd-notification,
142 #custom-notification.dnd-inhibited-none,
143 #custom-notification.dnd-inhibited-notification {
144 border-color: @red;
145 }
146
147 #custom-notification.inhibited-none,
148 #custom-notification.inhibited-notification {
149 border-color: @mauve;
150 }
151
152 #network.disconnected {
153 border-color: @red;
154 }
155
156 #privacy {
157 background: none;
158 border: none;
159 margin: 0;
160 padding: 0;
161 }
162
163 #privacy-item {
164 font-size: 1.5rem;
165 border-radius: 5rem;
166 padding: 5px 15px;
167 margin: 5px 2px;
168 border: 2px solid @red;
169 background-color: @crust;
170 }
171
172 #custom-weather.VeryCloudy,
173 #custom-weather.Cloudy,
174 #custom-weather.Fog {
175 border-color: @overlay0;
176 }
177
178 #custom-weather.HeavyRain,
179 #custom-weather.ThunderyHeavyRain,
180 #custom-weather.ThunderyRain,
181 #custom-weather.ThunderyShowers,
182 #custom-weather.HeavyShowers,
183 #custom-weather.LightRain,
184 #custom-weather.LightShowers {
185 border-color: @blue;
186 }
187
188 #custom-weather.HeavySnow,
189 #custom-weather.LightSnow,
190 #custom-weather.Sleet,
191 #custom-weather.Snow,
192 #custom-weather.LightSnowShowers,
193 #custom-weather.LightSleetShowers {
194 border-color: @text;
195 }
196
197 #custom-weather.Clear,
198 #custom-weather.Sunny {
199 border-color: @yellow;
200 }
201
202 #custom-weather.PartlyCloudy {
203 border-color: @flamingo;
204 }
205
206 #custom-weather.PartlyCloudy.night {
207 border-color: @lavender;
208 }
209
210 #custom-weather.Clear.night,
211 #custom-weather.Sunny.night {
212 border-color: @mauve;
213 }
214
215 #custom-news.utd {
216 font-size: 1.5rem;
217 }
218
219 #custom-news.unread {
220 border-color: @sapphire;
221 }
222
223 #mpris {
224 opacity: 0;
225 }
226
227 #mpris.paused {
228 opacity: 1;
229 }
230
231 #mpris.playing {
232 opacity: 1;
233 border-color: @sapphire;
234 }
235
236 #mpris.playing.spotify {
237 border-color: #33B980;
238 }
239
240 #mpris.paused.kdeconnect {
241 opacity: 0;
242 }
243 '';
244 settings = [
245 {
246 battery = {
247 format = "{icon} {capacity}";
248 format-charging = "{icon} {capacity}";
249 format-icons = {
250 charging = [
251 ""
252 ""
253 ""
254 ""
255 ""
256 ""
257 ""
258 ""
259 ""
260 ""
261 ];
262 default = [
263 ""
264 ""
265 ""
266 ""
267 ""
268 ""
269 ""
270 ""
271 ""
272 ""
273 ];
274 };
275 states = {
276 critical = 15;
277 warning = 30;
278 };
279 };
280 bluetooth = {
281 format = "";
282 format-connected = "";
283 format-connected-battery = " {device_battery_percentage}";
284 format-disabled = "";
285 format-off = "";
286 on-click-right = "rfkill toggle bluetooth";
287 tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
288 tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
289 tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
290 tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
291 };
292 "clock#1" = {
293 actions = {
294 on-click = "shift_up";
295 on-click-middle = "mode";
296 on-click-right = "shift_down";
297 };
298 calendar = {
299 format = {
300 days = "<span color='#ecc6d9'><b>{}</b></span>";
301 months = "<span color='#ffead3'><b>{}</b></span>";
302 today = "<span color='#ff6699'><b><u>{}</u></b></span>";
303 weekdays = "<span color='#ffcc66'><b>{}</b></span>";
304 weeks = "<span color='#99ffdd'><b>W{}</b></span>";
305 };
306 mode = "month";
307 mode-mon-col = 3;
308 on-scroll = 1;
309 weeks-pos = "right";
310 };
311 format = " {:%A, %B %Od}";
312 tooltip-format = "<tt><small>{calendar}</small></tt>";
313 };
314 "clock#2" = {
315 format = " {:%I:%M %p}";
316 tooltip-format = "{:%F at %T in %Z (UTC%Ez)}";
317 };
318 "custom/kde-connect" = {
319 exec = ''${pkgs.nushell}/bin/nu --plugins "[${
320 lib.getExe inputs.nu_plugin_dbus.packages.${pkgs.system}.default
321 }]" ${../res/custom_waybar_modules/kdeconnect.nu}'';
322 format = "{}";
323 interval = 30;
324 on-click = "kdeconnect-settings";
325 return-type = "json";
326 };
327 "custom/news" = {
328 exec = "${pkgs.nushell}/bin/nu ${../res/custom_waybar_modules/newsboat.nu}";
329 exec-on-event = true;
330 format = "{}";
331 on-click-right = "pkill waybar -SIGRTMIN+6";
332 restart-interval = 1800;
333 return-type = "json";
334 signal = 6;
335 };
336 "custom/notification" = {
337 escape = true;
338 exec = "swaync-client -swb";
339 exec-if = "which swaync-client";
340 format = "{icon}";
341 format-icons = {
342 dnd-inhibited-none = "";
343 dnd-inhibited-notification = "<sup></sup>";
344 dnd-none = "";
345 dnd-notification = "<sup></sup>";
346 inhibited-none = "";
347 inhibited-notification = "<sup></sup>";
348 none = "";
349 notification = "";
350 };
351 max-length = 3;
352 on-click = "sleep 0.2 && swaync-client -t -sw";
353 on-click-middle = "sleep 0.2 && swaync-client -C -sw";
354 on-click-right = "sleep 0.2 && swaync-client -d -sw";
355 return-type = "json";
356 tooltip = false;
357 };
358 "custom/weather" = {
359 exec = "${pkgs.nushell}/bin/nu ${../res/custom_waybar_modules/weather.nu}";
360 format = "{}";
361 interval = 600;
362 on-click = "xdg-open https://duckduckgo.com/?q=weather";
363 return-type = "json";
364 };
365 idle_inhibitor = {
366 format = "{icon}";
367 format-icons = {
368 activated = "";
369 deactivated = "";
370 };
371 };
372 layer = "top";
373 modules-center = [];
374 modules-left =
375 [
376 "user"
377 "clock#1"
378 "clock#2"
379 ]
380 ++ lib.optional config.cow.news.enable "custom/news"
381 ++ [
382 "custom/weather"
383 "mpris"
384 ];
385 modules-right =
386 [
387 "network"
388 "battery"
389 "bluetooth"
390 "pulseaudio"
391 ]
392 ++ lib.optional config.cow.kde-connect.enable "custom/kde-connect"
393 ++ lib.optional config.cow.gdi.doIdle "idle_inhibitor"
394 ++ [
395 "custom/notification"
396 "privacy"
397 "tray"
398 ];
399 mpris = {
400 album-len = 20;
401 artist-len = 25;
402 interval = 1;
403 dynamic-importance-order = [
404 "title"
405 "position"
406 "length"
407 "artist"
408 "album"
409 ];
410 dynamic-len = 50;
411 dynamic-order = [
412 "title"
413 "artist"
414 "album"
415 "position"
416 "length"
417 ];
418 format = "{player_icon} {dynamic}";
419 format-paused = "{status_icon} {dynamic}";
420 player-icons = {
421 QMPlay2 = "";
422 default = "";
423 firefox = "";
424 firefox-devedition = "";
425 chromium = "";
426 kdeconnect = "";
427 spotify = "";
428 };
429 status-icons = {
430 paused = "";
431 stopped = "";
432 };
433 title-len = 35;
434 };
435 network = {
436 format = "{ifname}";
437 format-disconnected = "";
438 format-ethernet = " {ifname}";
439 format-icons = [
440 ""
441 ""
442 ""
443 ""
444 ];
445 format-linked = " {ifname}";
446 format-wifi = "{icon} {essid}";
447 tooltip-disconnected = "Disconnected";
448 tooltip-format = "{ifname} via {gwaddr}";
449 tooltip-format-ethernet = " {ifname}";
450 tooltip-format-wifi = "Connected to {essid} ({signalStrength} Strength) over {ifname} via {gwaddr}";
451 };
452 position = "top";
453 privacy = {
454 icon-size = 20;
455 icon-spacing = 4;
456 modules = [
457 {
458 tooltip = true;
459 tooltip-icon-size = 24;
460 type = "screenshare";
461 }
462 {
463 tooltip = true;
464 tooltip-icon-size = 24;
465 type = "audio-in";
466 }
467 ];
468 transition-duration = 200;
469 };
470 pulseaudio = {
471 format = "{icon} {volume:2}";
472 format-bluetooth = "{icon} {volume}";
473 format-icons = {
474 car = "";
475 default = [
476 ""
477 ""
478 ];
479 hands-free = "";
480 headphone = "";
481 headset = "";
482 phone = "";
483 portable = "";
484 };
485 format-muted = "";
486 on-click = "pamixer -t";
487 on-click-right = "pavucontrol";
488 scroll-step = 5;
489 };
490 tray = {
491 icon-size = 25;
492 show-passive-items = true;
493 spacing = 5;
494 };
495 user = {
496 format = " {user}";
497 icon = true;
498 };
499 }
500 {
501 cpu = {
502 format = " {usage}";
503 states = {
504 critical = 95;
505 warning = 80;
506 };
507 };
508 "hyprland/workspaces" = {
509 disable-scroll = true;
510 format = "{name}";
511 };
512 layer = "top";
513 memory = {
514 format = " {} ({used:0.1f}/{total:0.1f} GiB)";
515 states = {
516 critical = 90;
517 warning = 70;
518 };
519 };
520 # modules-center = ["wlr/taskbar"];
521 # modules-left = ["hyprland/workspaces"];
522 modules-right = [
523 "temperature"
524 "cpu"
525 "memory"
526 ];
527 position = "bottom";
528 temperature = {
529 critical-threshold = 80;
530 format = "{icon} {temperatureC} °C";
531 format-critical = "{icon}! {temperatureC} °C";
532 format-icons = [
533 ""
534 ""
535 ""
536 ];
537 thermal-zone = 1;
538 };
539 "wlr/taskbar" = {
540 format = "{icon}";
541 icon-size = 35;
542 on-click = "activate";
543 };
544 }
545 ];
546 };
547 };
548}