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 dispatcher — thin presentation layer over
|
||||
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
||||
# hyprctl and friends. Icons are nf-md glyphs (Pango falls back to a
|
||||
# Nerd Font for them). `nomarchy-menu` with no argument shows the
|
||||
# module picker.
|
||||
# hyprctl and friends. Menu entries carry real icons from the theme's
|
||||
# icon set (Papirus) via rofi's per-row icon protocol — see row() below.
|
||||
# `nomarchy-menu` with no argument shows the module picker.
|
||||
|
||||
urlencode() {
|
||||
local s="$1" out="" ch i
|
||||
@@ -58,16 +58,22 @@ let
|
||||
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
|
||||
power)
|
||||
choice=$(printf '%s\n' \
|
||||
" Lock" \
|
||||
" Logout" \
|
||||
" Suspend" \
|
||||
" Hibernate" \
|
||||
" Reboot" \
|
||||
" Shutdown" \
|
||||
| rofi -dmenu -p power) || exit 0
|
||||
choice=$( {
|
||||
row "Lock" system-lock-screen
|
||||
row "Logout" system-log-out
|
||||
row "Suspend" system-suspend
|
||||
row "Hibernate" system-hibernate
|
||||
row "Reboot" system-reboot
|
||||
row "Shutdown" system-shutdown
|
||||
} | rofi -dmenu -show-icons -p Power) || exit 0
|
||||
case "$choice" in
|
||||
*Lock) loginctl lock-session ;;
|
||||
*Logout) hyprctl dispatch exit ;;
|
||||
@@ -134,12 +140,12 @@ let
|
||||
exec blueman-manager ;;
|
||||
|
||||
capture)
|
||||
choice=$(printf '%s\n' \
|
||||
" Region → clipboard" \
|
||||
" Region → file" \
|
||||
" Full screen → clipboard" \
|
||||
" Full screen → file" \
|
||||
| rofi -dmenu -p capture) || exit 0
|
||||
choice=$( {
|
||||
row "Region → clipboard" applets-screenshooter
|
||||
row "Region → file" applets-screenshooter
|
||||
row "Full screen → clipboard" camera-photo
|
||||
row "Full screen → file" camera-photo
|
||||
} | rofi -dmenu -show-icons -p Capture) || exit 0
|
||||
dir="$HOME/Pictures/Screenshots"
|
||||
file="$dir/$(date +%Y%m%d-%H%M%S).png"
|
||||
case "$choice" in
|
||||
@@ -183,16 +189,16 @@ let
|
||||
tools)
|
||||
# Tools submenu — utilities you invoke. Each leaf is also reachable
|
||||
# directly (SUPER+CTRL+<mnemonic>); this just keeps the root short.
|
||||
choice=$(printf '%s\n' \
|
||||
" Calculator" \
|
||||
" Clipboard" \
|
||||
" Emoji" \
|
||||
" Files" \
|
||||
" Web search" \
|
||||
" Capture" \
|
||||
" Ask Claude" \
|
||||
" Back" \
|
||||
| rofi -dmenu -p tools) || exit 0
|
||||
choice=$( {
|
||||
row "Calculator" accessories-calculator
|
||||
row "Clipboard" edit-paste
|
||||
row "Emoji" face-smile-big
|
||||
row "Files" system-file-manager
|
||||
row "Web search" system-search
|
||||
row "Capture" applets-screenshooter
|
||||
row "Ask Claude" internet-chat
|
||||
row "Back" go-previous
|
||||
} | rofi -dmenu -show-icons -p Tools) || exit 0
|
||||
case "$choice" in
|
||||
*Calc*) exec "$0" calc ;;
|
||||
*Clipboard*) exec "$0" clipboard ;;
|
||||
@@ -208,18 +214,17 @@ let
|
||||
# System submenu — connectivity and machine state. Snapshots and the
|
||||
# power-profile picker self-gate (BTRFS+snapper / laptop on ppd), so
|
||||
# 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*)
|
||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||
entries+=(" Power profile")
|
||||
fi
|
||||
entries+=(" Back")
|
||||
choice=$(printf '%s\n' "''${entries[@]}" | rofi -dmenu -p system) || exit 0
|
||||
choice=$( {
|
||||
row "Network" network-wireless
|
||||
row "Bluetooth" bluetooth
|
||||
row "Do Not Disturb" notification-disabled
|
||||
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
|
||||
*Network*) exec "$0" network ;;
|
||||
*Bluetooth*) exec "$0" bluetooth ;;
|
||||
@@ -233,14 +238,14 @@ let
|
||||
# Root picker — grouped into category submenus so the top level stays
|
||||
# short and scannable. Apps/Theme/Power/Keybindings are frequent enough
|
||||
# to keep at the top; everything else lives under Tools or System.
|
||||
choice=$(printf '%s\n' \
|
||||
" Apps" \
|
||||
" Theme" \
|
||||
" Tools" \
|
||||
" System" \
|
||||
" Power" \
|
||||
" Keybindings" \
|
||||
| rofi -dmenu -p menu) || exit 0
|
||||
choice=$( {
|
||||
row "Apps" applications-all
|
||||
row "Theme" preferences-desktop-theme
|
||||
row "Tools" applications-utilities
|
||||
row "System" preferences-system
|
||||
row "Power" system-shutdown
|
||||
row "Keybindings" preferences-desktop-keyboard
|
||||
} | rofi -dmenu -show-icons -p Menu) || exit 0
|
||||
case "$choice" in
|
||||
*Apps*) exec rofi -show drun ;;
|
||||
*Theme*) exec "$0" theme ;;
|
||||
@@ -283,6 +288,10 @@ in
|
||||
drun-display-format = "{name}";
|
||||
display-drun = "apps";
|
||||
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
|
||||
@@ -335,22 +344,34 @@ in
|
||||
columns = 1;
|
||||
dynamic = true;
|
||||
scrollbar = false;
|
||||
spacing = px 2;
|
||||
spacing = px 4; # a little air so the rounded zebra rows separate
|
||||
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" = {
|
||||
padding = mkLiteral "8px 12px";
|
||||
padding = mkLiteral "10px 14px";
|
||||
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";
|
||||
text-color = mkLiteral "@bg";
|
||||
};
|
||||
"element-icon" = {
|
||||
background-color = mkLiteral "transparent";
|
||||
size = mkLiteral "1em";
|
||||
size = px t.ui.iconSize; # real icons (Papirus), not 1em font glyphs
|
||||
};
|
||||
"element-text" = {
|
||||
background-color = mkLiteral "transparent";
|
||||
|
||||
@@ -38,6 +38,7 @@ let
|
||||
gapsOut = 12;
|
||||
borderSize = 2;
|
||||
rounding = 10;
|
||||
iconSize = 36; # rofi launcher + menu icon size (px) for the generated theme
|
||||
activeOpacity = 1.0;
|
||||
inactiveOpacity = 0.95;
|
||||
terminalOpacity = 0.96;
|
||||
|
||||
@@ -29,7 +29,8 @@ window {
|
||||
border-color: @yellow;
|
||||
border-radius: 15px;
|
||||
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;
|
||||
anchor: center;
|
||||
x-offset: 0;
|
||||
@@ -90,6 +91,12 @@ element {
|
||||
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 {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
|
||||
@@ -29,7 +29,8 @@ window {
|
||||
border-color: @yellow;
|
||||
border-radius: 15px;
|
||||
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;
|
||||
anchor: center;
|
||||
x-offset: 0;
|
||||
@@ -90,6 +91,12 @@ element {
|
||||
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 {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
|
||||
Reference in New Issue
Block a user