nixos/shared/modules/home-manager/waybar.nix

535 lines
14 KiB
Nix

# Shared Waybar configuration with Stylix theming
# Parameterized for use across multiple machines
{ config, pkgs, lib, ... }:
let
cfg = config.waybarConfig;
in
{
options.waybarConfig = {
enable = lib.mkEnableOption "Waybar with Stylix theming";
terminal = lib.mkOption {
type = lib.types.str;
default = "ghostty";
description = "Terminal emulator to use for on-click commands";
};
launcher = lib.mkOption {
type = lib.types.str;
default = "wofi --show=drun";
description = "Application launcher command";
};
fontSize = lib.mkOption {
type = lib.types.int;
default = 16;
description = "Base font size for waybar";
};
font = lib.mkOption {
type = lib.types.str;
default = "Overpass Nerd Font";
description = "Font family for waybar";
};
position = lib.mkOption {
type = lib.types.enum [ "top" "bottom" ];
default = "top";
description = "Bar position";
};
margin = lib.mkOption {
type = lib.types.int;
default = 3;
description = "Margin around the bar in pixels";
};
extraModulesLeft = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Additional modules to add to the left side";
};
extraModulesRight = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Additional modules to add to the right side";
};
windowRewriteRules = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {};
description = "Additional window title rewrite rules";
};
workspaceIcons = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {};
description = "Additional workspace icons";
};
};
config = lib.mkIf cfg.enable {
programs.waybar = {
enable = true;
settings = {
mainBar = {
layer = "top";
position = cfg.position;
margin-top = cfg.margin;
margin-left = cfg.margin;
margin-right = cfg.margin;
margin-bottom = cfg.margin;
modules-left = [
"custom/launcher"
"niri/workspaces"
"niri/window"
] ++ cfg.extraModulesLeft;
modules-right = cfg.extraModulesRight ++ [
"clock"
"custom/storage"
"memory"
"cpu"
"battery"
"custom/wlsunset"
"tray"
"custom/power"
];
"idle_inhibitor" = {
format = "{icon} ";
format-icons = {
activated = "";
deactivated = "";
};
};
battery = {
states = {
warning = 30;
critical = 15;
};
format = "{icon} {capacity}%";
format-charging = "{capacity}% 󰂄";
format-plugged = "{capacity}% ";
format-icons = [ "" "" "" "" "" ];
};
clock = {
interval = 1;
format = "{:%I:%M.%S %p}";
tooltip-format = "{:%e %B %Y}";
};
cpu = {
interval = 5;
format = " {usage}%";
states = {
warning = 70;
critical = 90;
};
on-click = "${cfg.terminal} -e 'htop'";
};
memory = {
interval = 5;
format = " {}%";
on-click = "${cfg.terminal} -e 'htop'";
states = {
warning = 70;
critical = 90;
};
};
network = {
interval = 5;
format-wifi = "";
format-ethernet = " {ifname}: {ipaddr}/{cidr}";
format-disconnected = " Disconnected";
tooltip-format = "{essid} - {ifname}:{ipaddr} {bandwidthUpBytes} {bandwidthDownBytes}";
on-click = "${cfg.terminal} -e 'nmtui'";
};
"niri/window" = {
format = "{title}";
icon = true;
icon-size = 20;
rewrite = {
# Firefox
"(.*) Mozilla Firefox" = " $1";
"(.*) - Mozilla Firefox" = " $1";
"Mozilla Firefox" = " Firefox";
# Chrome/Chromium
"(.*) - Google Chrome" = " $1";
"(.*) - Chromium" = " $1";
"Google Chrome" = " Chrome";
"Chromium" = " Chromium";
# Terminals
"(.*) - zsh" = " $1";
"(.*) - bash" = " $1";
"(.*) - fish" = " $1";
"ghostty" = " Terminal";
"kitty" = " Terminal";
"alacritty" = " Terminal";
# Editors/IDEs
"(.*) - Visual Studio Code" = " $1";
"(.*) - Code" = " $1";
"(.*) - Vim" = " $1";
"(.*) - Neovim" = " $1";
"(.*) - Emacs" = " $1";
"Visual Studio Code" = " VS Code";
# File managers
"(.*)Nautilus" = " Files: $1";
"Files" = " Files";
"Thunar" = " Files";
"Dolphin" = " Files";
# Communication
"Slack (.*)" = " $1";
"Slack" = " Slack";
"Signal" = " Signal";
"Discord" = " Discord";
"Telegram" = " Telegram";
# Media
"Spotify" = " Spotify";
"Steam" = " Steam";
"(.*) - YouTube" = "󰗃 $1";
"VLC media player" = "󰕼 VLC";
# Dev tools
"(.*) - GitHub" = " $1";
"GitKraken" = " GitKraken";
"Postman" = " Postman";
# System
"System Monitor" = " System Monitor";
"Task Manager" = " Task Manager";
"Settings" = " Settings";
"Control Panel" = " Settings";
# Office
"(.*) - LibreOffice Writer" = " $1";
"(.*) - LibreOffice Calc" = " $1";
"(.*) - LibreOffice Impress" = " $1";
# Fallbacks
"^(.*) - .*$" = "$1";
"^(.*) | .*$" = "$1";
"^$" = "Desktop";
} // cfg.windowRewriteRules;
};
"niri/workspaces" = {
disable-click = false;
disable-markup = false;
all-outputs = true;
format = " {icon} ";
format-icons = {
term = "";
net = "";
chat = "󰭻";
scratch = "";
"1" = " 1";
"2" = " 2";
"3" = " 3";
"4" = " 4";
"5" = " 5";
"6" = " 6";
"7" = " 7";
"8" = " 8";
"9" = " 9";
} // cfg.workspaceIcons;
};
pulseaudio = {
scroll-step = 1;
format = "{icon} {volume}%";
format-bluetooth = "{volume}% {icon} {format_source}";
format-bluetooth-muted = " {icon} {format_source}";
format-muted = " {format_source}";
format-source = "{volume}% ";
format-source-muted = "";
format-icons = {
headphone = [ "" "" "" "" "" ];
hands-free = "";
headset = "";
phone = "";
portable = "";
car = "";
default = [ "" "" "" ];
};
on-click = "pavucontrol";
on-scroll-up = "pactl set-sink-volume @DEFAULT_SINK@ +2%";
on-scroll-down = "pactl set-sink-volume @DEFAULT_SINK@ -2%";
};
tray = {
icon-size = 20;
spacing = 10;
};
backlight = {
format = "{icon} {percent}%";
format-icons = [ "󰹐" "󱩏" "󱩑" "󱩓" "󱩕" "󰛨" ];
on-scroll-down = "brightnessctl -c backlight set 1%-";
on-scroll-up = "brightnessctl -c backlight set +1%";
min-brightness = 1;
};
"custom/storage" = {
format = "{icon} {percentage}%";
format-icons = {
default = "";
warning = "";
critical = "";
};
exec = ''usage=$(df / --output=pcent | tail -n1 | tr -d ' %'); if [ $usage -ge 90 ]; then class="critical"; elif [ $usage -ge 75 ]; then class="warning"; else class="default"; fi; echo "{\"percentage\":$usage,\"class\":\"$class\"}"'';
return-type = "json";
interval = 30;
tooltip-format = "Root filesystem: {percentage}% used";
};
"custom/launcher" = {
format = " ";
on-click = cfg.launcher;
tooltip = false;
};
"custom/wlsunset" = {
format = "{}";
exec = "if systemctl --user is-active --quiet wlsunset; then echo '󰖜'; else echo '󰖚'; fi";
on-click = "if systemctl --user is-active --quiet wlsunset; then systemctl --user stop wlsunset; else systemctl --user start wlsunset; fi; pkill -SIGRTMIN+8 waybar";
interval = "once";
signal = 8;
tooltip = false;
};
"custom/power" = {
format = "";
on-click = "entries='Logout Suspend Reboot Shutdown'; selected=$(printf '%s\\n' $entries | wofi --show=dmenu | awk '{print tolower($1)}'); case $selected in logout) niri msg action quit;; suspend) systemctl suspend;; reboot) systemctl reboot;; shutdown) systemctl poweroff -i;; esac";
tooltip = false;
};
};
};
# Stylix provides @define-color variables for base16 colors
style = ''
/* Keyframes */
@keyframes blink-warning {
70% { color: @base05; }
to { color: @base05; background-color: @base00; }
}
@keyframes blink-critical {
70% { color: @base05; }
to { color: @base05; background-color: @base01; }
}
/* Reset all styles */
* {
border: none;
border-radius: 0;
min-height: 30px;
margin: 0px;
padding: 0px;
}
/* The whole bar */
#waybar {
background: transparent;
background-color: transparent;
font-family: ${cfg.font};
font-size: ${toString cfg.fontSize}px;
color: @base05;
}
#taskbar {
background: transparent;
}
#taskbar button {
padding-left: 3px;
padding-right: 3px;
margin-left: 3px;
margin-right: 3px;
border-bottom: 2px solid;
}
#taskbar button.active {
color: @base0B;
}
.modules-left,
.modules-right {
background: transparent;
background-color: @base00;
border-radius: 20px;
padding: 0px 6px 0px 6px;
border-style: solid;
border-width: 3px;
border-color: @base02;
}
.modules-center {
background: transparent;
border: none;
padding: 0;
min-height: 0;
}
#backlight,
#battery,
#clock,
#cpu,
#custom-storage,
#custom-keyboard-layout,
#custom-PBPbattery,
#custom-weather,
#idle_inhibitor,
#memory,
#mode,
#network,
#pulseaudio,
#temperature,
#tray {
padding: 0.5rem 0.6rem;
margin: 1px 0px;
}
#clock {
margin-left: 5px;
margin-right: 5px;
min-width: 140px;
}
#backlight,
#battery,
#cpu,
#custom-storage,
#memory,
#network,
#pulseaudio,
#temperature {
min-width: 90px;
}
#battery {
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#battery.warning,
#custom-storage.warning {
color: @base09;
}
#battery.critical,
#custom-storage.critical {
color: @base08;
}
#battery.warning.discharging {
animation-name: blink-warning;
animation-duration: 3s;
}
#battery.critical.discharging {
animation-name: blink-critical;
animation-duration: 2s;
}
#cpu.warning {
color: @base09;
}
#cpu.critical {
color: @base08;
}
#memory {
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#memory.warning {
color: @base09;
}
#memory.critical {
color: @base08;
animation-name: blink-critical;
animation-duration: 2s;
padding-left: 5px;
padding-right: 5px;
}
#mode {
background: @base03;
border-bottom: 3px transparent;
color: @base05;
margin-left: 5px;
margin-right: 5px;
border-radius: 20px;
}
#network.disconnected {
color: @base09;
}
#pulseaudio {
padding-top: 6px;
}
#pulseaudio.muted {
color: @base0C;
}
#temperature.critical {
color: @base08;
}
#window {
font-weight: bold;
margin-left: 20px;
margin-right: 10px;
}
#workspaces {
font-size: ${toString cfg.fontSize}px;
}
#workspaces button {
margin-bottom: 0px;
padding: 0px;
}
#workspaces button.active {
border-bottom: 3px solid @base0D;
color: @base0B;
}
#workspaces button.urgent {
border-color: @base0D;
color: @base0A;
}
#custom-power {
margin-left: 15px;
margin-right: 15px;
color: @base09;
}
#custom-launcher {
margin-left: 15px;
margin-right: 10px;
}
#backlight.icon {
padding-right: 1px;
}
'';
};
};
}