Files
nix-config/modules/home/programs/waybar/default.nix
2026-04-05 19:10:23 -05:00

600 lines
18 KiB
Nix
Executable File

{
config,
lib,
namespace,
...
}:
with lib;
let
cfg = config.${namespace}.programs.waybar;
baseStyle =
if cfg.style.file != null then
builtins.readFile cfg.style.file
else
''
/* =============================================================================
ANIMATIONS & GLOBAL OVERRIDES
============================================================================= */
@keyframes blinker {
50% { color: @base08; }
}
/* Override Stylix font settings */
* {
font-family: "Jetbrains Mono Nerd Font", monospace;
font-size: 14px;
min-height: 0;
}
/* =============================================================================
MAIN BAR & TOOLTIPS
============================================================================= */
window#waybar {
background: transparent;
}
#waybar {
background: transparent;
color: @base06;
margin: 5px 5px;
}
#tooltip {
background: @base00;
border-color: @base00;
border-radius: 1rem;
border-width: 2px; /* Reduced from 1rem which is usually too thick */
border-style: solid;
}
/* Right-click menu styling */
menu {
border-radius: 15px;
background: @base00;
color: @base06;
}
menuitem {
border-radius: 15px;
}
/* =============================================================================
WORKSPACES
============================================================================= */
#workspaces {
background-color: @base00;
border-radius: 1rem;
opacity: 0.85;
padding: 0.2rem 0.5rem;
margin: 3px 0 3px 0.6rem;
}
#workspaces button {
color: @base0F;
border-radius: 1rem;
padding: 0.4rem;
/* Border handled by stylix, but we add specific colors below */
}
#workspaces button.active,
#workspaces button:hover {
color: @base0C;
border-radius: 1rem;
}
#workspaces button.focused {
color: @base06;
background: @base0A;
border-radius: 1rem;
}
#workspaces button.urgent {
color: @base00;
background: @base06;
border-radius: 1rem;
}
/* =============================================================================
WINDOW TITLE
============================================================================= */
#window {
color: @base0E;
background-color: @base00;
opacity: 0.85;
border-radius: 1rem;
padding: 0.2rem 0.5rem;
margin: 3px 0;
margin-left: 4rem;
margin-right: 75rem; /* This is very large, likely a centering hack */
}
#window.empty {
background-color: transparent;
}
/* =============================================================================
SHARED MODULE STYLES
============================================================================= */
/* This block applies the standard "Nord Background" style to all modules
to avoid repeating code for every single ID. */
#custom-power,
#custom-weather,
#custom-notifications,
#battery,
#clock,
#idle_inhibitor,
#network,
#bluetooth,
#wireplumber,
#keyboard-state,
#temperature,
#custom-left-end,
#custom-right-end,
#custom-lights,
#tray {
background-color: @base00;
opacity: 0.85;
padding: 0.2rem 0.5rem;
margin: 3px 0;
border-radius: 0; /* Default to square, rounded manually below */
}
/* Common Hover Effect */
#idle_inhibitor:hover,
#network:hover,
#bluetooth:hover,
#wireplumber:hover,
#temperature:hover,
#custom-lights:hover {
background: @base02;
}
/* =============================================================================
MODULE SPECIFIC COLORS
============================================================================= */
#custom-power,
#custom-weather,
#custom-notifications {
color: @base0F;
}
#custom-notifications.notify { color: @base08; }
#custom-notifications.alert {
animation: blinker 3s linear infinite;
}
#battery {
color: @base0E;
min-width: 3rem;
}
#clock { color: @base0F; }
#idle_inhibitor {
color: @base0F;
padding-right: 1rem;
}
#network {
color: @base0E;
padding-right: 15px;
}
#bluetooth { color: @base0F; }
/* --- Audio source/sink --- */
#wireplumber.source,
#wireplumber.sink {
color: @base0C;
}
#wireplumber.source.muted {
animation: blinker 2s linear infinite;
padding-right: 1rem;
}
#wireplumber.sink.muted {
animation: blinker 5s linear infinite;
}
/* --- Keyboard --- */
#keyboard-state.numlock { color: @base0C; }
#keyboard-state.capslock { color: @base0F; }
/* --- Temperature --- */
#temperature,
#temperature.gpu {
color: @base0F;
}
/* --- Tray --- */
#tray {
border-radius: 1rem;
margin-right: 0.6rem;
}
/* =============================================================================
DECORATIVE END CAPS & EXTRAS
============================================================================= */
#custom-left-end {
border-radius: 1rem 0 0 1rem;
margin-left: 0.5rem;
}
#custom-right-end {
border-radius: 0 1rem 1rem 0;
margin-right: 0.5rem;
}
#custom-lights {
color: @base0C;
/* Re-declaring background here to ensure specific override logic if needed */
background-color: @base00;
border-radius: 1rem 0 0 1rem;
margin-left: 0.5rem;
}
'';
in
{
imports = [
./options.nix
./scripts/audio-control.nix
./scripts/hass.nix
./scripts/media.nix
./scripts/notifications.nix
./scripts/weather.nix
];
config = mkIf cfg.enable {
# https://github.com/Alexays/Waybar/wiki/Module:-Hyprland
# https://www.nerdfonts.com/cheat-sheet
home.file = {
".config/waybar/power_menu.xml".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkMenu" id="menu">
<child>
<object class="GtkMenuItem" id="suspend">
<property name="label">Suspend</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="hibernat">
<property name="label">Hibernate</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="shutdown">
<property name="label">Shutdown</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="delimiter1" />
</child>
<child>
<object class="GtkMenuItem" id="reboot">
<property name="label">Reboot</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="lock">
<property name="label">Lock</property>
</object>
</child>
</object>
</interface>
'';
};
programs.waybar = {
enable = true;
systemd.enable = true;
settings = {
mainBar =
(mkMerge [
{
inherit (cfg) layer;
position = "top";
mod = "dock";
exclusive = true;
passthrough = false;
gtk-layer-shell = true;
height = 0;
# Module Layout
modules-left = cfg.layout.left;
modules-center = cfg.layout.center;
modules-right = cfg.layout.right;
# Base module definitions always present unless individually gated
"hyprland/workspaces" = {
disable-scroll = true;
all-outputs = true;
on-click = "activate";
persistent_workspaces = {
"*" = 1;
};
};
"hyprland/window" = {
separate-outputs = true;
format = { };
};
temperature = {
hwmon-path-abs = cfg.temperature.cpu.hwmonPath;
input-filename = cfg.temperature.cpu.hwmonFile;
critical-threshold = 110;
format-critical = "{temperatureC}°C ";
format = "{temperatureC}°C {icon}";
format-icons = [
""
""
""
""
""
];
tooltip-format = "CPU: {temperatureC}°C";
};
network = {
inherit (cfg.network) interface;
on-click = "nm-connection-editor";
format = "{icon}";
tooltip-format = "{ifname} via {gwaddr} 󰊗";
tooltip-format-wifi = ''
{essid} ({signalStrength}%) {icon}
{bandwidthDownBits} {bandwidthUpBits}
'';
tooltip-format-ethernet = "{ifname} ";
tooltip-format-disconnected = "Disconnected";
max-length = 50;
format-icons = {
wifi = [
"󰤯"
"󰤟"
"󰤢"
"󰤥"
"󰤨"
];
ethernet = "󰈀";
linked = "󰤫";
disconnected = "󰤫";
};
};
"custom/notifications" = {
interval = 30;
format = { };
tooltip = true;
exec = "waybar-notifications";
return-type = "json";
on-click-middle = "makoctl restore && makoctl dismiss --all --no-history"; # todo
};
"custom/left-end" = {
format = "&ampnbsp";
tooltip = false;
};
"custom/right-end" = {
format = "&ampnbsp";
tooltip = false;
};
"custom/power" = {
format = " ";
tooltip = false;
menu = "on-click";
menu-file = "~/.config/waybar/power_menu.xml";
menu-actions = {
shutdown = "shutdown";
reboot = "reboot";
suspend = "systemctl suspend";
hibernate = "systemctl hibernate";
lock = "pidof hyprlock || hyprlock";
};
};
}
(mkIf cfg.features.tray.enable {
tray = {
icon-size = 16;
spacing = 10;
};
})
(mkIf cfg.features.keyboardIndicators.enable {
"keyboard-state#capslock" = {
capslock = true;
format = "{icon}";
tooltip-format = "Caps Lock {state}";
format-icons = {
locked = "󰬶";
unlocked = "󰬵";
};
};
"keyboard-state#numlock" = {
numlock = true;
format = "{icon}";
tooltip-format = "Num Lock {state}";
format-icons = {
locked = "󰎠";
unlocked = "󱧓";
};
};
})
(mkIf cfg.features.audio.sink.enable {
"wireplumber#sink" = {
format = "{icon} {volume}%";
tooltip-format = "{icon}\n{node_name}\n{format_source}\n{source_desc}";
format-muted = "{icon} Muted";
on-click = "wpctl set-mute @DEFAULT_SINK@ toggle";
on-click-right = "pavucontrol -t 1";
on-scroll-up = "wpctl set-volume @DEFAULT_SINK@ 5%+";
on-scroll-down = "wpctl set-volume @DEFAULT_SINK@ 5%-";
on-click-middle = "waybar-audio";
scroll-step = 5;
format-icons = {
headphone = "󰋋";
headphone-muted = "󰟎";
hands-free = "󰋋";
headset = "󰋋";
phone = "";
portable = "󰋋";
car = "";
default = [
""
""
""
""
];
};
};
})
(mkIf cfg.features.audio.source.enable {
"wireplumber#source" = {
node-type = "Audio/Source";
format = "";
format-muted = "";
tooltip = false;
on-click = "wpctl set-mute @DEFAULT_SOURCE@ toggle";
on-click-right = "pavucontrol -t 2";
on-scroll-up = "wpctl set-volume @DEFAULT_SOURCE@ 5%+";
on-scroll-down = "wpctl set-volume @DEFAULT_SOURCE@ 5%-";
scroll-step = 5;
};
})
(mkIf cfg.features.bluetooth.enable {
bluetooth = {
on-click = "overskride";
tooltip = true;
format = "{icon}";
tooltip-format = "{status}";
tooltip-format-disabled = "{status}";
tooltip-format-off = "{status}";
tooltip-format-on = "{status}";
tooltip-format-connected = "{status}";
tooltip-format-enumerate-connected = { };
format-icons = {
disabled = "󰂲";
off = "󰂲";
on = "󰂯";
connected = "󰂱";
};
};
})
(mkIf cfg.features.idleInhibitor.enable {
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = "󰐂";
deactivated = "󱩜";
};
};
})
(mkIf cfg.features.clock.enable {
clock = {
format = "{:%I:%M %p}";
tooltip-format = "<tt><small>{calendar}</small></tt>";
calendar = {
mode = "month";
format = {
months = "<span color='@base0F'><b>{}</b></span>";
days = "<span color='@base0F'><b>{}</b></span>";
weekdays = "<span color='@base0C'><b>{}</b></span>";
today = "<span color='${config.lib.stylix.colors.base0B}'><b><u>{}</u></b></span>";
};
};
};
})
(mkIf cfg.features.battery.enable {
battery = {
interval = 60;
states = {
warning = 30;
critical = 15;
};
format = "{capacity}% {icon}";
format-icons = {
default = [
"󰂃"
"󰁺"
"󰁻"
"󰁼"
"󰁽"
"󰁾"
"󰁿"
"󰂀"
"󰂁"
"󰂂"
"󰁹"
];
charging = [
"󰢟"
"󰢜"
"󰂆"
"󰂇"
"󰂈"
"󰢝"
"󰂉"
"󰢞"
"󰂊"
"󰂋"
"󰂅"
];
};
max-length = 25;
};
})
(mkIf cfg.temperature.gpu.enable {
"temperature#gpu" = {
hwmon-path-abs = cfg.temperature.gpu.hwmonPath;
input-filename = cfg.temperature.gpu.hwmonFile;
critical-threshold = 110;
format-critical = "{temperatureC}°C ";
format = "{temperatureC}°C {icon}";
format-icons = [
""
""
""
""
""
];
on-click = "lact";
tooltip-format = "GPU: {temperatureC}°C";
};
})
(mkIf cfg.features.weather.enable {
"custom/weather" = {
tooltip = true;
format = { };
interval = 30;
exec = "waybar-weather --waybar";
return-type = "json";
markup = "pango";
};
})
])
// cfg.extra.settings;
}
// cfg.extraModules; # keep legacy top-level extra modules for compatibility
style = baseStyle + (cfg.extra.style or "") + (cfg.extraModulesStyle or "");
};
};
}