├── .github ├── assets │ ├── catppuccin-frappe.png │ ├── catppuccin-latte.png │ ├── catppuccin-mocha.png │ └── catppuccin-macchiato.png └── README.md ├── modules ├── extras │ ├── tray.jsonc │ ├── taskbar.jsonc │ └── wireplumber.jsonc ├── hyprland │ ├── windowcount.jsonc │ ├── window.jsonc │ └── workspaces.jsonc ├── cpu.jsonc ├── custom │ ├── distro.jsonc │ ├── power_menu.jsonc │ ├── system_update.jsonc │ ├── dividers.jsonc │ └── user.jsonc ├── memory.jsonc ├── idle_inhibitor.jsonc ├── backlight.jsonc ├── temperature.jsonc ├── mpris.jsonc ├── network.jsonc ├── battery.jsonc ├── bluetooth.jsonc ├── clock.jsonc └── pulseaudio.jsonc ├── style.css ├── themes ├── fzf │ └── catppuccin.txt ├── catppuccin-latte.css ├── catppuccin-mocha.css ├── catppuccin-frappe.css └── catppuccin-macchiato.css ├── styles ├── fonts.css ├── global.css ├── modules-left.css ├── states.css ├── modules-right.css └── modules-center.css ├── scripts ├── _fzf_colorizer.sh ├── power-menu.sh ├── backlight.sh ├── system-update.sh ├── network.sh ├── volume.sh └── bluetooth.sh ├── LICENSE ├── install.sh ├── config.jsonc └── current-theme.css /.github/assets/catppuccin-frappe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sejjy/mechabar/HEAD/.github/assets/catppuccin-frappe.png -------------------------------------------------------------------------------- /.github/assets/catppuccin-latte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sejjy/mechabar/HEAD/.github/assets/catppuccin-latte.png -------------------------------------------------------------------------------- /.github/assets/catppuccin-mocha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sejjy/mechabar/HEAD/.github/assets/catppuccin-mocha.png -------------------------------------------------------------------------------- /.github/assets/catppuccin-macchiato.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sejjy/mechabar/HEAD/.github/assets/catppuccin-macchiato.png -------------------------------------------------------------------------------- /modules/extras/tray.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "tray": { 3 | "icon-size": 16, 4 | // "show-passive-items": 5 | // "smooth-scrolling-threshold": 6 | "spacing": 12, 7 | // "reverse-direction": 8 | // "on-update": 9 | // "expand": 10 | // "icons": 11 | "cursor": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /modules/hyprland/windowcount.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "hyprland/windowcount": { 3 | "format": "[{}]", 4 | // "format-empty": 5 | // "format-windowed": 6 | // "format-fullscreen": 7 | // "separate-outputs": 8 | // "min-length": 9 | // "max-length": 10 | "swap-icon-label": false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* ignore GTK theme */ 2 | * { 3 | all: initial; 4 | } 5 | 6 | @import "current-theme.css"; 7 | @import "styles/fonts.css"; 8 | @import "styles/global.css"; 9 | @import "styles/modules-center.css"; 10 | @import "styles/modules-left.css"; 11 | @import "styles/modules-right.css"; 12 | @import "styles/states.css"; 13 | -------------------------------------------------------------------------------- /themes/fzf/catppuccin.txt: -------------------------------------------------------------------------------- 1 | current-bg surface0 2 | bg base 3 | spinner rosewater 4 | hl red 5 | fg text 6 | header red 7 | info mauve 8 | pointer rosewater 9 | marker lavender 10 | current-fg text 11 | prompt mauve 12 | current-hl red 13 | selected-bg surface1 14 | border overlay0 15 | label text 16 | -------------------------------------------------------------------------------- /modules/hyprland/window.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "hyprland/window": { 3 | "format": "{}", 4 | "rewrite": { 5 | "": "Desktop", 6 | "kitty": "Terminal", 7 | "zsh": "Terminal", 8 | "~": "Terminal" 9 | }, 10 | // "separate-outputs": 11 | // "icon": 12 | // "icon-size": 13 | // "min-length": 14 | // "max-length": 15 | // "tooltip": 16 | "swap-icon-label": false 17 | // "expand": 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /modules/extras/taskbar.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "wlr/taskbar": { 3 | // "all-outputs": 4 | // "format": 5 | // "icon-theme": 6 | // "icon-size": 7 | // "markup": 8 | // "tooltip": 9 | // "tooltip-format": 10 | // "active-first": 11 | // "sort-by-app-id": 12 | "on-click": "activate", 13 | // "on-click-middle": 14 | // "on-click-right": 15 | // "on-update": 16 | "ignore-list": [ "kitty" ], 17 | // "app_ids-mapping": 18 | // "rewrite": 19 | "cursor": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /styles/fonts.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: "Commit Mono Nerd Font"; 3 | font-weight: bold; 4 | font-size: 16px; 5 | } 6 | 7 | #custom-user, 8 | #window label, 9 | #mpris, 10 | tooltip label { 11 | font-weight: normal; 12 | } 13 | 14 | #workspaces button.active label, 15 | #workspaces button.focused label, 16 | #custom-distro { 17 | font-size: 20px; 18 | } 19 | 20 | #custom-power_menu { 21 | font-size: 18px; 22 | } 23 | 24 | #custom-left_div, 25 | #custom-left_inv, 26 | #custom-right_div, 27 | #custom-right_inv { 28 | font-size: 22px; 29 | } 30 | -------------------------------------------------------------------------------- /styles/global.css: -------------------------------------------------------------------------------- 1 | * { 2 | color: @main-fg; 3 | } 4 | 5 | .module { 6 | margin-bottom: -1px; 7 | } 8 | 9 | #waybar { 10 | background-color: @outline; 11 | } 12 | #waybar > box { 13 | margin: 4px; 14 | background-color: @main-bg; 15 | } 16 | 17 | button { 18 | border-radius: 16px; 19 | min-width: 16px; 20 | padding: 0 10px; 21 | } 22 | button:hover { 23 | background-color: @hover-bg; 24 | color: @hover-fg; 25 | } 26 | 27 | tooltip { 28 | border: 2px solid @main-br; 29 | border-radius: 10px; 30 | background-color: @main-bg; 31 | } 32 | tooltip > box { 33 | padding: 0 6px; 34 | } 35 | -------------------------------------------------------------------------------- /styles/modules-left.css: -------------------------------------------------------------------------------- 1 | /*-------------- 2 | username 3 | --------------*/ 4 | 5 | #custom-user { 6 | padding-right: 12px; 7 | } 8 | 9 | /*---------------- 10 | workspaces 11 | ----------------*/ 12 | 13 | #custom-left_div.1, 14 | #custom-right_div.1 { 15 | color: @workspaces; 16 | } 17 | #workspaces { 18 | padding: 0 1px; 19 | background-color: @workspaces; 20 | } 21 | #workspaces button.active label, 22 | #workspaces button.focused label { 23 | color: @accent; 24 | } 25 | 26 | /*------------------ 27 | window title 28 | ------------------*/ 29 | 30 | #window { 31 | margin-left: 12px; 32 | } 33 | -------------------------------------------------------------------------------- /modules/cpu.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "cpu": { 3 | "interval": 10, 4 | "format": "󰍛 {usage}%", 5 | "format-warning": "󰀨 {usage}%", 6 | "format-critical": "󰀨 {usage}%", 7 | // "format-icons": 8 | "min-length": 7, 9 | "max-length": 7, 10 | // "align": 11 | // "justify": 12 | // "rotate": 13 | "states": { 14 | "warning": 75, 15 | "critical": 90 16 | }, 17 | // "on-click": 18 | // "on-click-middle": 19 | // "on-click-right": 20 | // "on-update": 21 | // "on-scroll-up": 22 | // "on-scroll-down": 23 | // "smooth-scrolling-threshold": 24 | "tooltip": false 25 | // "expand": 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /modules/custom/distro.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "custom/distro": { 3 | // "exec": 4 | // "exec-if": 5 | // "exec-on-event": 6 | // "hide-empty-text": 7 | // "return-type": 8 | // "interval": 9 | // "restart-interval": 10 | // "signal": 11 | "format": "󰣇", 12 | // "format-icons": 13 | // "rotate": 14 | // "min-length": 15 | // "max-length": 16 | // "align": 17 | // "justify": 18 | // "on-click": 19 | // "on-click-middle": 20 | // "on-click-right": 21 | // "on-update": 22 | // "on-scroll-up": 23 | // "on-scroll-down": 24 | // "smooth-scrolling-threshold": 25 | "tooltip": false 26 | // "tooltip-format": 27 | // "escape": 28 | // "menu": 29 | // "menu-file": 30 | // "menu-actions": 31 | // "expand": 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /styles/states.css: -------------------------------------------------------------------------------- 1 | #custom-trigger:hover, 2 | #idle_inhibitor:hover, 3 | #clock.date:hover, 4 | #network:hover, 5 | #bluetooth:hover, 6 | #custom-system_update:hover, 7 | #mpris:hover, 8 | #pulseaudio:hover, 9 | #wireplumber:hover { 10 | color: @hover-fg; 11 | } 12 | 13 | /* inactive state */ 14 | #idle_inhibitor.deactivated, 15 | #mpris.paused, 16 | #pulseaudio.output.muted, 17 | #pulseaudio.input.source-muted, 18 | #wireplumber.muted { 19 | color: @hover-fg; 20 | } 21 | 22 | #memory.warning, 23 | #cpu.warning, 24 | #battery.warning { 25 | color: @warning; 26 | } 27 | 28 | #temperature.critical, 29 | #memory.critical, 30 | #cpu.critical, 31 | #battery.critical { 32 | color: @critical; 33 | } 34 | 35 | #battery.charging { 36 | color: @charging; 37 | } 38 | -------------------------------------------------------------------------------- /modules/memory.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "memory": { 3 | "interval": 10, 4 | "format": "󰘚 {percentage}%", 5 | "format-warning": "󰀧 {percentage}%", 6 | "format-critical": "󰀧 {percentage}%", 7 | // "format-icons": 8 | // "rotate": 9 | "states": { 10 | "warning": 75, 11 | "critical": 90 12 | }, 13 | "min-length": 7, 14 | "max-length": 7, 15 | // "align": 16 | // "justify": 17 | // "on-click": 18 | // "on-click-middle": 19 | // "on-click-right": 20 | // "on-update": 21 | // "on-scroll-up": 22 | // "on-scroll-down": 23 | // "smooth-scrolling-threshold": 24 | // "tooltip": 25 | "tooltip-format": "Memory Used: {used:0.0f}/{total:0.0f} GB" 26 | // "menu": 27 | // "menu-file": 28 | // "menu-actions": 29 | // "expand": 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scripts/_fzf_colorizer.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # A helper script that syncs fzf colors with the current Waybar theme 4 | # 5 | 6 | main() { 7 | local wcss="$HOME/.config/waybar/current-theme.css" 8 | 9 | local wtheme fcolors 10 | wtheme=$(sed 1q "$wcss" | awk '{print $2}') 11 | fcolors="$HOME/.config/waybar/themes/fzf/$wtheme.txt" 12 | 13 | # Extract theme colors starting from line 3 up to (but not including) the 14 | # first blank line 15 | local wcolors 16 | wcolors=$(sed -n '3,${/^ *$/Q;p}' "$wcss") 17 | 18 | local element color hex 19 | fcconf=() 20 | while read -r element color; do 21 | read -r _ _ hex < <(grep " $color " <<< "$wcolors") 22 | hex=${hex%;} 23 | fcconf+=("--color=$element:$hex") 24 | done < "$fcolors" 25 | } 26 | 27 | main 28 | -------------------------------------------------------------------------------- /modules/idle_inhibitor.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "idle_inhibitor": { 3 | "format": "{icon}", 4 | "format-icons": { 5 | "activated": "󰈈", 6 | "deactivated": "󰈉" 7 | }, 8 | // "rotate": 9 | "min-length": 3, 10 | "max-length": 3, 11 | // "align": 12 | // "justify": 13 | // "on-click": 14 | // "on-click-middle": 15 | // "on-click-right": 16 | // "on-update": 17 | // "on-scroll-up": 18 | // "on-scroll-down": 19 | // "smooth-scrolling-threshold": 20 | // "tooltip": 21 | "tooltip-format-activated": "Idle Inhibitor: Activated", 22 | "tooltip-format-deactivated": "Idle Inhibitor: Deactivated", 23 | "start-activated": false 24 | // "timeout": 25 | // "menu": 26 | // "menu-file": 27 | // "menu-actions": 28 | // "expand": 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /modules/custom/power_menu.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "custom/power_menu": { 3 | // "exec": 4 | // "exec-if": 5 | // "exec-on-event": 6 | // "hide-empty-text": 7 | // "return-type": 8 | // "interval": 9 | // "restart-interval": 10 | // "signal": 11 | "format": "󰤄", 12 | // "format-icons": 13 | // "rotate": 14 | // "min-length": 15 | // "max-length": 16 | // "align": 17 | // "justify": 18 | "on-click": "kitty -e ~/.config/waybar/scripts/power-menu.sh", 19 | // "on-click-middle": 20 | // "on-click-right": 21 | // "on-update": 22 | // "on-scroll-up": 23 | // "on-scroll-down": 24 | // "smooth-scrolling-threshold": 25 | // "tooltip": 26 | "tooltip-format": "Power Menu" 27 | // "escape": 28 | // "menu": 29 | // "menu-file": 30 | // "menu-actions": 31 | // "expand": 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /modules/backlight.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "backlight": { 3 | // "interval": 4 | "format": "{icon} {percent}%", 5 | "format-icons": [ 6 | "", "", "", "", "", "", "", "", "" 7 | ], 8 | "min-length": 7, 9 | "max-length": 7, 10 | // "align": 11 | // "justify": 12 | // "rotate": 13 | // "states": 14 | // "on-click": 15 | // "on-click-middle": 16 | // "on-click-right": 17 | // "on-update": 18 | "on-scroll-up": "~/.config/waybar/scripts/backlight.sh up", 19 | "on-scroll-down": "~/.config/waybar/scripts/backlight.sh down", 20 | // "smooth-scrolling-threshold": 21 | // "reverse-scrolling": 22 | // "reverse-mouse-scrolling": 23 | // "scroll-step": 24 | // "min-brightness": 25 | "tooltip": false 26 | // "tooltip-format": 27 | // "menu": 28 | // "menu-file": 29 | // "menu-actions": 30 | // "expand": 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /modules/temperature.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "temperature": { 3 | "thermal-zone": 1, 4 | // "hwmon-path": 5 | // "hwmon-path-abs": 6 | // "input-filename": 7 | // "warning-threshold": 8 | "critical-threshold": 90, 9 | "interval": 10, 10 | // "format-warning": 11 | "format-critical": "󰀦 {temperatureC}°C", 12 | "format": "{icon} {temperatureC}°C", 13 | "format-icons": [ 14 | "󱃃", "󰔏", "󱃂" 15 | ], 16 | // "rotate": 17 | "min-length": 8, 18 | "max-length": 8, 19 | // "align": 20 | // "justify": 21 | // "on-click": 22 | // "on-click-middle": 23 | // "on-click-right": 24 | // "on-update": 25 | // "on-scroll-up": 26 | // "on-scroll-down": 27 | // "smooth-scrolling-threshold": 28 | // "tooltip": 29 | "tooltip-format": "Fahrenheit: {temperatureF}°F" 30 | // "menu": 31 | // "menu-file": 32 | // "menu-actions": 33 | // "expand": 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /modules/custom/system_update.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "custom/system_update": { 3 | "exec": "~/.config/waybar/scripts/system-update.sh module", 4 | // "exec-if": 5 | // "exec-on-event": 6 | // "hide-empty-text": 7 | "return-type": "json", 8 | "interval": 3600, 9 | // "restart-interval": 10 | "signal": 1, 11 | "format": "{}", 12 | // "format-icons": 13 | // "rotate": 14 | // "align": 15 | // "justify": 16 | "min-length": 2, 17 | "max-length": 2, 18 | "on-click": "kitty -e ~/.config/waybar/scripts/system-update.sh", 19 | // "on-click-middle": 20 | "on-click-right": "pkill -RTMIN+1 waybar" 21 | // "on-update": 22 | // "on-scroll-up": 23 | // "on-scroll-down": 24 | // "smooth-scrolling-threshold": 25 | // "tooltip": 26 | // "tooltip-format": 27 | // "escape": 28 | // "menu": 29 | // "menu-file": 30 | // "menu-actions": 31 | // "expand": 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /modules/mpris.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "mpris": { 3 | // "player": 4 | // "ignored-players": 5 | // "interval": 6 | "format": "{player_icon} {title} - {artist}", 7 | "format-paused": "{status_icon} {title} - {artist}", 8 | "tooltip-format": "Playing: {title} - {artist}", 9 | "tooltip-format-paused": "Paused: {title} - {artist}", 10 | // "enable-tooltip-len-limits": 11 | // "on-click": 12 | // "on-click-middle": 13 | // "on-click-right": 14 | "player-icons": { 15 | "default": "󰐊" 16 | }, 17 | "status-icons": { 18 | "paused": "󰏤" 19 | }, 20 | // "artist-len": 21 | // "album-len": 22 | // "title-len": 23 | // "dynamic-len": 24 | // "dynamic-order": 25 | // "dynamic-separator": 26 | // "dynamic-importance-order": 27 | // "truncate-hours": 28 | // "ellipsis": 29 | // "rotate": 30 | // "min-length": 31 | "max-length": 1000 32 | // "align": 33 | // "justify": 34 | // "expand": 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /modules/hyprland/workspaces.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "hyprland/workspaces": { 3 | // "active-only": 4 | // "hide-active": 5 | // "all-outputs": 6 | "format": "{icon}", 7 | "format-icons": { 8 | "active": "", 9 | "default": "" 10 | }, 11 | "persistent-workspaces": { 12 | "*": 5 13 | }, 14 | // "persistent-only": 15 | // "show-special": 16 | // "special-visible-only": 17 | // "sort-by": 18 | // "window-rewrite": 19 | // "window-rewrite-default": 20 | // "format-window-separator": 21 | "workspace-taskbar": { 22 | // "enable": 23 | // "update-active-window": 24 | // "format": 25 | // "icon-size": 26 | // "icon-theme": 27 | // "orientation": 28 | // "ignore-list": 29 | // "on-click-window": 30 | }, 31 | // "move-to-monitor": 32 | // "ignore-workspaces": 33 | "on-scroll-up": "hyprctl dispatch workspace +1", 34 | "on-scroll-down": "hyprctl dispatch workspace -1", 35 | // "expand": 36 | "cursor": true 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /styles/modules-right.css: -------------------------------------------------------------------------------- 1 | /*---------------- 2 | media info 3 | ----------------*/ 4 | 5 | #mpris { 6 | padding: 0 12px; 7 | } 8 | 9 | /*------------ 10 | volume 11 | ------------*/ 12 | 13 | #custom-left_div.6 { 14 | color: @volume; 15 | } 16 | #pulseaudio, 17 | #wireplumber { 18 | background-color: @volume; 19 | } 20 | 21 | /*---------------- 22 | brightness 23 | ----------------*/ 24 | 25 | #custom-left_div.7 { 26 | background-color: @volume; 27 | color: @backlight; 28 | } 29 | #backlight { 30 | background-color: @backlight; 31 | } 32 | 33 | /*------------- 34 | battery 35 | -------------*/ 36 | 37 | #custom-left_div.8 { 38 | background-color: @backlight; 39 | color: @battery; 40 | } 41 | #battery { 42 | background-color: @battery; 43 | } 44 | #custom-left_inv.2 { 45 | color: @battery; 46 | } 47 | 48 | /*---------------- 49 | power menu 50 | ----------------*/ 51 | 52 | #custom-power_menu { 53 | border-radius: 16px; 54 | padding: 0 19px 0 16px; 55 | color: @accent; 56 | } 57 | #custom-power_menu:hover { 58 | background-color: @hover-bg; 59 | } 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jesse Mirabel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/power-menu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Launch a power menu 4 | # 5 | # Requirements: 6 | # - fzf 7 | # 8 | # Author: Jesse Mirabel 9 | # Created: August 19, 2025 10 | # License: MIT 11 | 12 | fcconf=() 13 | # Get fzf color config 14 | # shellcheck disable=SC1090,SC2154 15 | . ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true 16 | # If the file is missing, fzf will fall back to its default colors 17 | 18 | main() { 19 | local list=( 20 | 'Lock' 21 | 'Shutdown' 22 | 'Reboot' 23 | 'Logout' 24 | 'Hibernate' 25 | 'Suspend' 26 | ) 27 | local opts=( 28 | '--border=sharp' 29 | '--border-label= Power Menu ' 30 | '--height=~100%' 31 | '--highlight-line' 32 | '--no-input' 33 | '--pointer=' 34 | '--reverse' 35 | "${fcconf[@]}" 36 | ) 37 | 38 | local selected 39 | selected=$(printf '%s\n' "${list[@]}" | fzf "${opts[@]}") 40 | case $selected in 41 | 'Lock') loginctl lock-session ;; 42 | 'Shutdown') systemctl poweroff ;; 43 | 'Reboot') systemctl reboot ;; 44 | 'Logout') loginctl terminate-session "$XDG_SESSION_ID" ;; 45 | 'Hibernate') systemctl hibernate ;; 46 | 'Suspend') systemctl suspend ;; 47 | *) exit 1 ;; 48 | esac 49 | } 50 | 51 | main 52 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RED='\033[1;31m' 4 | GRN='\033[1;32m' 5 | BLU='\033[1;34m' 6 | RST='\033[0m' 7 | 8 | DEPS=( 9 | bluez 10 | bluez-utils # bluetoothctl 11 | brightnessctl 12 | fzf 13 | networkmanager # nmcli 14 | pacman-contrib # checkupdates 15 | pipewire-pulse 16 | otf-commit-mono-nerd 17 | ) 18 | 19 | main() { 20 | printf '%bInstalling dependencies...%b\n' "$BLU" "$RST" 21 | 22 | local package 23 | local error=0 24 | for package in "${DEPS[@]}"; do 25 | if pacman -Qi "$package" > /dev/null; then 26 | printf '[%b/%b] %s\n' "$GRN" "$RST" "$package" 27 | else 28 | printf '[ ] %s...\n' "$package" 29 | if sudo pacman -S --noconfirm "$package"; then 30 | printf '[%b+%b] %s\n' "$GRN" "$RST" "$package" 31 | else 32 | printf '[%bx%b] %s\n' "$RED" "$RST" "$package" 33 | ((error++)) 34 | fi 35 | fi 36 | done 37 | 38 | printf '\n%bMaking scripts executable...%b\n' "$BLU" "$RST" 39 | chmod +x ~/.config/waybar/scripts/*.sh --verbose 40 | 41 | pkill waybar 42 | waybar &> /dev/null & 43 | disown 44 | 45 | if ((error > 0)); then 46 | printf '\nInstallation completed with %b%d errors%b\n' \ 47 | "$RED" "$error" "$RST" 48 | else 49 | printf '\n%bInstallation complete!%b\n' "$GRN" "$RST" 50 | fi 51 | } 52 | 53 | main 54 | -------------------------------------------------------------------------------- /modules/network.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | // "interface": 4 | // "rfkill": 5 | "interval": 10, 6 | // "family": 7 | "format": "󰤨", 8 | "format-ethernet": "󰈀", 9 | "format-wifi": "{icon}", 10 | // "format-linked": 11 | "format-disconnected": "󰤯", 12 | "format-disabled": "󰤮", 13 | // "format-alt": 14 | "format-icons": [ 15 | "󰤟", "󰤢", "󰤥", "󰤨" 16 | ], 17 | // "rotate": 18 | "min-length": 2, 19 | "max-length": 2, 20 | // "align": 21 | // "justify": 22 | "on-click": "kitty -e ~/.config/waybar/scripts/network.sh", 23 | // "on-click-middle": 24 | "on-click-right": "nmcli radio wifi off && notify-send 'Wi-Fi Disabled' -i 'network-wireless-off' -r 1125", 25 | // "on-update": 26 | // "on-scroll-up": 27 | // "on-scroll-down": 28 | // "smooth-scrolling-threshold": 29 | // "tooltip": 30 | "tooltip-format": "Gateway: {gwaddr}", 31 | "tooltip-format-ethernet": "Interface: {ifname}", 32 | "tooltip-format-wifi": "Network: {essid}\nIP Addr: {ipaddr}/{cidr}\nStrength: {signalStrength}%\nFrequency: {frequency} GHz", 33 | "tooltip-format-disconnected": "Wi-Fi Disconnected", 34 | "tooltip-format-disabled": "Wi-Fi Disabled" 35 | // "menu": 36 | // "menu-file": 37 | // "menu-actions": 38 | // "expand": 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /modules/battery.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "battery": { 3 | // "bat": 4 | // "adapter": 5 | // "design-capacity": 6 | // "full-at": 7 | // "interval": 8 | "states": { 9 | "warning": 20, 10 | "critical": 10 11 | }, 12 | "format": "{icon} {capacity}%", 13 | "format-time": "{H}h {M}min", 14 | "format-icons": [ 15 | "󰂎", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹" 16 | ], 17 | "format-charging": "󰉁 {capacity}%", 18 | "min-length": 7, 19 | "max-length": 7, 20 | // "align": 21 | // "justify": 22 | // "rotate": 23 | // "on-click": 24 | // "on-click-middle": 25 | // "on-click-right": 26 | // "on-update": 27 | // "on-scroll-up": 28 | // "on-scroll-down": 29 | // "smooth-scrolling-threshold": 30 | // "tooltip": 31 | "tooltip-format": "Discharging: {time}", 32 | "tooltip-format-charging": "Charging: {time}", 33 | // "weighted-average": 34 | // "bat-compatibility": 35 | // "menu": 36 | // "menu-file": 37 | // "menu-actions": 38 | // "expand": 39 | "events": { 40 | "on-discharging-warning": "notify-send 'Battery Low (20%)' -u critical -i 'battery-020' -r 1525", 41 | "on-discharging-critical": "notify-send 'Battery Critical (10%)' -u critical -i 'battery-010' -r 1525", 42 | "on-charging-100": "notify-send 'Battery Full (100%)' -i 'battery-100-charged'" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /modules/bluetooth.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "bluetooth": { 3 | // "controller": 4 | // "format-device-preference": 5 | "format": "󰂯", 6 | "format-disabled": "󰂲", 7 | "format-off": "󰂲", 8 | "format-on": "󰂰", 9 | "format-connected": "󰂱", 10 | // "format-connected-battery": 11 | // "format-no-controller": 12 | // "format-icons": 13 | // "rotate": 14 | "min-length": 2, 15 | "max-length": 2, 16 | // "align": 17 | // "justify": 18 | "on-click": "kitty -e ~/.config/waybar/scripts/bluetooth.sh", 19 | // "on-click-middle": 20 | "on-click-right": "bluetoothctl power off && notify-send 'Bluetooth Off' -i 'network-bluetooth-inactive' -r 1925", 21 | // "on-scroll-up": 22 | // "on-scroll-down": 23 | // "smooth-scrolling-threshold": 24 | // "tooltip": 25 | "tooltip-format": "Device Addr: {device_address}", 26 | "tooltip-format-disabled": "Bluetooth Disabled", 27 | "tooltip-format-off": "Bluetooth Off", 28 | "tooltip-format-on": "Bluetooth Disconnected", 29 | "tooltip-format-connected": "Device: {device_alias}", 30 | "tooltip-format-enumerate-connected": "Device: {device_alias}", 31 | "tooltip-format-connected-battery": "Device: {device_alias}\nBattery: {device_battery_percentage}%", 32 | "tooltip-format-enumerate-connected-battery": "Device: {device_alias}\nBattery: {device_battery_percentage}%" 33 | // "menu": 34 | // "menu-file": 35 | // "menu-actions": 36 | // "expand": 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scripts/backlight.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Adjust screen brightness and send a notification with the current level 4 | # 5 | # Requirements: 6 | # - brightnessctl 7 | # - notify-send (libnotify) 8 | # 9 | # Author: Jesse Mirabel 10 | # Created: August 28, 2025 11 | # License: MIT 12 | 13 | VALUE=1 14 | 15 | print-usage() { 16 | local script=${0##*/} 17 | cat <<- EOF 18 | USAGE: $script [OPTIONS] 19 | 20 | Adjust screen brightness and send a notification with the current level 21 | 22 | OPTIONS: 23 | up Increase brightness by 24 | down Decrease brightness by 25 | Default value: $VALUE 26 | 27 | EXAMPLES: 28 | Increase brightness: 29 | $ $script up 30 | 31 | Decrease brightness by 5: 32 | $ $script down 5 33 | EOF 34 | exit 1 35 | } 36 | 37 | set-brightness() { 38 | local op 39 | case $action in 40 | 'up') op='+' ;; 41 | 'down') op='-' ;; 42 | esac 43 | 44 | brightnessctl -n set "${value}%${op}" > /dev/null 45 | 46 | local level 47 | level=$(brightnessctl -m | awk -F ',' '{print $4}') 48 | 49 | notify-send "Brightness: $level" -h int:value:"$level" -i 'contrast' -r 2825 50 | } 51 | 52 | main() { 53 | action=$1 54 | value=${2:-$VALUE} 55 | 56 | ! ((value > 0)) && print-usage 57 | 58 | case $action in 59 | 'up' | 'down') set-brightness ;; 60 | *) print-usage ;; 61 | esac 62 | } 63 | 64 | main "$@" 65 | -------------------------------------------------------------------------------- /modules/custom/dividers.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | /*------------------- 3 | left dividers 4 | -------------------*/ 5 | 6 | "custom/left_div#1": { 7 | "format": "", 8 | "tooltip": false 9 | }, 10 | "custom/left_div#2": { 11 | "format": "", 12 | "tooltip": false 13 | }, 14 | "custom/left_div#3": { 15 | "format": "", 16 | "tooltip": false 17 | }, 18 | "custom/left_div#4": { 19 | "format": "", 20 | "tooltip": false 21 | }, 22 | "custom/left_div#5": { 23 | "format": "", 24 | "tooltip": false 25 | }, 26 | "custom/left_div#6": { 27 | "format": "", 28 | "tooltip": false 29 | }, 30 | "custom/left_div#7": { 31 | "format": "", 32 | "tooltip": false 33 | }, 34 | "custom/left_div#8": { 35 | "format": "", 36 | "tooltip": false 37 | }, 38 | 39 | // inverse 40 | "custom/left_inv#1": { 41 | "format": "", 42 | "tooltip": false 43 | }, 44 | "custom/left_inv#2": { 45 | "format": "", 46 | "tooltip": false 47 | }, 48 | 49 | /*-------------------- 50 | right dividers 51 | --------------------*/ 52 | 53 | "custom/right_div#1": { 54 | "format": "", 55 | "tooltip": false 56 | }, 57 | "custom/right_div#2": { 58 | "format": "", 59 | "tooltip": false 60 | }, 61 | "custom/right_div#3": { 62 | "format": "", 63 | "tooltip": false 64 | }, 65 | "custom/right_div#4": { 66 | "format": "", 67 | "tooltip": false 68 | }, 69 | "custom/right_div#5": { 70 | "format": "", 71 | "tooltip": false 72 | }, 73 | 74 | // inverse 75 | "custom/right_inv#1": { 76 | "format": "", 77 | "tooltip": false 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /modules/clock.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "clock#time": { 3 | // "interval": 4 | "format": "{:%H:%M}", 5 | // "timezone": 6 | // "timezones": 7 | // "locale": 8 | "min-length": 5, 9 | "max-length": 5, 10 | // "rotate": 0, 11 | // "on-click": 12 | // "on-click-middle": 13 | // "on-click-right": 14 | // "on-scroll-up": 15 | // "on-scroll-down": 16 | // "smooth-scrolling-threshold": 17 | // "tooltip": 18 | "tooltip-format": "Standard Time: {:%I:%M %p}" 19 | // "menu": 20 | // "menu-file": 21 | // "menu-actions": 22 | // "expand": 23 | }, 24 | 25 | /*-------------- 26 | calendar 27 | --------------*/ 28 | 29 | "clock#date": { 30 | // "interval": 31 | "format": "󰸗 {:%d-%m}", 32 | // "timezone": 33 | // "timezones": 34 | // "locale": 35 | "min-length": 8, 36 | "max-length": 8, 37 | // "rotate": 38 | // "on-click": 39 | // "on-click-middle": 40 | // "on-click-right": 41 | // "on-scroll-up": 42 | // "on-scroll-down": 43 | // "smooth-scrolling-threshold": 44 | // "tooltip": 45 | "tooltip-format": "{calendar}", 46 | // "menu": 47 | // "menu-file": 48 | // "menu-actions": 49 | // "expand": 50 | "calendar": { 51 | "mode": "month", 52 | "mode-mon-col": 6, 53 | // "week-pos": 54 | // "on-scroll": 55 | "format": { 56 | "months": "{}", 57 | "days": "{}", 58 | // "weeks": 59 | "weekdays": "{}", 60 | "today": "{}" 61 | } 62 | }, 63 | "actions": { 64 | "on-click": "mode" 65 | // "on-click-middle": 66 | // "on-click-right": 67 | // "on-scroll-up": 68 | // "on-scroll-down": 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /modules/custom/user.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "group/user": { 3 | "orientation": "horizontal", 4 | "modules": [ 5 | "custom/trigger", 6 | "custom/user" 7 | ], 8 | "drawer": { 9 | // "transition-duration": 10 | // "transition-left-to-right": 11 | // "children-class": 12 | // "click-to-reveal": 13 | } 14 | }, 15 | 16 | "custom/trigger": { 17 | // "exec": 18 | // "exec-if": 19 | // "exec-on-event": 20 | // "hide-empty-text": 21 | // "return-type": 22 | // "interval": 23 | // "restart-interval": 24 | // "signal": 25 | "format": "󰍜", 26 | // "format-icons": 27 | // "rotate": 28 | "min-length": 4, 29 | "max-length": 4, 30 | // "align": 31 | // "justify": 32 | // "on-click": 33 | // "on-click-middle": 34 | // "on-click-right": 35 | // "on-update": 36 | // "on-scroll-up": 37 | // "on-scroll-down": 38 | // "smooth-scrolling-threshold": 39 | "tooltip": false 40 | // "tooltip-format": 41 | // "escape": 42 | // "menu": 43 | // "menu-file": 44 | // "menu-actions": 45 | // "expand": 46 | }, 47 | 48 | /*-------------- 49 | username 50 | --------------*/ 51 | 52 | "custom/user": { 53 | "exec": "id -un", 54 | // "exec-if": 55 | // "exec-on-event": 56 | // "hide-empty-text": 57 | // "return-type": 58 | // "interval": 59 | // "restart-interval": 60 | // "signal": 61 | "format": "{}", 62 | // "format-icons": 63 | // "rotate": 64 | // "min-length": 65 | // "max-length": 66 | // "align": 67 | // "justify": 68 | // "on-click": 69 | // "on-click-middle": 70 | // "on-click-right": 71 | // "on-update": 72 | // "on-scroll-up": 73 | // "on-scroll-down": 74 | // "smooth-scrolling-threshold": 75 | "tooltip": false 76 | // "tooltip-format": 77 | // "escape": 78 | // "menu": 79 | // "menu-file": 80 | // "menu-actions": 81 | // "expand": 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /config.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "~/.config/waybar/modules/*.jsonc", 4 | "~/.config/waybar/modules/custom/*.jsonc", 5 | "~/.config/waybar/modules/hyprland/*.jsonc" 6 | 7 | // modules that are not included by default: 8 | // "~/.config/waybar/modules/extras/*.jsonc" 9 | ], 10 | 11 | /*------------ 12 | layout 13 | ------------*/ 14 | 15 | "modules-left": [ 16 | "group/user", 17 | "custom/left_div#1", 18 | "hyprland/workspaces", 19 | "custom/right_div#1", 20 | "hyprland/window" 21 | ], 22 | "modules-center": [ 23 | "hyprland/windowcount", 24 | "custom/left_div#2", 25 | "temperature", 26 | "custom/left_div#3", 27 | "memory", 28 | "custom/left_div#4", 29 | "cpu", 30 | "custom/left_inv#1", 31 | "custom/left_div#5", 32 | "custom/distro", 33 | "custom/right_div#2", 34 | "custom/right_inv#1", 35 | "idle_inhibitor", 36 | "clock#time", 37 | "custom/right_div#3", 38 | "clock#date", 39 | "custom/right_div#4", 40 | "network", 41 | "bluetooth", 42 | "custom/system_update", 43 | "custom/right_div#5" 44 | ], 45 | "modules-right": [ 46 | "mpris", 47 | "custom/left_div#6", 48 | "group/pulseaudio", 49 | "custom/left_div#7", 50 | "backlight", 51 | "custom/left_div#8", 52 | "battery", 53 | "custom/left_inv#2", 54 | "custom/power_menu" 55 | ], 56 | 57 | /*------------- 58 | options 59 | -------------*/ 60 | 61 | // "expand-center": 62 | // "expand-left": 63 | // "expand-right": 64 | "layer": "top", 65 | // "output": 66 | // "position": 67 | "height": 0, 68 | "width": 0, 69 | "margin": 0, 70 | // "margin-top": 71 | // "margin-left": 72 | // "margin-bottom": 73 | // "margin-right": 74 | // "no-center": 75 | "spacing": 0, 76 | // "name": 77 | "mode": "dock", 78 | // "start_hidden": 79 | // "modifier-reset": 80 | // "exclusive": 81 | // "fixed-center": 82 | // "passthrough": 83 | // "ipc": 84 | // "id": 85 | "reload_style_on_change": true 86 | // "on-sigusr1": 87 | // "on-sigusr2": 88 | } 89 | -------------------------------------------------------------------------------- /current-theme.css: -------------------------------------------------------------------------------- 1 | /* catppuccin mocha */ 2 | 3 | @define-color rosewater #f5e0dc; 4 | @define-color flamingo #f2cdcd; 5 | @define-color pink #f5c2e7; 6 | @define-color mauve #cba6f7; 7 | @define-color red #f38ba8; 8 | @define-color maroon #eba0ac; 9 | @define-color peach #fab387; 10 | @define-color yellow #f9e2af; 11 | @define-color green #a6e3a1; 12 | @define-color teal #94e2d5; 13 | @define-color sky #89dceb; 14 | @define-color sapphire #74c7ec; 15 | @define-color blue #89b4fa; 16 | @define-color lavender #b4befe; 17 | @define-color text #cdd6f4; 18 | @define-color subtext1 #bac2de; 19 | @define-color subtext0 #a6adc8; 20 | @define-color overlay2 #9399b2; 21 | @define-color overlay1 #7f849c; 22 | @define-color overlay0 #6c7086; 23 | @define-color surface2 #585b70; 24 | @define-color surface1 #45475a; 25 | @define-color surface0 #313244; 26 | @define-color base #1e1e2e; 27 | @define-color mantle #181825; 28 | @define-color crust #11111b; 29 | 30 | /* 31 | br - border 32 | bg - background 33 | fg - foreground 34 | */ 35 | 36 | /* main colors */ 37 | 38 | @define-color accent @lavender; 39 | @define-color main-br @subtext0; 40 | @define-color main-bg @crust; 41 | @define-color main-fg @text; 42 | @define-color hover-bg @base; 43 | @define-color hover-fg alpha(@main-fg, 0.75); 44 | @define-color outline shade(@main-bg, 0.5); 45 | 46 | /* module colors */ 47 | 48 | @define-color workspaces @mantle; 49 | @define-color temperature @mantle; 50 | @define-color memory @base; 51 | @define-color cpu @surface0; 52 | @define-color time @surface0; 53 | @define-color date @base; 54 | @define-color tray @mantle; 55 | @define-color volume @mantle; 56 | @define-color backlight @base; 57 | @define-color battery @surface0; 58 | 59 | /* state colors */ 60 | 61 | @define-color warning @yellow; 62 | @define-color critical @red; 63 | @define-color charging @green; 64 | -------------------------------------------------------------------------------- /themes/catppuccin-latte.css: -------------------------------------------------------------------------------- 1 | /* catppuccin latte */ 2 | 3 | @define-color rosewater #dc8a78; 4 | @define-color flamingo #dd7878; 5 | @define-color pink #ea76cb; 6 | @define-color mauve #8839ef; 7 | @define-color red #d20f39; 8 | @define-color maroon #e64553; 9 | @define-color peach #fe640b; 10 | @define-color yellow #df8e1d; 11 | @define-color green #40a02b; 12 | @define-color teal #179299; 13 | @define-color sky #04a5e5; 14 | @define-color sapphire #209fb5; 15 | @define-color blue #1e66f5; 16 | @define-color lavender #7287fd; 17 | @define-color text #4c4f69; 18 | @define-color subtext1 #5c5f77; 19 | @define-color subtext0 #6c6f85; 20 | @define-color overlay2 #7c7f93; 21 | @define-color overlay1 #8c8fa1; 22 | @define-color overlay0 #9ca0b0; 23 | @define-color surface2 #acb0be; 24 | @define-color surface1 #bcc0cc; 25 | @define-color surface0 #ccd0da; 26 | @define-color base #eff1f5; 27 | @define-color mantle #e6e9ef; 28 | @define-color crust #dce0e8; 29 | 30 | /* 31 | br - border 32 | bg - background 33 | fg - foreground 34 | */ 35 | 36 | /* main colors */ 37 | 38 | @define-color accent @lavender; 39 | @define-color main-br @subtext0; 40 | @define-color main-bg @crust; 41 | @define-color main-fg @text; 42 | @define-color hover-bg @base; 43 | @define-color hover-fg alpha(@main-fg, 0.75); 44 | @define-color outline shade(@main-bg, 0.5); 45 | 46 | /* module colors */ 47 | 48 | @define-color workspaces @mantle; 49 | @define-color temperature @mantle; 50 | @define-color memory @base; 51 | @define-color cpu @surface0; 52 | @define-color time @surface0; 53 | @define-color date @base; 54 | @define-color tray @mantle; 55 | @define-color volume @mantle; 56 | @define-color backlight @base; 57 | @define-color battery @surface0; 58 | 59 | /* state colors */ 60 | 61 | @define-color warning @yellow; 62 | @define-color critical @red; 63 | @define-color charging @green; 64 | -------------------------------------------------------------------------------- /themes/catppuccin-mocha.css: -------------------------------------------------------------------------------- 1 | /* catppuccin mocha */ 2 | 3 | @define-color rosewater #f5e0dc; 4 | @define-color flamingo #f2cdcd; 5 | @define-color pink #f5c2e7; 6 | @define-color mauve #cba6f7; 7 | @define-color red #f38ba8; 8 | @define-color maroon #eba0ac; 9 | @define-color peach #fab387; 10 | @define-color yellow #f9e2af; 11 | @define-color green #a6e3a1; 12 | @define-color teal #94e2d5; 13 | @define-color sky #89dceb; 14 | @define-color sapphire #74c7ec; 15 | @define-color blue #89b4fa; 16 | @define-color lavender #b4befe; 17 | @define-color text #cdd6f4; 18 | @define-color subtext1 #bac2de; 19 | @define-color subtext0 #a6adc8; 20 | @define-color overlay2 #9399b2; 21 | @define-color overlay1 #7f849c; 22 | @define-color overlay0 #6c7086; 23 | @define-color surface2 #585b70; 24 | @define-color surface1 #45475a; 25 | @define-color surface0 #313244; 26 | @define-color base #1e1e2e; 27 | @define-color mantle #181825; 28 | @define-color crust #11111b; 29 | 30 | /* 31 | br - border 32 | bg - background 33 | fg - foreground 34 | */ 35 | 36 | /* main colors */ 37 | 38 | @define-color accent @lavender; 39 | @define-color main-br @subtext0; 40 | @define-color main-bg @crust; 41 | @define-color main-fg @text; 42 | @define-color hover-bg @base; 43 | @define-color hover-fg alpha(@main-fg, 0.75); 44 | @define-color outline shade(@main-bg, 0.5); 45 | 46 | /* module colors */ 47 | 48 | @define-color workspaces @mantle; 49 | @define-color temperature @mantle; 50 | @define-color memory @base; 51 | @define-color cpu @surface0; 52 | @define-color time @surface0; 53 | @define-color date @base; 54 | @define-color tray @mantle; 55 | @define-color volume @mantle; 56 | @define-color backlight @base; 57 | @define-color battery @surface0; 58 | 59 | /* state colors */ 60 | 61 | @define-color warning @yellow; 62 | @define-color critical @red; 63 | @define-color charging @green; 64 | -------------------------------------------------------------------------------- /themes/catppuccin-frappe.css: -------------------------------------------------------------------------------- 1 | /* catppuccin frappe */ 2 | 3 | @define-color rosewater #f2d5cf; 4 | @define-color flamingo #eebebe; 5 | @define-color pink #f4b8e4; 6 | @define-color mauve #ca9ee6; 7 | @define-color red #e78284; 8 | @define-color maroon #ea999c; 9 | @define-color peach #ef9f76; 10 | @define-color yellow #e5c890; 11 | @define-color green #a6d189; 12 | @define-color teal #81c8be; 13 | @define-color sky #99d1db; 14 | @define-color sapphire #85c1dc; 15 | @define-color blue #8caaee; 16 | @define-color lavender #babbf1; 17 | @define-color text #c6d0f5; 18 | @define-color subtext1 #b5bfe2; 19 | @define-color subtext0 #a5adce; 20 | @define-color overlay2 #949cbb; 21 | @define-color overlay1 #838ba7; 22 | @define-color overlay0 #737994; 23 | @define-color surface2 #626880; 24 | @define-color surface1 #51576d; 25 | @define-color surface0 #414559; 26 | @define-color base #303446; 27 | @define-color mantle #292c3c; 28 | @define-color crust #232634; 29 | 30 | /* 31 | br - border 32 | bg - background 33 | fg - foreground 34 | */ 35 | 36 | /* main colors */ 37 | 38 | @define-color accent @lavender; 39 | @define-color main-br @subtext0; 40 | @define-color main-bg @crust; 41 | @define-color main-fg @text; 42 | @define-color hover-bg @base; 43 | @define-color hover-fg alpha(@main-fg, 0.75); 44 | @define-color outline shade(@main-bg, 0.5); 45 | 46 | /* module colors */ 47 | 48 | @define-color workspaces @mantle; 49 | @define-color temperature @mantle; 50 | @define-color memory @base; 51 | @define-color cpu @surface0; 52 | @define-color time @surface0; 53 | @define-color date @base; 54 | @define-color tray @mantle; 55 | @define-color volume @mantle; 56 | @define-color backlight @base; 57 | @define-color battery @surface0; 58 | 59 | /* state colors */ 60 | 61 | @define-color warning @yellow; 62 | @define-color critical @red; 63 | @define-color charging @green; 64 | -------------------------------------------------------------------------------- /themes/catppuccin-macchiato.css: -------------------------------------------------------------------------------- 1 | /* catppuccin macchiato */ 2 | 3 | @define-color rosewater #f4dbd6; 4 | @define-color flamingo #f0c6c6; 5 | @define-color pink #f5bde6; 6 | @define-color mauve #c6a0f6; 7 | @define-color red #ed8796; 8 | @define-color maroon #ee99a0; 9 | @define-color peach #f5a97f; 10 | @define-color yellow #eed49f; 11 | @define-color green #a6da95; 12 | @define-color teal #8bd5ca; 13 | @define-color sky #91d7e3; 14 | @define-color sapphire #7dc4e4; 15 | @define-color blue #8aadf4; 16 | @define-color lavender #b7bdf8; 17 | @define-color text #cad3f5; 18 | @define-color subtext1 #b8c0e0; 19 | @define-color subtext0 #a5adcb; 20 | @define-color overlay2 #939ab7; 21 | @define-color overlay1 #8087a2; 22 | @define-color overlay0 #6e738d; 23 | @define-color surface2 #5b6078; 24 | @define-color surface1 #494d64; 25 | @define-color surface0 #363a4f; 26 | @define-color base #24273a; 27 | @define-color mantle #1e2030; 28 | @define-color crust #181926; 29 | 30 | /* 31 | br - border 32 | bg - background 33 | fg - foreground 34 | */ 35 | 36 | /* main colors */ 37 | 38 | @define-color accent @lavender; 39 | @define-color main-br @subtext0; 40 | @define-color main-bg @crust; 41 | @define-color main-fg @text; 42 | @define-color hover-bg @base; 43 | @define-color hover-fg alpha(@main-fg, 0.75); 44 | @define-color outline shade(@main-bg, 0.5); 45 | 46 | /* module colors */ 47 | 48 | @define-color workspaces @mantle; 49 | @define-color temperature @mantle; 50 | @define-color memory @base; 51 | @define-color cpu @surface0; 52 | @define-color time @surface0; 53 | @define-color date @base; 54 | @define-color tray @mantle; 55 | @define-color volume @mantle; 56 | @define-color backlight @base; 57 | @define-color battery @surface0; 58 | 59 | /* state colors */ 60 | 61 | @define-color warning @yellow; 62 | @define-color critical @red; 63 | @define-color charging @green; 64 | -------------------------------------------------------------------------------- /modules/extras/wireplumber.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "group/wireplumber": { 3 | "orientation": "horizontal", 4 | "modules": [ 5 | "wireplumber#output", 6 | "wireplumber#input" 7 | ], 8 | "drawer": { 9 | // "transition-duration": 10 | "transition-left-to-right": false 11 | // "children-class": 12 | // "click-to-reveal": 13 | } 14 | }, 15 | 16 | /*------------------- 17 | output device 18 | -------------------*/ 19 | 20 | "wireplumber#output": { 21 | "format": "{icon} {volume}%", 22 | "format-muted": "󰝟 {volume}%", 23 | // "format-source": 24 | // "format-source-muted": 25 | "format-icons": [ 26 | "󰕿", "󰖀", "󰕾" 27 | ], 28 | // "rotate": 29 | // "states": 30 | "min-length": 7, 31 | "max-length": 7, 32 | // "align": 33 | // "justify": 34 | // "scroll-step": 35 | "on-click": "~/.config/waybar/scripts/volume.sh output mute", 36 | // "on-click-middle": 37 | // "on-click-right": 38 | // "on-update": 39 | "on-scroll-up": "~/.config/waybar/scripts/volume.sh output raise", 40 | "on-scroll-down": "~/.config/waybar/scripts/volume.sh output lower", 41 | // "tooltip": 42 | "tooltip-format": "Device: {node_name}", 43 | // "max-volume": 44 | // "reverse-scrolling": 45 | "node-type": "Audio/Sink" 46 | // "menu": 47 | // "menu-file": 48 | // "menu-actions": 49 | }, 50 | 51 | /*---------------- 52 | microphone 53 | ----------------*/ 54 | 55 | "wireplumber#input": { 56 | "format": "󰍬 {volume}%", 57 | "format-muted": "󰍭 {volume}%", 58 | // "format-source": 59 | // "format-source-muted": 60 | // "rotate": 61 | // "states": 62 | "min-length": 7, 63 | "max-length": 7, 64 | // "align": 65 | // "justify": 66 | // "scroll-step": 67 | "on-click": "~/.config/waybar/scripts/volume.sh input mute", 68 | // "on-click-middle": 69 | // "on-click-right": 70 | // "on-update": 71 | "on-scroll-up": "~/.config/waybar/scripts/volume.sh input raise", 72 | "on-scroll-down": "~/.config/waybar/scripts/volume.sh input lower", 73 | // "tooltip": 74 | "tooltip-format": "Device: {node_name}", 75 | // "max-volume": 76 | // "reverse-scrolling": 77 | "node-type": "Audio/Source" 78 | // "menu": 79 | // "menu-file": 80 | // "menu-actions": 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /styles/modules-center.css: -------------------------------------------------------------------------------- 1 | /*------------------ 2 | window count 3 | ------------------*/ 4 | 5 | #windowcount { 6 | margin-right: 12px; 7 | } 8 | #windowcount label { 9 | color: @hover-fg; 10 | } 11 | 12 | /*----------------- 13 | temperature 14 | -----------------*/ 15 | 16 | #custom-left_div.2 { 17 | color: @temperature; 18 | } 19 | #temperature { 20 | background-color: @temperature; 21 | } 22 | 23 | /*------------ 24 | memory 25 | ------------*/ 26 | 27 | #custom-left_div.3 { 28 | background-color: @temperature; 29 | color: @memory; 30 | } 31 | #memory { 32 | background-color: @memory; 33 | } 34 | 35 | /*--------- 36 | cpu 37 | ---------*/ 38 | 39 | #custom-left_div.4 { 40 | background-color: @memory; 41 | color: @cpu; 42 | } 43 | #cpu { 44 | background-color: @cpu; 45 | } 46 | #custom-left_inv.1 { 47 | color: @cpu; 48 | } 49 | 50 | /*----------------- 51 | distro icon 52 | -----------------*/ 53 | 54 | #custom-left_div.5, 55 | #custom-right_div.2 { 56 | color: @accent; 57 | } 58 | #custom-distro { 59 | padding: 0 10px 0 5px; 60 | background-color: @accent; 61 | color: @main-bg; 62 | } 63 | 64 | /*-------------------- 65 | idle inhibitor 66 | --------------------*/ 67 | 68 | #custom-right_inv.1 { 69 | color: @time; 70 | } 71 | #idle_inhibitor { 72 | background-color: @time; 73 | } 74 | 75 | /*---------- 76 | time 77 | ----------*/ 78 | 79 | #clock.time { 80 | padding-right: 6px; 81 | background-color: @time; 82 | } 83 | #custom-right_div.3 { 84 | background-color: @date; 85 | color: @time; 86 | } 87 | 88 | /*---------- 89 | date 90 | ----------*/ 91 | 92 | #clock.date { 93 | padding-left: 6px; 94 | background-color: @date; 95 | } 96 | #custom-right_div.4 { 97 | background-color: @tray; 98 | color: @date; 99 | } 100 | 101 | /*----------------- 102 | system tray 103 | -----------------*/ 104 | 105 | #network { 106 | background-color: @tray; 107 | padding: 0 6px 0 4px; 108 | } 109 | #bluetooth { 110 | background-color: @tray; 111 | padding: 0 5px; 112 | } 113 | #custom-system_update { 114 | background-color: @tray; 115 | padding: 0 8px 0 2px; 116 | } 117 | #custom-right_div.5 { 118 | color: @tray; 119 | } 120 | -------------------------------------------------------------------------------- /modules/pulseaudio.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "group/pulseaudio": { 3 | "orientation": "horizontal", 4 | "modules": [ 5 | "pulseaudio#output", 6 | "pulseaudio#input" 7 | ], 8 | "drawer": { 9 | // "transition-duration": 10 | "transition-left-to-right": false 11 | // "children-class": 12 | // "click-to-reveal": 13 | } 14 | }, 15 | 16 | /*------------------- 17 | output device 18 | -------------------*/ 19 | 20 | "pulseaudio#output": { 21 | "format": "{icon} {volume}%", 22 | // "format-bluetooth": 23 | "format-muted": "{icon} {volume}%", 24 | // "format-source": 25 | // "format-source-muted": 26 | "format-icons": { 27 | "default": [ "󰕿", "󰖀", "󰕾" ], 28 | "default-muted": "󰝟", 29 | "headphone": "󰋋", 30 | "headphone-muted": "󰟎", 31 | "headset": "󰋎", 32 | "headset-muted": "󰋐" 33 | }, 34 | // "rotate": 35 | // "states": 36 | "min-length": 7, 37 | "max-length": 7, 38 | // "align": 39 | // "justify": 40 | // "scroll-step": 41 | "on-click": "~/.config/waybar/scripts/volume.sh output mute", 42 | // "on-click-middle": 43 | // "on-click-right": 44 | // "on-update": 45 | "on-scroll-up": "~/.config/waybar/scripts/volume.sh output raise", 46 | "on-scroll-down": "~/.config/waybar/scripts/volume.sh output lower", 47 | // "smooth-scrolling-threshold": 48 | // "tooltip": 49 | "tooltip-format": "Output Device: {desc}" 50 | // "max-volume": 51 | // "ignored-sinks": 52 | // "reverse-scrolling": 53 | // "reverse-mouse-scrolling": 54 | // "menu": 55 | // "menu-file": 56 | // "menu-actions": 57 | // "expand": 58 | }, 59 | 60 | /*---------------- 61 | microphone 62 | ----------------*/ 63 | 64 | "pulseaudio#input": { 65 | "format": "{format_source}", 66 | // "format-bluetooth": 67 | // "format-muted": 68 | "format-source": "󰍬 {volume}%", 69 | "format-source-muted": "󰍭 {volume}%", 70 | // "format-icons": 71 | // "rotate": 72 | // "states": 73 | "min-length": 7, 74 | "max-length": 7, 75 | // "align": 76 | // "justify": 77 | // "scroll-step": 78 | "on-click": "~/.config/waybar/scripts/volume.sh input mute", 79 | // "on-click-middle": 80 | // "on-click-right": 81 | // "on-update": 82 | "on-scroll-up": "~/.config/waybar/scripts/volume.sh input raise", 83 | "on-scroll-down": "~/.config/waybar/scripts/volume.sh input lower", 84 | // "smooth-scrolling-threshold": 85 | // "tooltip": 86 | "tooltip-format": "Input Device: {desc}" 87 | // "max-volume": 88 | // "ignored-sinks": 89 | // "reverse-scrolling": 90 | // "reverse-mouse-scrolling": 91 | // "menu": 92 | // "menu-file": 93 | // "menu-actions": 94 | // "expand": 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /scripts/system-update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Check for official and AUR package updates and upgrade them. When run with the 4 | # 'module' argument, output the status icon and update counts in JSON format for 5 | # Waybar 6 | # 7 | # Requirements: 8 | # - checkupdates (pacman-contrib) 9 | # - notify-send (libnotify) 10 | # - optional: an AUR helper 11 | # 12 | # Author: Jesse Mirabel 13 | # Created: August 16, 2025 14 | # License: MIT 15 | 16 | GRN='\033[1;32m' 17 | BLU='\033[1;34m' 18 | RST='\033[0m' 19 | 20 | TIMEOUT=10 21 | HELPERS=('aura' 'paru' 'pikaur' 'trizen' 'yay') 22 | 23 | detect-helper() { 24 | local h 25 | for h in "${HELPERS[@]}"; do 26 | if command -v "$h" > /dev/null; then 27 | helper=$h 28 | break 29 | fi 30 | done 31 | } 32 | 33 | check-updates() { 34 | is_online=true 35 | repo=0 36 | aur=0 37 | 38 | local rout rstat 39 | rout=$(timeout $TIMEOUT checkupdates) 40 | rstat=$? 41 | # 2 means no updates are available 42 | if ((rstat != 0 && rstat != 2)); then 43 | is_online=false 44 | return 1 45 | fi 46 | repo=$(grep -cve '^\s*$' <<< "$rout") 47 | 48 | if [[ -z $helper ]]; then 49 | return 0 50 | fi 51 | 52 | local aout astat 53 | aout=$(timeout $TIMEOUT "$helper" -Quaq) 54 | astat=$? 55 | # Return only if the exit status is non-zero and there is an error 56 | # message 57 | if ((${#aout} > 0 && astat != 0)); then 58 | is_online=false 59 | return 1 60 | fi 61 | aur=$(grep -cve '^\s*$' <<< "$aout") 62 | } 63 | 64 | update-packages() { 65 | printf '\n%bUpdating pacman packages...%b\n' "$BLU" "$RST" 66 | sudo pacman -Syu 67 | 68 | if [[ -n $helper ]]; then 69 | printf '\n%bUpdating AUR packages...%b\n' "$BLU" "$RST" 70 | "$helper" -Syu 71 | fi 72 | 73 | notify-send 'Update Complete' -i 'package-install' 74 | printf '\n%bUpdate Complete!%b\n' "$GRN" "$RST" 75 | read -rs -n 1 -p 'Press any key to exit...' 76 | } 77 | 78 | display-module() { 79 | if [[ $is_online == false ]]; then 80 | echo "{ \"text\": \"󰒑\", \"tooltip\": \"Cannot fetch updates. Right-click to retry.\" }" 81 | return 0 82 | fi 83 | 84 | local tooltip="Official: $repo" 85 | if [[ -n $helper ]]; then 86 | tooltip+="\nAUR($helper): $aur" 87 | fi 88 | 89 | local total=$((repo + aur)) 90 | if ((total == 0)); then 91 | echo "{ \"text\": \"󰸟\", \"tooltip\": \"No updates available\" }" 92 | else 93 | echo "{ \"text\": \"󰄠\", \"tooltip\": \"$tooltip\" }" 94 | fi 95 | } 96 | 97 | main() { 98 | detect-helper 99 | 100 | case $1 in 101 | 'module') 102 | check-updates 103 | display-module 104 | ;; 105 | *) 106 | printf '%bChecking for updates...%b' "$BLU" "$RST" 107 | check-updates 108 | update-packages 109 | # use signal to update the module 110 | pkill -RTMIN+1 waybar 111 | ;; 112 | esac 113 | } 114 | 115 | main "$@" 116 | -------------------------------------------------------------------------------- /scripts/network.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Scan, select, and connect to Wi-Fi networks 4 | # 5 | # Requirements: 6 | # - nmcli (networkmanager) 7 | # - fzf 8 | # - notify-send (libnotify) 9 | # 10 | # Author: Jesse Mirabel 11 | # Created: August 11, 2025 12 | # License: MIT 13 | 14 | fcconf=() 15 | # Get fzf color config 16 | # shellcheck disable=SC1090,SC2154 17 | . ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true 18 | # If the file is missing, fzf will fall back to its default colors 19 | 20 | RED='\033[1;31m' 21 | RST='\033[0m' 22 | 23 | TIMEOUT=5 24 | 25 | ensure-enabled() { 26 | local radio 27 | radio=$(nmcli radio wifi) 28 | if [[ $radio == 'enabled' ]]; then 29 | return 0 30 | fi 31 | nmcli radio wifi on 32 | 33 | local i state 34 | for ((i = 1; i <= TIMEOUT; i++)); do 35 | printf '\rEnabling Wi-Fi... (%d/%d)' $i $TIMEOUT 36 | 37 | state=$(nmcli -t -f STATE general) 38 | # If STATE returns anything other than this, we assume that Wi-Fi is 39 | # fully enabled 40 | if [[ $state != 'connected (local only)' ]]; then 41 | break 42 | fi 43 | sleep 1 44 | done 45 | notify-send 'Wi-Fi Enabled' -i 'network-wireless-on' -r 1125 46 | } 47 | 48 | get-network-list() { 49 | nmcli device wifi rescan 50 | 51 | local i 52 | for ((i = 1; i <= TIMEOUT; i++)); do 53 | printf '\rScanning for networks... (%d/%d)' $i $TIMEOUT 54 | 55 | list=$(timeout 1 nmcli device wifi list) 56 | networks=$(tail -n +2 <<< "$list" | awk '$2 != "--"') 57 | if [[ -n $networks ]]; then 58 | break 59 | fi 60 | done 61 | printf '\n%bScanning stopped.%b\n\n' "$RED" "$RST" 62 | 63 | if [[ -z $networks ]]; then 64 | notify-send 'Wi-Fi' 'No networks found' -i 'package-broken' 65 | return 1 66 | fi 67 | } 68 | 69 | select-network() { 70 | local header 71 | header=$(head -n 1 <<< "$list") 72 | local opts=( 73 | '--border=sharp' 74 | '--border-label= Wi-Fi Networks ' 75 | '--ghost=Search' 76 | "--header=$header" 77 | '--height=~100%' 78 | '--highlight-line' 79 | '--info=inline-right' 80 | '--pointer=' 81 | '--reverse' 82 | "${fcconf[@]}" 83 | ) 84 | 85 | bssid=$(fzf "${opts[@]}" <<< "$networks" | awk '{print $1}') 86 | if [[ -z $bssid ]]; then 87 | return 1 88 | fi 89 | if [[ $bssid == '*' ]]; then 90 | notify-send 'Wi-Fi' 'Already connected to this network' \ 91 | -i 'package-install' 92 | return 1 93 | fi 94 | } 95 | 96 | connect-to-network() { 97 | printf 'Connecting...\n' 98 | if ! nmcli --ask device wifi connect "$bssid"; then 99 | notify-send 'Wi-Fi' 'Failed to connect' -i 'package-purge' 100 | return 1 101 | fi 102 | notify-send 'Wi-Fi' 'Successfully connected' -i 'package-install' 103 | } 104 | 105 | main() { 106 | tput civis 107 | ensure-enabled || exit 1 108 | get-network-list || exit 1 109 | tput cnorm 110 | select-network || exit 1 111 | connect-to-network || exit 1 112 | } 113 | 114 | main 115 | -------------------------------------------------------------------------------- /scripts/volume.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Adjust default device volume and send a notification with the current level 4 | # 5 | # Requirements: 6 | # - pactl (libpulse) 7 | # - notify-send (libnotify) 8 | # 9 | # Author: Jesse Mirabel 10 | # Created: September 07, 2025 11 | # License: MIT 12 | 13 | VALUE=1 14 | MIN=0 15 | MAX=100 16 | 17 | print-usage() { 18 | local script=${0##*/} 19 | cat <<- EOF 20 | USAGE: $script [OPTIONS] 21 | 22 | Adjust default device volume and send a notification with the current level 23 | 24 | OPTIONS: 25 | input Set device as '@DEFAULT_SOURCE@' 26 | output Set device as '@DEFAULT_SINK@' 27 | 28 | mute Toggle device mute 29 | 30 | raise Raise volume by 31 | lower Lower volume by 32 | Default value: $VALUE 33 | 34 | EXAMPLES: 35 | Toggle microphone mute: 36 | $ $script input mute 37 | 38 | Raise speaker volume: 39 | $ $script output raise 40 | 41 | Lower speaker volume by 5: 42 | $ $script output lower 5 43 | EOF 44 | exit 1 45 | } 46 | 47 | check-muted() { 48 | local muted 49 | muted=$(pactl "get-$dev_mute" "$dev" | awk '{print $2}') 50 | local state 51 | case $muted in 52 | 'yes') state='Muted' ;; 53 | 'no') state='Unmuted' ;; 54 | esac 55 | 56 | echo "$state" 57 | } 58 | 59 | get-volume() { 60 | pactl "get-$dev_vol" "$dev" | awk '{print $5}' | tr -d '%' 61 | } 62 | 63 | get-icon() { 64 | local icon 65 | local new_vol=${1:-$(get-volume)} 66 | 67 | if [[ $(check-muted) == 'Muted' ]]; then 68 | icon="$dev_icon-muted" 69 | else 70 | if ((new_vol < ((MAX * 33) / 100))); then 71 | icon="$dev_icon-low" 72 | elif ((new_vol < ((MAX * 66) / 100))); then 73 | icon="$dev_icon-medium" 74 | else 75 | icon="$dev_icon-high" 76 | fi 77 | fi 78 | 79 | echo "$icon" 80 | } 81 | 82 | toggle-mute() { 83 | pactl "set-$dev_mute" "$dev" toggle 84 | notify-send "$title: $(check-muted)" -i "$(get-icon)" -r 2425 85 | } 86 | 87 | set-volume() { 88 | local vol 89 | vol=$(get-volume) 90 | local new_vol 91 | 92 | case $action in 93 | 'raise') 94 | new_vol=$((vol + value)) 95 | ((new_vol > MAX)) && new_vol=$MAX 96 | ;; 97 | 'lower') 98 | new_vol=$((vol - value)) 99 | ((new_vol < MIN)) && new_vol=$MIN 100 | ;; 101 | esac 102 | 103 | pactl "set-$dev_vol" "$dev" "${new_vol}%" 104 | 105 | local icon 106 | icon=$(get-icon "$new_vol") 107 | 108 | notify-send "$title: ${new_vol}%" -h int:value:$new_vol -i "$icon" -r 2425 109 | } 110 | 111 | main() { 112 | device=$1 113 | action=$2 114 | value=${3:-$VALUE} 115 | 116 | ! ((value > 0)) && print-usage 117 | 118 | case $device in 119 | 'input') 120 | dev='@DEFAULT_SOURCE@' 121 | dev_mute='source-mute' 122 | dev_vol='source-volume' 123 | dev_icon='mic-volume' 124 | title='Microphone' 125 | ;; 126 | 'output') 127 | dev='@DEFAULT_SINK@' 128 | dev_mute='sink-mute' 129 | dev_vol='sink-volume' 130 | dev_icon='audio-volume' 131 | title='Volume' 132 | ;; 133 | *) print-usage ;; 134 | esac 135 | 136 | case $action in 137 | 'mute') toggle-mute ;; 138 | 'raise' | 'lower') set-volume ;; 139 | *) print-usage ;; 140 | esac 141 | } 142 | 143 | main "$@" 144 | -------------------------------------------------------------------------------- /scripts/bluetooth.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Scan, select, pair, and connect to Bluetooth devices 4 | # 5 | # Requirements: 6 | # - bluetoothctl (bluez-utils) 7 | # - fzf 8 | # - notify-send (libnotify) 9 | # 10 | # Author: Jesse Mirabel 11 | # Created: August 19, 2025 12 | # License: MIT 13 | 14 | fcconf=() 15 | # Get fzf color config 16 | # shellcheck disable=SC1090,SC2154 17 | . ~/.config/waybar/scripts/_fzf_colorizer.sh 2> /dev/null || true 18 | # If the file is missing, fzf will fall back to its default colors 19 | 20 | RED='\033[1;31m' 21 | RST='\033[0m' 22 | 23 | TIMEOUT=10 24 | 25 | ensure-on() { 26 | local status 27 | status=$(bluetoothctl show | awk '/PowerState/ {print $2}') 28 | 29 | case $status in 30 | 'off') bluetoothctl power on > /dev/null ;; 31 | 'off-blocked') 32 | rfkill unblock bluetooth 33 | 34 | local i new_status 35 | for ((i = 1; i <= TIMEOUT; i++)); do 36 | printf '\rUnblocking Bluetooth... (%d/%d)' $i $TIMEOUT 37 | 38 | new_status=$(bluetoothctl show | awk '/PowerState/ {print $2}') 39 | if [[ $new_status == 'on' ]]; then 40 | break 41 | fi 42 | sleep 1 43 | done 44 | 45 | # Bluetooth could be hard blocked 46 | if [[ $new_status != 'on' ]]; then 47 | notify-send 'Bluetooth' 'Failed to unblock' -i 'package-purge' 48 | return 1 49 | fi 50 | ;; 51 | *) return 0 ;; 52 | esac 53 | 54 | notify-send 'Bluetooth On' -i 'network-bluetooth-activated' -r 1925 55 | } 56 | 57 | get-device-list() { 58 | bluetoothctl --timeout $TIMEOUT scan on > /dev/null & 59 | 60 | local i num 61 | for ((i = 1; i <= TIMEOUT; i++)); do 62 | printf '\rScanning for devices... (%d/%d)' $i $TIMEOUT 63 | printf '\n%bPress [q] to stop%b\n\n' "$RED" "$RST" 64 | 65 | num=$(bluetoothctl devices | grep -c 'Device') 66 | printf '\rDevices: %s' "$num" 67 | printf '\033[3A' 68 | 69 | read -rs -n 1 -t 1 70 | if [[ $REPLY == [Qq] ]]; then 71 | break 72 | fi 73 | done 74 | printf '\n%bScanning stopped.%b\n\n' "$RED" "$RST" 75 | 76 | list=$(bluetoothctl devices | sed 's/^Device //') 77 | if [[ -z $list ]]; then 78 | notify-send 'Bluetooth' 'No devices found' -i 'package-broken' 79 | return 1 80 | fi 81 | } 82 | 83 | select-device() { 84 | local header 85 | header=$(printf '%-17s %s' 'Address' 'Name') 86 | local opts=( 87 | '--border=sharp' 88 | '--border-label= Bluetooth Devices ' 89 | '--ghost=Search' 90 | "--header=$header" 91 | '--height=~100%' 92 | '--highlight-line' 93 | '--info=inline-right' 94 | '--pointer=' 95 | '--reverse' 96 | "${fcconf[@]}" 97 | ) 98 | 99 | address=$(fzf "${opts[@]}" <<< "$list" | awk '{print $1}') 100 | if [[ -z $address ]]; then 101 | return 1 102 | fi 103 | 104 | local connected 105 | connected=$(bluetoothctl info "$address" | awk '/Connected/ {print $2}') 106 | if [[ $connected == 'yes' ]]; then 107 | notify-send 'Bluetooth' 'Already connected to this device' \ 108 | -i 'package-install' 109 | return 1 110 | fi 111 | } 112 | 113 | pair-and-connect() { 114 | local paired 115 | paired=$(bluetoothctl info "$address" | awk '/Paired/ {print $2}') 116 | if [[ $paired == 'no' ]]; then 117 | printf 'Pairing...' 118 | if ! timeout $TIMEOUT bluetoothctl pair "$address" > /dev/null; then 119 | notify-send 'Bluetooth' 'Failed to pair' -i 'package-purge' 120 | return 1 121 | fi 122 | fi 123 | 124 | printf '\nConnecting...' 125 | if ! timeout $TIMEOUT bluetoothctl connect "$address" > /dev/null; then 126 | notify-send 'Bluetooth' 'Failed to connect' -i 'package-purge' 127 | return 1 128 | fi 129 | notify-send 'Bluetooth' 'Successfully connected' -i 'package-install' 130 | } 131 | 132 | main() { 133 | tput civis 134 | ensure-on || exit 1 135 | get-device-list || exit 1 136 | tput cnorm 137 | select-device || exit 1 138 | pair-and-connect || exit 1 139 | } 140 | 141 | main 142 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ## 🤖 mechabar 4 | 5 | A mecha-themed, modular Waybar configuration. 6 | 7 | | ![Mechabar](assets/catppuccin-mocha.png) | 8 | | :--------------------------------------: | 9 | 10 |
11 | Themes 12 | 13 | Catppuccin: 14 | 15 | | Mocha (default) | 16 | | :----------------------------------------------: | 17 | | ![Catppuccin Mocha](assets/catppuccin-mocha.png) | 18 | 19 | | Macchiato | 20 | | :------------------------------------------------------: | 21 | | ![Catppuccin Macchiato](assets/catppuccin-macchiato.png) | 22 | 23 | | Frappe | 24 | | :------------------------------------------------: | 25 | | ![Catppuccin Frappe](assets/catppuccin-frappe.png) | 26 | 27 | | Latte | 28 | | :----------------------------------------------: | 29 | | ![Catppuccin Latte](assets/catppuccin-latte.png) | 30 | 31 | Feel free to open a pull request if you'd like to add themes! :^) 32 | 33 |
34 |
35 | 36 | # 37 | 38 | ### Prerequisites 39 | 40 | 1. **[Waybar](https://github.com/Alexays/Waybar)** 41 | 42 | > [!WARNING] 43 | > **Waybar v0.14.0** introduced an [issue](https://github.com/Alexays/Waybar/issues/4354) that breaks [wildcard includes](/config.jsonc#L3-L10). 44 | > [Clone the `fix/v0.14.0` branch](#clone-fix-branch) as a temporary workaround. 45 | 46 | 2. A **terminal emulator** (default: `kitty`) 47 | 48 | > [!IMPORTANT] 49 | > If you use a different terminal emulator (e.g., `ghostty`), 50 | > you need to replace all invocations of `kitty` with your terminal command: 51 | > 52 | > ```diff 53 | > - "on-click": "kitty -e ..." 54 | > + "on-click": "ghostty -e ..." 55 | > ``` 56 | 57 | # 58 | 59 | ### Installation 60 | 61 | 1. Back up your current config: 62 | 63 | ```bash 64 | mv ~/.config/waybar{,.bak} 65 | ``` 66 | 67 | 2. Clone the repository: 68 | 69 | ```bash 70 | git clone https://github.com/sejjy/mechabar.git ~/.config/waybar 71 | ``` 72 | 73 | For **Waybar v0.14.0**: 74 | 75 | ```bash 76 | git clone -b fix/v0.14.0 https://github.com/sejjy/mechabar.git ~/.config/waybar 77 | ``` 78 | 79 | 3. Run [`install.sh`](/install.sh): 80 | 81 | ```bash 82 | ~/.config/waybar/install.sh 83 | ``` 84 | 85 | This makes the [scripts](/scripts/) executable and installs the following dependencies: 86 | 87 |
88 | Packages (8) 89 | 90 | | Package | Command | Description | 91 | | ---------------------- | --------------- | ------------------------------------------------------------------------------ | 92 | | `bluez` | - | Daemons for the bluetooth protocol stack | 93 | | `bluez-utils` | `bluetoothctl` | Development and debugging utilities for the bluetooth protocol stack | 94 | | `brightnessctl` | `brightnessctl` | Lightweight brightness control tool | 95 | | `fzf` | `fzf` | Command-line fuzzy finder | 96 | | `networkmanager` | `nmcli` | Network connection manager and user applications | 97 | | `pacman-contrib` | `checkupdates` | Contributed scripts and tools for pacman systems | 98 | | `pipewire-pulse` | - | Low-latency audio/video router and processor - PulseAudio replacement | 99 | | `otf-commit-mono-nerd` | - | Patched font Commit Mono from nerd fonts library | 100 | 101 |
102 | 103 | # 104 | 105 | ### Customization 106 | 107 |
108 | Binds 109 | 110 | You can set keybinds to interact with modules via [scripts](/scripts/). Example: 111 | 112 | ```properties 113 | # ~/.config/hypr/hyprland.conf 114 | 115 | $mod = SUPER 116 | $term = kitty 117 | $scr = ~/.config/waybar/scripts 118 | 119 | bind = $mod, B, exec, $term -e $scr/bluetooth.sh 120 | bind = $mod, N, exec, $term -e $scr/network.sh 121 | bind = $mod, O, exec, $term -e $scr/power-menu.sh 122 | bind = $mod, U, exec, $term -e $scr/system-update.sh 123 | 124 | bindl = , XF86AudioMicMute, exec, $scr/volume.sh input mute 125 | bindl = , XF86AudioMute, exec, $scr/volume.sh output mute 126 | bindel = , XF86AudioLowerVolume, exec, $scr/volume.sh output lower 127 | bindel = , XF86AudioRaiseVolume, exec, $scr/volume.sh output raise 128 | bindel = , XF86MonBrightnessDown, exec, $scr/backlight.sh down 129 | bindel = , XF86MonBrightnessUp, exec, $scr/backlight.sh up 130 | ``` 131 | 132 | # 133 | 134 |
135 | 136 |
137 | Icons 138 | 139 | You can search for icons on [Nerd Fonts: Cheat Sheet ↗](https://www.nerdfonts.com/cheat-sheet). Example: 140 | 141 | ``` 142 | battery charging 143 | ``` 144 | 145 | For consistency, most modules use icons from Material Design, prefixed with `nf-md`: 146 | 147 | ``` 148 | nf-md battery charging 149 | ``` 150 | 151 | See [Nerd Fonts wiki: Glyph Sets](https://github.com/ryanoasis/nerd-fonts/wiki/Glyph-Sets-and-Code-Points#glyph-sets) for more info. 152 | 153 | # 154 | 155 |
156 | 157 |
158 | Theme 159 | 160 | Copy your preferred theme from the [themes](/themes/) directory into `current-theme.css`. Example: 161 | 162 | ```bash 163 | cd ~/.config/waybar 164 | cp themes/catppuccin-latte.css current-theme.css 165 | ``` 166 | 167 |
168 | 169 | # 170 | 171 | ### Documentation 172 | 173 | - [Waybar wiki](https://github.com/Alexays/Waybar/wiki) 174 | 175 | - Man pages: 176 | 177 | ```bash 178 | man waybar 179 | man waybar-styles 180 | man waybar-custom 181 | man waybar- 182 | man waybar-- 183 | ``` 184 | 185 | # 186 | 187 | ### Credits 188 | 189 | - Themes: [Catppuccin](https://github.com/catppuccin/waybar) 190 | - Original font: [Commit Mono](https://github.com/eigilnikolajsen/commit-mono) 191 | - Patched font: [CommitMono Nerd Font](https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/CommitMono) 192 | --------------------------------------------------------------------------------