{ config, lib, ... }: with lib; let cfg = config.mjallen.programs.waybar; palette = import cfg.theme.file; # Back-compat shims for deprecated options rightModules = if builtins.hasAttr "modules-right" cfg && (cfg."modules-right" != [ ]) then cfg."modules-right" else cfg.layout.right; netIf = if (cfg ? networkInterface) && (cfg.networkInterface != "wlan0") then cfg.networkInterface else cfg.network.interface; defaultOpacity = palette.tokens.opacity or "opacity: 0.85;"; defaultBorderRadius = palette.tokens.borderRadius or "border-radius: 1rem;"; defaultCenterOptions = palette.tokens.centerOptions or '' padding-top: 0.2rem; padding-bottom: 0.2rem; padding-left: 0.5rem; padding-right: 0.5rem; margin: 3px 0; ''; borderRight = palette.tokens.borderRight or '' padding-top: 0.2rem; padding-bottom: 0.2rem; padding-left: 0.5rem; padding-right: 0.5rem; margin: 3px 0; border-radius: 0rem 1rem 1rem 0rem; margin-right: 0.5rem; ''; borderLeft = palette.tokens.borderLeft or '' padding-top: 0.2rem; padding-bottom: 0.2rem; padding-left: 0.5rem; padding-right: 0.5rem; margin: 3px 0; border-radius: 1rem 0rem 0rem 1rem; margin-left: 0.5rem; ''; baseStyle = if cfg.style.file != null then builtins.readFile cfg.style.file else '' .blink_me { animation: blinker 1s linear infinite; } @keyframes blinker { 50% { color: ${palette.colors.danger}; } } * { font-family: Jetbrains Mono Nerd Font, monospace; font-size: 14px; min-height: 0; } #waybar { background: transparent; color: ${palette.colors.text}; margin: 5px 5px; } #workspaces { background-color: ${palette.colors.bg}; ${defaultBorderRadius} ${defaultOpacity} ${defaultCenterOptions} margin-left: 0.6rem; } #workspaces button { color: ${palette.colors.primary}; ${defaultBorderRadius} padding: 0.4rem; } #workspaces button.active { color: ${palette.colors.info}; ${defaultBorderRadius} } #workspaces button:hover { color: ${palette.colors.info}; ${defaultBorderRadius} } #workspaces button.focused { color: ${palette.colors.text}; background: ${palette.colors.warning}; ${defaultBorderRadius} } #workspaces button.urgent { color: ${palette.colors.bg}; background: ${palette.colors.text}; ${defaultBorderRadius} } #tooltip { background: ${palette.colors.bg}; border-color: ${palette.colors.bg}; ${defaultBorderRadius} border-width: 1rem; border-style: solid; } #window { color: ${palette.colors.accent}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultBorderRadius} ${defaultCenterOptions} margin-left: 4rem; margin-right: ${toString cfg.windowOffset}rem; } /* make window module transparent when no windows present */ #window.empty { background-color: transparent; } #custom-weather { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #battery { color: ${palette.colors.accent}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; min-width: 3rem; } #clock { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } /* ------------- */ #idle_inhibitor { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; padding-right: 1rem; } #idle_inhibitor:hover { background: ${palette.colors.surfaceAlt}; } #network { color: ${palette.colors.accent}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; padding-right: 15px; } #network:hover { background: ${palette.colors.surfaceAlt}; } #bluetooth { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #bluetooth:hover { background: ${palette.colors.surfaceAlt}; } #wireplumber.source { color: ${palette.colors.info}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #wireplumber.source.muted { animation-name: blinker; animation-duration: 2s; animation-timing-function: linear; animation-iteration-count: infinite; padding-right: 1rem; } #wireplumber.source:hover { background: ${palette.colors.surfaceAlt}; } #wireplumber.sink { color: ${palette.colors.info}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #wireplumber.sink.muted { animation-name: blinker; animation-duration: 5s; animation-timing-function: linear; animation-iteration-count: infinite; } #wireplumber.sink:hover { background: ${palette.colors.surfaceAlt}; } #keyboard-state.numlock { color: ${palette.colors.info}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #keyboard-state.capslock { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #temperature.gpu { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0; } #temperature.gpu:hover { background: ${palette.colors.surfaceAlt}; } #temperature { color: ${palette.colors.primary}; background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} border-radius: 0 } /* ------------- */ #tray { background-color: ${palette.colors.bg}; ${defaultOpacity} ${defaultCenterOptions} ${defaultBorderRadius} margin-right: 0.6rem; } /* ------------- */ #custom-left-end { background-color: ${palette.colors.bg}; ${defaultOpacity} ${borderLeft} } #custom-right-end { background-color: ${palette.colors.bg}; ${defaultOpacity} ${borderRight} } ''; in { imports = [ ./options.nix ./scripts/audio-control.nix ./scripts/hass.nix ./scripts/weather.nix ]; config = mkIf cfg.enable { # https://github.com/Alexays/Waybar/wiki/Module:-Hyprland # https://www.nerdfonts.com/cheat-sheet 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 = rightModules; # 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 = cfg.temperature.cpu.hwmonPath; critical-threshold = 110; format-critical = "{temperatureC}°C "; format = "{temperatureC}°C {icon}"; format-icons = [ "" "" "" "" "" ]; tooltip-format = "CPU: {temperatureC}°C"; }; network = { interface = netIf; 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/left-end" = { format = " "; tooltip = false; }; "custom/right-end" = { format = " "; tooltip = false; }; } (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 = false; 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%-"; 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 = cfg.temperature.gpu.hwmonPath; 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"; 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 ""); }; }; }