{ config, lib, pkgs, ... }: # Waybar: a top status bar reading system state at a glance. let waybarModulesFor = position: map (module: module.name) ( lib.sort (a: b: a.order < b.order) ( lib.filter (module: module.position == position) (staticWaybarModules ++ registeredWaybarModules) ) ); staticWaybarModules = [ { name = "hyprland/workspaces"; position = "left"; order = 10; } { name = "clock"; position = "center"; order = 10; } { name = "mpris"; position = "right"; order = 30; } { name = "wireplumber"; position = "right"; order = 40; } { name = "custom/network"; position = "right"; order = 60; } { name = "battery"; position = "right"; order = 70; } ]; registeredWaybarModules = lib.mapAttrsToList ( name: module: module // { inherit name; } ) hostWaybarModules; hostWaybarModules = lib.attrByPath [ config.networking.hostName ] { } config.registry.waybar; # A Nerd Font Private-Use-Area codepoint as a literal character, decoded # through JSON so the glyph survives as bytes rather than an editor paste. g = code: builtins.fromJSON ''"\u${code}"''; registeredWaybarModuleSettings = lib.mapAttrs (_name: module: module.settings) hostWaybarModules; networkStatus = pkgs.writeShellScript "waybar-network-status" '' active=$( ${lib.getExe' pkgs.networkmanager "nmcli"} -t -f DEVICE,TYPE,STATE,CONNECTION device status \ | ${lib.getExe' pkgs.gawk "awk"} -F: '$3 == "connected" && $2 != "loopback" { print; exit }' ) if [ -z "$active" ]; then ${lib.getExe pkgs.jq} -cn \ --arg text "${g "f127"} off" \ --arg tooltip "Network disconnected" \ --arg class "disconnected" \ '{ text: $text, tooltip: $tooltip, class: $class }' exit 0 fi IFS=: read -r device type _state connection <<< "$active" case "$type" in wifi) icon="${g "f1eb"}" ;; ethernet) icon="LAN" ;; *) icon="NET" ;; esac ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$device" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }') ${lib.getExe pkgs.jq} -cn \ --arg text "$icon $connection" \ --arg tooltip "$device: ''${ipaddr:-no IPv4}" \ --arg class "$type" \ '{ text: $text, tooltip: $tooltip, class: $class }' ''; in { options.modules.desktop.session.waybar.enable = lib.mkEnableOption "the Waybar status bar"; config = lib.mkIf config.modules.desktop.session.waybar.enable { # A symbols font backs the module glyphs, so pango falls back to it for the # codepoints Stylix's monospace font does not carry. fonts.packages = [ pkgs.nerd-fonts.symbols-only ]; home-manager.users.${config.user.name}.programs.waybar = { enable = true; # A user service bound to graphical-session.target, which uwsm activates, # so the bar comes up with the session and no compositor exec-once. systemd.enable = true; style = '' .modules-right { margin-right: 8px; } #custom-dnd { margin-right: 8px; } ''; settings.mainBar = lib.mkMerge [ { layer = "top"; position = "top"; height = 30; spacing = 8; modules-left = waybarModulesFor "left"; modules-center = waybarModulesFor "center"; modules-right = waybarModulesFor "right"; # Per-application icons for the windows on each workspace, mapped from # window class with a neutral glyph for anything unlisted. "hyprland/workspaces" = { on-click = "activate"; format = "{id} {windows}"; format-window-separator = " "; window-rewrite-default = g "f2d0"; window-rewrite = lib.mapAttrs' ( _name: windowIcon: lib.nameValuePair "class<${windowIcon.class}>" (g windowIcon.icon) ) (lib.attrByPath [ config.networking.hostName ] { } config.registry.window-icon); }; clock = { format = "{:%a %d %b %H:%M}"; tooltip-format = "{calendar}"; calendar = { mode = "month"; # Underline the current day so it stands out in the grid. format.today = "{}"; }; }; mpris = { format = "${g "f001"} {title}"; format-paused = "${g "f04c"} {title}"; max-length = 40; on-click = "play-pause"; on-scroll-up = "next"; on-scroll-down = "previous"; }; wireplumber = { format = "{icon} {volume}%"; format-muted = "${g "f026"} muted"; format-icons = [ (g "f026") (g "f027") (g "f028") ]; on-click = "${lib.getExe' pkgs.wireplumber "wpctl"} set-mute @DEFAULT_AUDIO_SINK@ toggle"; }; "custom/network" = { return-type = "json"; exec = "${networkStatus}"; interval = 5; }; battery = { format = "{icon} {capacity}%"; format-charging = "${g "f0e7"} {capacity}%"; format-icons = [ (g "f244") (g "f243") (g "f242") (g "f241") (g "f240") ]; states = { warning = 20; critical = 10; }; }; } registeredWaybarModuleSettings ]; }; }; }