feat(rofi): real icons, zebra rows, content-fit menus across all themes
Reworked the menu look, palette-driven so it lands on every theme:
- Real Papirus icons in place of Nerd Font glyphs: a row() helper emits
rofi's per-row icon protocol, and the five static menus (root, Tools,
System, Power, Capture) map each entry to a freedesktop icon name
(verified present in Papirus). Entry text is now clean ("Apps"), the
case-matching is unchanged.
- Larger icons via a new t.ui.iconSize knob (36px, generated theme); the
summer whole-swaps keep their 40px identity.
- Rounded, roomy rows with subtle zebra striping: alternate rows lift to
@surface (a faint bg0 wash on the summer cream/slate windows), the
selected row to @accent — using rofi's normal/alternate/selected row
parities.
- Content-fit windows: fixed-num-lines=false so a 6-entry menu stops
reserving 8 rows of empty space (the launcher still fills + scrolls).
Dropped the fixed height:50% from the summer .rasi so they size to
content too — which also unhid their clipped Power/Keybindings rows.
- Title-cased the menu prompts.
Verified by building the HM config and rendering the generated theme plus
both summer whole-swaps headlessly (sway + grim): icons resolve, zebra
shows, every menu hugs its rows.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
163
config.rasi
Normal file
163
config.rasi
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/**
|
||||||
|
* Rofi Everforest Theme
|
||||||
|
* Based on wofi everforest config
|
||||||
|
*/
|
||||||
|
|
||||||
|
* {
|
||||||
|
/* Everforest color definitions */
|
||||||
|
bg-dim: #232a2e;
|
||||||
|
bg0: #2d353b;
|
||||||
|
bg1: #343f44;
|
||||||
|
bg2: #3d484d;
|
||||||
|
bg3: #475258;
|
||||||
|
bg4: #4f585e;
|
||||||
|
bg5: #56635f;
|
||||||
|
bg-visual: #543a48;
|
||||||
|
bg-red: #514045;
|
||||||
|
bg-green: #425047;
|
||||||
|
bg-blue: #3a515d;
|
||||||
|
bg-yellow: #4d4c43;
|
||||||
|
fg: #d3c6aa;
|
||||||
|
red: #e67e80;
|
||||||
|
orange: #e69875;
|
||||||
|
yellow: #dbbc7f;
|
||||||
|
green: #a7c080;
|
||||||
|
aqua: #83c092;
|
||||||
|
blue: #7fbbb3;
|
||||||
|
purple: #d699b6;
|
||||||
|
grey0: #7a8478;
|
||||||
|
grey1: #859289;
|
||||||
|
grey2: #9da9a0;
|
||||||
|
|
||||||
|
/* Font settings */
|
||||||
|
font: "Iosevka Nerd Font 17";
|
||||||
|
|
||||||
|
/* General styling */
|
||||||
|
background-color: transparent;
|
||||||
|
text-color: @fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration {
|
||||||
|
/* Basic settings */
|
||||||
|
drun-display-format: "{name}";
|
||||||
|
case-sensitive: false;
|
||||||
|
location: 0;
|
||||||
|
disable-history: false;
|
||||||
|
hide-scrollbar: true;
|
||||||
|
display-drun: "Search";
|
||||||
|
|
||||||
|
/* Image settings */
|
||||||
|
drun-icon-theme: "Papirus-Dark";
|
||||||
|
show-icons: true;
|
||||||
|
icon-size: 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
/* Window styling based on wofi config */
|
||||||
|
transparency: "real";
|
||||||
|
background-color: @fg;
|
||||||
|
text-color: @bg0;
|
||||||
|
border-bottom: 5px;
|
||||||
|
border-color: #7d6a40;
|
||||||
|
border-radius: 15px;
|
||||||
|
width: 40%;
|
||||||
|
height: 50%;
|
||||||
|
location: center;
|
||||||
|
anchor: center;
|
||||||
|
x-offset: 0;
|
||||||
|
y-offset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mainbox {
|
||||||
|
background-color: transparent;
|
||||||
|
children: [ inputbar, listview ];
|
||||||
|
spacing: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputbar {
|
||||||
|
children: [ prompt, entry ];
|
||||||
|
background-color: @green;
|
||||||
|
text-color: @bg0;
|
||||||
|
expand: false;
|
||||||
|
border-bottom: 5px;
|
||||||
|
border-color: #556a35;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
spacing: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt {
|
||||||
|
enabled: true;
|
||||||
|
background-color: inherit;
|
||||||
|
text-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry {
|
||||||
|
background-color: inherit;
|
||||||
|
text-color: inherit;
|
||||||
|
cursor: text;
|
||||||
|
placeholder: "Type to search...";
|
||||||
|
placeholder-color: @bg0;
|
||||||
|
}
|
||||||
|
|
||||||
|
listview {
|
||||||
|
background-color: transparent;
|
||||||
|
columns: 1;
|
||||||
|
lines: 8;
|
||||||
|
spacing: 0px;
|
||||||
|
cycle: true;
|
||||||
|
dynamic: true;
|
||||||
|
layout: vertical;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
element {
|
||||||
|
background-color: transparent;
|
||||||
|
text-color: @bg0;
|
||||||
|
orientation: horizontal;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
spacing: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
element-icon {
|
||||||
|
background-color: transparent;
|
||||||
|
text-color: inherit;
|
||||||
|
size: 40px;
|
||||||
|
cursor: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
element-text {
|
||||||
|
background-color: transparent;
|
||||||
|
text-color: inherit;
|
||||||
|
highlight: bold;
|
||||||
|
cursor: inherit;
|
||||||
|
vertical-align: 0.5;
|
||||||
|
horizontal-align: 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
element selected {
|
||||||
|
background-color: @bg0;
|
||||||
|
text-color: @fg;
|
||||||
|
border-bottom: 5px;
|
||||||
|
border-color: #161a1d;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
element-text selected {
|
||||||
|
text-color: @fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
element-icon selected {
|
||||||
|
text-color: @fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollbar {
|
||||||
|
width: 0px;
|
||||||
|
background-color: transparent;
|
||||||
|
handle-width: 0px;
|
||||||
|
handle-color: transparent;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
@@ -41,9 +41,9 @@ let
|
|||||||
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
||||||
# Nomarchy menu dispatcher — thin presentation layer over
|
# Nomarchy menu dispatcher — thin presentation layer over
|
||||||
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
||||||
# hyprctl and friends. Icons are nf-md glyphs (Pango falls back to a
|
# hyprctl and friends. Menu entries carry real icons from the theme's
|
||||||
# Nerd Font for them). `nomarchy-menu` with no argument shows the
|
# icon set (Papirus) via rofi's per-row icon protocol — see row() below.
|
||||||
# module picker.
|
# `nomarchy-menu` with no argument shows the module picker.
|
||||||
|
|
||||||
urlencode() {
|
urlencode() {
|
||||||
local s="$1" out="" ch i
|
local s="$1" out="" ch i
|
||||||
@@ -58,16 +58,22 @@ let
|
|||||||
printf '%s' "$out"
|
printf '%s' "$out"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Emit one dmenu row with a themed icon: `row "Label" icon-name`. The NUL
|
||||||
|
# + 0x1f field separator is rofi's per-row icon protocol; printed straight
|
||||||
|
# to the pipe because bash can't store NUL in a variable. Rendered when
|
||||||
|
# rofi has show-icons (on globally; passed explicitly on the icon menus).
|
||||||
|
row() { printf '%s\0icon\x1f%s\n' "$1" "$2"; }
|
||||||
|
|
||||||
case "''${1:-}" in
|
case "''${1:-}" in
|
||||||
power)
|
power)
|
||||||
choice=$(printf '%s\n' \
|
choice=$( {
|
||||||
" Lock" \
|
row "Lock" system-lock-screen
|
||||||
" Logout" \
|
row "Logout" system-log-out
|
||||||
" Suspend" \
|
row "Suspend" system-suspend
|
||||||
" Hibernate" \
|
row "Hibernate" system-hibernate
|
||||||
" Reboot" \
|
row "Reboot" system-reboot
|
||||||
" Shutdown" \
|
row "Shutdown" system-shutdown
|
||||||
| rofi -dmenu -p power) || exit 0
|
} | rofi -dmenu -show-icons -p Power) || exit 0
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
*Lock) loginctl lock-session ;;
|
*Lock) loginctl lock-session ;;
|
||||||
*Logout) hyprctl dispatch exit ;;
|
*Logout) hyprctl dispatch exit ;;
|
||||||
@@ -134,12 +140,12 @@ let
|
|||||||
exec blueman-manager ;;
|
exec blueman-manager ;;
|
||||||
|
|
||||||
capture)
|
capture)
|
||||||
choice=$(printf '%s\n' \
|
choice=$( {
|
||||||
" Region → clipboard" \
|
row "Region → clipboard" applets-screenshooter
|
||||||
" Region → file" \
|
row "Region → file" applets-screenshooter
|
||||||
" Full screen → clipboard" \
|
row "Full screen → clipboard" camera-photo
|
||||||
" Full screen → file" \
|
row "Full screen → file" camera-photo
|
||||||
| rofi -dmenu -p capture) || exit 0
|
} | rofi -dmenu -show-icons -p Capture) || exit 0
|
||||||
dir="$HOME/Pictures/Screenshots"
|
dir="$HOME/Pictures/Screenshots"
|
||||||
file="$dir/$(date +%Y%m%d-%H%M%S).png"
|
file="$dir/$(date +%Y%m%d-%H%M%S).png"
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
@@ -183,16 +189,16 @@ let
|
|||||||
tools)
|
tools)
|
||||||
# Tools submenu — utilities you invoke. Each leaf is also reachable
|
# Tools submenu — utilities you invoke. Each leaf is also reachable
|
||||||
# directly (SUPER+CTRL+<mnemonic>); this just keeps the root short.
|
# directly (SUPER+CTRL+<mnemonic>); this just keeps the root short.
|
||||||
choice=$(printf '%s\n' \
|
choice=$( {
|
||||||
" Calculator" \
|
row "Calculator" accessories-calculator
|
||||||
" Clipboard" \
|
row "Clipboard" edit-paste
|
||||||
" Emoji" \
|
row "Emoji" face-smile-big
|
||||||
" Files" \
|
row "Files" system-file-manager
|
||||||
" Web search" \
|
row "Web search" system-search
|
||||||
" Capture" \
|
row "Capture" applets-screenshooter
|
||||||
" Ask Claude" \
|
row "Ask Claude" internet-chat
|
||||||
" Back" \
|
row "Back" go-previous
|
||||||
| rofi -dmenu -p tools) || exit 0
|
} | rofi -dmenu -show-icons -p Tools) || exit 0
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
*Calc*) exec "$0" calc ;;
|
*Calc*) exec "$0" calc ;;
|
||||||
*Clipboard*) exec "$0" clipboard ;;
|
*Clipboard*) exec "$0" clipboard ;;
|
||||||
@@ -208,18 +214,17 @@ let
|
|||||||
# System submenu — connectivity and machine state. Snapshots and the
|
# System submenu — connectivity and machine state. Snapshots and the
|
||||||
# power-profile picker self-gate (BTRFS+snapper / laptop on ppd), so
|
# power-profile picker self-gate (BTRFS+snapper / laptop on ppd), so
|
||||||
# the submenu shrinks to match the hardware, like the Waybar modules.
|
# the submenu shrinks to match the hardware, like the Waybar modules.
|
||||||
entries=(
|
|
||||||
" Network"
|
|
||||||
" Bluetooth"
|
|
||||||
" Do Not Disturb"
|
|
||||||
)
|
|
||||||
command -v btrfs-assistant >/dev/null 2>&1 && entries+=(" Snapshots")
|
|
||||||
bats=(/sys/class/power_supply/BAT*)
|
bats=(/sys/class/power_supply/BAT*)
|
||||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
choice=$( {
|
||||||
entries+=(" Power profile")
|
row "Network" network-wireless
|
||||||
fi
|
row "Bluetooth" bluetooth
|
||||||
entries+=(" Back")
|
row "Do Not Disturb" notification-disabled
|
||||||
choice=$(printf '%s\n' "''${entries[@]}" | rofi -dmenu -p system) || exit 0
|
command -v btrfs-assistant >/dev/null 2>&1 && row "Snapshots" timeshift
|
||||||
|
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||||
|
row "Power profile" preferences-system-power
|
||||||
|
fi
|
||||||
|
row "Back" go-previous
|
||||||
|
} | rofi -dmenu -show-icons -p System) || exit 0
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
*Network*) exec "$0" network ;;
|
*Network*) exec "$0" network ;;
|
||||||
*Bluetooth*) exec "$0" bluetooth ;;
|
*Bluetooth*) exec "$0" bluetooth ;;
|
||||||
@@ -233,14 +238,14 @@ let
|
|||||||
# Root picker — grouped into category submenus so the top level stays
|
# Root picker — grouped into category submenus so the top level stays
|
||||||
# short and scannable. Apps/Theme/Power/Keybindings are frequent enough
|
# short and scannable. Apps/Theme/Power/Keybindings are frequent enough
|
||||||
# to keep at the top; everything else lives under Tools or System.
|
# to keep at the top; everything else lives under Tools or System.
|
||||||
choice=$(printf '%s\n' \
|
choice=$( {
|
||||||
" Apps" \
|
row "Apps" applications-all
|
||||||
" Theme" \
|
row "Theme" preferences-desktop-theme
|
||||||
" Tools" \
|
row "Tools" applications-utilities
|
||||||
" System" \
|
row "System" preferences-system
|
||||||
" Power" \
|
row "Power" system-shutdown
|
||||||
" Keybindings" \
|
row "Keybindings" preferences-desktop-keyboard
|
||||||
| rofi -dmenu -p menu) || exit 0
|
} | rofi -dmenu -show-icons -p Menu) || exit 0
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
*Apps*) exec rofi -show drun ;;
|
*Apps*) exec rofi -show drun ;;
|
||||||
*Theme*) exec "$0" theme ;;
|
*Theme*) exec "$0" theme ;;
|
||||||
@@ -283,6 +288,10 @@ in
|
|||||||
drun-display-format = "{name}";
|
drun-display-format = "{name}";
|
||||||
display-drun = "apps";
|
display-drun = "apps";
|
||||||
display-run = "run";
|
display-run = "run";
|
||||||
|
# Size the window to the actual number of rows instead of always
|
||||||
|
# reserving `lines` (8) — so a 6-entry menu doesn't leave empty space,
|
||||||
|
# while the app launcher still fills + scrolls past `lines`.
|
||||||
|
fixed-num-lines = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Whole-swap themes bring their own rofi.rasi; otherwise the theme
|
# Whole-swap themes bring their own rofi.rasi; otherwise the theme
|
||||||
@@ -335,22 +344,34 @@ in
|
|||||||
columns = 1;
|
columns = 1;
|
||||||
dynamic = true;
|
dynamic = true;
|
||||||
scrollbar = false;
|
scrollbar = false;
|
||||||
spacing = px 2;
|
spacing = px 4; # a little air so the rounded zebra rows separate
|
||||||
padding = mkLiteral "8px 0px 0px 0px";
|
padding = mkLiteral "8px 0px 0px 0px";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Rounded, roomy rows with subtle zebra striping: alternate rows
|
||||||
|
# lift to @surface, the selected row to @accent. normal/alternate/
|
||||||
|
# selected are rofi's row parities (the `.normal` suffix is the
|
||||||
|
# match-state, untouched by our menus).
|
||||||
"element" = {
|
"element" = {
|
||||||
padding = mkLiteral "8px 12px";
|
padding = mkLiteral "10px 14px";
|
||||||
border-radius = px t.ui.rounding;
|
border-radius = px t.ui.rounding;
|
||||||
spacing = px 8;
|
spacing = px 12; # gap between the (larger) icon and the label
|
||||||
};
|
};
|
||||||
"element selected" = {
|
"element normal.normal" = {
|
||||||
|
background-color = mkLiteral "@bg";
|
||||||
|
text-color = mkLiteral "@fg";
|
||||||
|
};
|
||||||
|
"element alternate.normal" = {
|
||||||
|
background-color = mkLiteral "@surface";
|
||||||
|
text-color = mkLiteral "@fg";
|
||||||
|
};
|
||||||
|
"element selected.normal" = {
|
||||||
background-color = mkLiteral "@accent";
|
background-color = mkLiteral "@accent";
|
||||||
text-color = mkLiteral "@bg";
|
text-color = mkLiteral "@bg";
|
||||||
};
|
};
|
||||||
"element-icon" = {
|
"element-icon" = {
|
||||||
background-color = mkLiteral "transparent";
|
background-color = mkLiteral "transparent";
|
||||||
size = mkLiteral "1em";
|
size = px t.ui.iconSize; # real icons (Papirus), not 1em font glyphs
|
||||||
};
|
};
|
||||||
"element-text" = {
|
"element-text" = {
|
||||||
background-color = mkLiteral "transparent";
|
background-color = mkLiteral "transparent";
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ let
|
|||||||
gapsOut = 12;
|
gapsOut = 12;
|
||||||
borderSize = 2;
|
borderSize = 2;
|
||||||
rounding = 10;
|
rounding = 10;
|
||||||
|
iconSize = 36; # rofi launcher + menu icon size (px) for the generated theme
|
||||||
activeOpacity = 1.0;
|
activeOpacity = 1.0;
|
||||||
inactiveOpacity = 0.95;
|
inactiveOpacity = 0.95;
|
||||||
terminalOpacity = 0.96;
|
terminalOpacity = 0.96;
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ window {
|
|||||||
border-color: @yellow;
|
border-color: @yellow;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
height: 50%;
|
/* No fixed height — size to content (fixed-num-lines:false) so every
|
||||||
|
* entry shows without scrolling and there's no empty space below. */
|
||||||
location: center;
|
location: center;
|
||||||
anchor: center;
|
anchor: center;
|
||||||
x-offset: 0;
|
x-offset: 0;
|
||||||
@@ -90,6 +91,12 @@ element {
|
|||||||
spacing: 15px;
|
spacing: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Zebra striping: every other row lifts with a faint light wash over the
|
||||||
|
* dark window (bg0 at ~12% alpha). The selected row below still wins. */
|
||||||
|
element alternate.normal {
|
||||||
|
background-color: #fdf6e31f;
|
||||||
|
}
|
||||||
|
|
||||||
element-icon {
|
element-icon {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-color: inherit;
|
text-color: inherit;
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ window {
|
|||||||
border-color: @yellow;
|
border-color: @yellow;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
height: 50%;
|
/* No fixed height — size to content (fixed-num-lines:false) so every
|
||||||
|
* entry shows without scrolling and there's no empty space below. */
|
||||||
location: center;
|
location: center;
|
||||||
anchor: center;
|
anchor: center;
|
||||||
x-offset: 0;
|
x-offset: 0;
|
||||||
@@ -90,6 +91,12 @@ element {
|
|||||||
spacing: 15px;
|
spacing: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Zebra striping: every other row lifts with a faint dark wash over the
|
||||||
|
* cream window (bg0 at ~12% alpha). The selected row below still wins. */
|
||||||
|
element alternate.normal {
|
||||||
|
background-color: #2d353b1f;
|
||||||
|
}
|
||||||
|
|
||||||
element-icon {
|
element-icon {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-color: inherit;
|
text-color: inherit;
|
||||||
|
|||||||
Reference in New Issue
Block a user