535 lines
14 KiB
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;
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
}
|