{ config, lib, ... }: with lib; let cfg = config.mjallen.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 = '' Suspend Hibernate Shutdown Reboot Lock ''; }; programs.waybar = { enable = true; systemd.enable = true; settings = { mainBar = ( (mkMerge [ { layer = 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 = { interface = 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 = "&nbsp"; tooltip = false; }; "custom/right-end" = { format = "&nbsp"; 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 = "{calendar}"; calendar = { mode = "month"; format = { months = "{}"; days = "{}"; weekdays = "{}"; today = "{}"; }; }; }; }) (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 ""); }; }; }