replace the old dotfiles with the sakura line rice
The bare $HOME repo is gone. This is now the rice: install.sh, rice-* scripts in bin/, configs in home/ linked into $HOME, theme templates, st and the particle wallpaper. Clone to ~/rice and run install.sh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BLLuuQfeDiqFHHSgd2VWrQ
This commit is contained in:
commit
4b203d06bd
104 changed files with 8077 additions and 0 deletions
217
home/.config/eww/eww.scss
Normal file
217
home/.config/eww/eww.scss
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// Sakura Line - eww design system.
|
||||
// The same tokens as polybar, rofi and dunst: the theme's alpha, 1px border,
|
||||
// 12px radius, rows with an 8px radius and a 17% accent tint on hover.
|
||||
// colors.scss is a link to ~/.local/state/rice/theme/eww-colors.scss.
|
||||
@import "colors";
|
||||
|
||||
$tint: rgba($accent, 0.17);
|
||||
|
||||
* {
|
||||
all: unset;
|
||||
font-family: $font, "Symbols Nerd Font";
|
||||
}
|
||||
|
||||
window, .closer { background-color: transparent; }
|
||||
|
||||
tooltip {
|
||||
background-color: rgba($bg, 0.95);
|
||||
border: $border-width solid $border;
|
||||
border-radius: $radius-small;
|
||||
padding: 6px 10px;
|
||||
color: $fg;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ panel
|
||||
.panel {
|
||||
background-color: rgba($bg, $alpha);
|
||||
border: $border-width solid $border;
|
||||
border-radius: $radius;
|
||||
padding: 4px 8px 10px 8px;
|
||||
color: $fg;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.head {
|
||||
padding: 10px 10px 12px 10px;
|
||||
margin-bottom: 6px;
|
||||
border-bottom: $border-width solid $border;
|
||||
}
|
||||
.title { font-weight: bold; font-size: 14px; }
|
||||
|
||||
.head-action {
|
||||
color: $dim;
|
||||
font-size: 15px;
|
||||
padding: 2px 7px;
|
||||
margin-left: 2px;
|
||||
border-radius: $radius-small;
|
||||
}
|
||||
.head-action:hover { color: $fg; background-color: $tint; }
|
||||
.head-action.active { color: $accent; }
|
||||
|
||||
.section {
|
||||
color: $dim;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 10px 10px 4px 10px;
|
||||
}
|
||||
|
||||
.sep {
|
||||
min-height: 1px;
|
||||
margin: 6px 4px;
|
||||
background-color: $border;
|
||||
}
|
||||
|
||||
.empty { color: $dim; padding: 8px 10px; }
|
||||
|
||||
// -------------------------------------------------------------------- rows
|
||||
.row {
|
||||
padding: 8px 10px;
|
||||
border-radius: $radius-small;
|
||||
}
|
||||
.row:hover { background-color: $tint; }
|
||||
.row.active .row-title, .row.active .glyph { color: $accent; }
|
||||
.row.dimmed .row-title, .row.dimmed .glyph { color: $dim; }
|
||||
|
||||
.glyph { font-size: 15px; min-width: 24px; margin-right: 10px; }
|
||||
.row-title { color: $fg; }
|
||||
.row-sub { color: $dim; font-size: 11px; margin-top: 1px; }
|
||||
.row-value { color: $dim; margin-left: 10px; }
|
||||
.chev { color: $dim; margin-left: 8px; font-size: 15px; }
|
||||
|
||||
.accent { color: $accent; }
|
||||
.urgent { color: $urgent; }
|
||||
.good { color: $green; }
|
||||
.warn { color: $yellow; }
|
||||
.dim { color: $dim; }
|
||||
|
||||
// ---------------------------------------------------------------- controls
|
||||
.slider-row:hover { background-color: transparent; }
|
||||
.slider-row .glyph { padding: 2px 0; border-radius: $radius-small; }
|
||||
.slider-row .glyph:hover { color: $accent; }
|
||||
.slider-value { min-width: 48px; }
|
||||
|
||||
scale trough {
|
||||
min-height: 6px;
|
||||
min-width: 140px;
|
||||
margin: 0 4px;
|
||||
border-radius: 3px;
|
||||
background-color: $selection;
|
||||
}
|
||||
scale highlight {
|
||||
border-radius: 3px;
|
||||
background-color: $accent;
|
||||
}
|
||||
scale slider {
|
||||
min-width: 12px;
|
||||
min-height: 12px;
|
||||
margin: -3px;
|
||||
border-radius: 6px;
|
||||
background-color: $fg;
|
||||
}
|
||||
|
||||
.switch {
|
||||
min-width: 30px;
|
||||
min-height: 16px;
|
||||
padding: 2px;
|
||||
border-radius: 10px;
|
||||
background-color: $selection;
|
||||
}
|
||||
.switch.on { background-color: rgba($accent, 0.55); }
|
||||
.knob {
|
||||
min-width: 12px;
|
||||
min-height: 12px;
|
||||
border-radius: 6px;
|
||||
background-color: $dim;
|
||||
}
|
||||
.switch.on .knob { background-color: $fg; }
|
||||
|
||||
.pill {
|
||||
padding: 4px 10px;
|
||||
margin: 0 3px;
|
||||
border-radius: $radius-small;
|
||||
color: $dim;
|
||||
}
|
||||
.pills { padding: 2px 6px 6px 6px; }
|
||||
.pill:hover { color: $fg; background-color: $tint; }
|
||||
.pill.active { color: $accent; background-color: $tint; }
|
||||
|
||||
.field {
|
||||
padding: 8px 10px;
|
||||
border-radius: $radius-small;
|
||||
background-color: rgba($surface, 0.8);
|
||||
color: $fg;
|
||||
caret-color: $accent;
|
||||
}
|
||||
|
||||
progressbar trough {
|
||||
min-height: 4px;
|
||||
border-radius: 2px;
|
||||
background-color: $selection;
|
||||
}
|
||||
progressbar progress {
|
||||
min-height: 4px;
|
||||
border-radius: 2px;
|
||||
background-color: $accent;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- calendar
|
||||
.cal-title { font-weight: bold; }
|
||||
.cal-grid { margin: 4px 4px 2px 4px; }
|
||||
.cal-dow, .cal-wk { color: $dim; font-size: 10px; font-weight: bold; min-height: 22px; }
|
||||
.cal-wk { min-width: 26px; }
|
||||
.cal-day {
|
||||
min-width: 34px;
|
||||
min-height: 30px;
|
||||
border-radius: $radius-small;
|
||||
color: $fg;
|
||||
}
|
||||
.cal-day:hover { background-color: $tint; }
|
||||
.cal-day.other { color: $muted; }
|
||||
.cal-day.weekend { color: $fg-alt; }
|
||||
.cal-day.selected { background-color: $tint; color: $accent; }
|
||||
.cal-day.today { background-color: $accent; color: $bg; font-weight: bold; }
|
||||
.cal-dot { color: $magenta; font-size: 8px; min-height: 8px; }
|
||||
.cal-day.today .cal-dot { color: $bg; }
|
||||
|
||||
.event-time { color: $accent; min-width: 52px; font-size: 12px; }
|
||||
.event-bar { min-width: 3px; border-radius: 2px; margin-right: 10px; background-color: $magenta; }
|
||||
.event-bar.reminder { background-color: $yellow; }
|
||||
|
||||
// ------------------------------------------------------------------- media
|
||||
.art {
|
||||
min-width: 72px;
|
||||
min-height: 72px;
|
||||
border-radius: $radius-small;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-color: $surface;
|
||||
}
|
||||
.media-title { font-weight: bold; }
|
||||
.media-artist { color: $dim; font-size: 12px; }
|
||||
.media-btn {
|
||||
font-size: 18px;
|
||||
padding: 4px 12px;
|
||||
border-radius: $radius-small;
|
||||
}
|
||||
.media-btn:hover { background-color: $tint; color: $accent; }
|
||||
.media-time { color: $dim; font-size: 10px; }
|
||||
|
||||
// ----------------------------------------------------------- notifications
|
||||
// The event box takes the hover tint; GTK ignores padding on event boxes,
|
||||
// so the box inside it carries the padding.
|
||||
.notif-hit { border-radius: $radius-small; }
|
||||
.notif-hit:hover { background-color: $tint; }
|
||||
.notif { padding: 8px 10px; }
|
||||
.notif.critical .notif-summary { color: $urgent; }
|
||||
.notif-app { color: $dim; font-size: 10px; font-weight: bold; }
|
||||
.notif-summary { font-weight: bold; }
|
||||
.notif-body { color: $fg-alt; font-size: 12px; }
|
||||
.notif-ago { color: $dim; font-size: 10px; }
|
||||
.notif-close {
|
||||
color: $dim;
|
||||
padding: 0 6px;
|
||||
border-radius: $radius-small;
|
||||
font-size: 13px;
|
||||
}
|
||||
.notif-close:hover { color: $urgent; background-color: rgba($urgent, 0.15); }
|
||||
91
home/.config/eww/eww.yuck
Normal file
91
home/.config/eww/eww.yuck
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
;; Sakura Line - eww popups.
|
||||
;; rice-panel opens one window at a time; every panel is built from the
|
||||
;; widgets below so they all look and behave like the rofi menus.
|
||||
|
||||
;; ------------------------------------------------------------------ state
|
||||
(defvar open_panel "") ; set by rice-panel; list polls only run while their panel is open
|
||||
(defvar cal_offset 0) ; months away from the current one
|
||||
(defvar cal_day "") ; selected day as YYYY-MM-DD, "" = today
|
||||
(defvar cal_input "") ; text typed into the calendar's add box
|
||||
|
||||
(deflisten notifs :initial "{}" "rice-notify watch")
|
||||
(deflisten audio :initial "{}" "rice-audio watch")
|
||||
(deflisten media :initial "{}" "rice-media watch")
|
||||
|
||||
(defpoll net :interval "4s" :initial "{}" :run-while {open_panel == "network" || open_panel == "hub"} "rice-net list")
|
||||
(defpoll bt :interval "4s" :initial "{}" :run-while {open_panel == "bluetooth" || open_panel == "hub"} "rice-bt list")
|
||||
(defpoll display :interval "10s" :initial "{}" :run-while {open_panel == "display" || open_panel == "hub"} "rice-display info")
|
||||
(defpoll power :interval "3s" :initial "{}" :run-while {open_panel == "power" || open_panel == "hub"} "rice-power info")
|
||||
;; rice-cal reads cal_offset / cal_day itself and pushes fresh data on every click.
|
||||
(defpoll month :interval "60s" :initial "{}" :run-while {open_panel == "calendar"} "rice-cal month")
|
||||
(defpoll agenda :interval "30s" :initial "{}" :run-while {open_panel == "calendar"} "rice-cal agenda")
|
||||
(defpoll idle :interval "3s" :initial "{}" :run-while {open_panel == "hub"} "rice-idle status")
|
||||
|
||||
;; ---------------------------------------------------------------- windows
|
||||
;; A transparent layer under the open panel: clicking anywhere else closes it.
|
||||
(defwindow closer
|
||||
:monitor 0
|
||||
:geometry (geometry :x "0" :y "0" :width "100%" :height "100%")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
(eventbox :class "closer" :onclick "rice-panel close" :onrightclick "rice-panel close"))
|
||||
|
||||
;; -------------------------------------------------------- shared widgets
|
||||
;; Header: title on the left, optional action buttons on the right.
|
||||
(defwidget head [title]
|
||||
(box :class "head" :space-evenly false
|
||||
(label :class "title" :text title :hexpand true :xalign 0)
|
||||
(children)))
|
||||
|
||||
(defwidget head-action [glyph onclick ?tip ?active]
|
||||
(button :class "head-action ${active == true ? 'active' : ''}" :onclick onclick :tooltip {tip ?: ""} glyph))
|
||||
|
||||
(defwidget section [text]
|
||||
(label :class "section" :xalign 0 :text text))
|
||||
|
||||
(defwidget sep []
|
||||
(box :class "sep"))
|
||||
|
||||
;; One list row: glyph, title and optional subtitle, value on the right.
|
||||
(defwidget row [glyph title ?sub ?value ?onclick ?active ?chev ?dim]
|
||||
(button :class "row ${active == true ? 'active' : ''} ${dim == true ? 'dimmed' : ''}" :onclick {onclick ?: ""}
|
||||
(box :space-evenly false
|
||||
(label :class "glyph" :text glyph)
|
||||
(box :orientation "v" :hexpand true :space-evenly false :valign "center"
|
||||
(label :class "row-title" :xalign 0 :limit-width 30 :text title)
|
||||
(label :class "row-sub" :xalign 0 :limit-width 38 :visible {(sub ?: "") != ""} :text {sub ?: ""}))
|
||||
(label :class "row-value" :visible {(value ?: "") != ""} :text {value ?: ""})
|
||||
(label :class "chev" :visible {chev == true} :text "›"))))
|
||||
|
||||
;; A row with a pill switch.
|
||||
(defwidget switch-row [glyph title on onclick ?sub]
|
||||
(button :class "row" :onclick onclick
|
||||
(box :space-evenly false
|
||||
(label :class "glyph ${on == true ? 'accent' : ''}" :text glyph)
|
||||
(box :orientation "v" :hexpand true :space-evenly false :valign "center"
|
||||
(label :class "row-title" :xalign 0 :text title)
|
||||
(label :class "row-sub" :xalign 0 :visible {(sub ?: "") != ""} :text {sub ?: ""}))
|
||||
(box :class "switch ${on == true ? 'on' : ''}" :valign "center" :space-evenly false
|
||||
(box :class "knob" :hexpand true :halign {on == true ? "end" : "start"})))))
|
||||
|
||||
;; A slider row: clicking the glyph runs onglyph (mute), dragging runs onchange.
|
||||
(defwidget slider-row [glyph value onchange ?onglyph ?muted]
|
||||
(box :class "row slider-row" :space-evenly false
|
||||
(button :class "glyph ${muted == true ? 'urgent' : ''}" :onclick {onglyph ?: ""} glyph)
|
||||
(scale :class "slider" :hexpand true :min 0 :max 101 :value {value ?: 0} :onchange onchange)
|
||||
(label :class "row-value slider-value" :xalign 1 :text {muted == true ? "muted" : "${value ?: 0}%"})))
|
||||
|
||||
;; An empty-state line inside a list.
|
||||
(defwidget empty [text]
|
||||
(label :class "empty" :xalign 0 :text text))
|
||||
|
||||
;; ----------------------------------------------------------------- panels
|
||||
(include "panels/hub.yuck")
|
||||
(include "panels/audio.yuck")
|
||||
(include "panels/network.yuck")
|
||||
(include "panels/bluetooth.yuck")
|
||||
(include "panels/display.yuck")
|
||||
(include "panels/power.yuck")
|
||||
(include "panels/media.yuck")
|
||||
(include "panels/calendar.yuck")
|
||||
(include "panels/notifications.yuck")
|
||||
3
home/.config/eww/panel-keys
Normal file
3
home/.config/eww/panel-keys
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# sxhkd config that rice-panel runs only while a panel is open.
|
||||
Escape
|
||||
rice-panel close
|
||||
45
home/.config/eww/panels/audio.yuck
Normal file
45
home/.config/eww/panels/audio.yuck
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
;; Audio: output and mic levels, device pickers, per-app mixer.
|
||||
(defwindow audio
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Audio"
|
||||
(head-action :glyph "" :tip "Advanced mixer" :onclick "rice-panel close; setsid -f pavucontrol"))
|
||||
|
||||
(slider-row :glyph {audio?.sink?.muted == true ? "" : ""}
|
||||
:value {audio?.sink?.vol ?: 0}
|
||||
:muted {audio?.sink?.muted ?: false}
|
||||
:onglyph "rice-volume mute"
|
||||
:onchange "rice-volume set {}")
|
||||
(slider-row :glyph {audio?.source?.muted == true ? "" : ""}
|
||||
:value {audio?.source?.vol ?: 0}
|
||||
:muted {audio?.source?.muted ?: false}
|
||||
:onglyph "rice-audio mic-mute"
|
||||
:onchange "rice-audio mic {}")
|
||||
|
||||
;; eww appends a loop's items after their siblings, so every loop gets its own box.
|
||||
(section :text "Output")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for s in {audio?.sinks ?: []}
|
||||
(row :glyph "" :title {s.desc} :active {s.default} :onclick "rice-audio sink ${s.index}")))
|
||||
|
||||
(section :text "Input")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for s in {audio?.sources ?: []}
|
||||
(row :glyph "" :title {s.desc} :active {s.default} :onclick "rice-audio source ${s.index}")))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {arraylength(audio?.apps ?: []) > 0}
|
||||
(section :text "Apps")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for a in {audio?.apps ?: []}
|
||||
(box :class "row slider-row" :space-evenly false
|
||||
(button :class "glyph ${a.muted ? 'urgent' : ''}" :tooltip {a.name}
|
||||
:onclick "rice-audio app-mute ${a.id}"
|
||||
{a.muted ? "" : ""})
|
||||
(label :class "row-title" :xalign 0 :width 90 :limit-width 11 :text {a.name})
|
||||
(scale :class "slider" :hexpand true :min 0 :max 101 :value {a.vol}
|
||||
:onchange "rice-audio app-volume ${a.id} {}")
|
||||
(label :class "row-value slider-value" :xalign 1 :text "${a.vol}%")))))))
|
||||
32
home/.config/eww/panels/bluetooth.yuck
Normal file
32
home/.config/eww/panels/bluetooth.yuck
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
;; Bluetooth: power, paired devices with battery, nearby devices to pair.
|
||||
(defwindow bluetooth
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Bluetooth"
|
||||
(head-action :glyph "" :tip "Look for new devices" :active {bt?.discovering == true}
|
||||
:onclick "rice-bt scan"))
|
||||
|
||||
(switch-row :glyph "" :title "Bluetooth" :on {bt?.powered == true}
|
||||
:onclick "rice-bt power toggle"
|
||||
:sub {bt?.powered != true ? "off" : (bt?.connected > 0 ? "${bt.connected} connected" : "on")})
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {bt?.powered == true}
|
||||
(section :text "My devices")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for d in {bt?.paired ?: []}
|
||||
(row :glyph {d.glyph} :title {d.name} :sub {d.sub} :value {d.battery}
|
||||
:active {d.connected} :onclick "rice-bt toggle ${d.mac}")))
|
||||
(box :visible {arraylength(bt?.paired ?: []) == 0}
|
||||
(empty :text "No paired devices"))
|
||||
|
||||
(section :text {bt?.discovering == true ? "Nearby · scanning" : "Nearby"})
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for d in {bt?.nearby ?: []}
|
||||
(row :glyph {d.glyph} :title {d.name} :sub {d.sub} :dim true
|
||||
:onclick "rice-bt toggle ${d.mac}")))
|
||||
(box :visible {arraylength(bt?.nearby ?: []) == 0}
|
||||
(empty :text {bt?.discovering == true ? "Looking…" : "Press to look for devices"})))))
|
||||
47
home/.config/eww/panels/calendar.yuck
Normal file
47
home/.config/eww/panels/calendar.yuck
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
;; Calendar: month grid with ISO weeks, the selected day's events and reminders.
|
||||
(defwindow calendar
|
||||
:monitor 0
|
||||
:geometry (geometry :x "0" :y "47px" :width "360px" :anchor "top center")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title {month?.title ?: "Calendar"}
|
||||
(head-action :glyph "" :tip "Previous month" :onclick "rice-cal shift -1")
|
||||
(head-action :glyph "" :tip "Today" :onclick "rice-cal today")
|
||||
(head-action :glyph "" :tip "Next month" :onclick "rice-cal shift 1"))
|
||||
|
||||
(box :class "cal-grid" :orientation "v" :space-evenly false
|
||||
(box :space-evenly false
|
||||
(label :class "cal-wk" :text "Wk")
|
||||
(for d in {month?.dow ?: []}
|
||||
(label :class "cal-dow" :hexpand true :text d)))
|
||||
(for w in {month?.weeks ?: []}
|
||||
(box :space-evenly false
|
||||
(label :class "cal-wk" :text {w.wk})
|
||||
(for d in {w.days}
|
||||
(button :hexpand true :onclick "rice-cal select ${d.date}"
|
||||
:class "cal-day ${d.other ? 'other' : ''} ${d.weekend ? 'weekend' : ''} ${d.selected ? 'selected' : ''} ${d.today ? 'today' : ''}"
|
||||
(box :orientation "v" :space-evenly false :valign "center"
|
||||
(label :text {d.d})
|
||||
(label :class "cal-dot" :text {d.events > 0 ? "●" : " "})))))))
|
||||
|
||||
(sep)
|
||||
(box :space-evenly false
|
||||
(label :class "section" :hexpand true :xalign 0 :text {agenda?.heading ?: "Today"})
|
||||
(head-action :glyph "" :tip "Add event" :onclick "rice-cal add")
|
||||
(head-action :glyph "" :tip "Add reminder" :onclick "rice-panel close; rice-reminder new"))
|
||||
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for ev in {agenda?.items ?: []}
|
||||
(box :class "row" :space-evenly false
|
||||
(box :class "event-bar ${ev.kind == 'reminder' ? 'reminder' : ''}")
|
||||
(label :class "event-time" :xalign 0 :text {ev.time})
|
||||
(box :orientation "v" :hexpand true :space-evenly false :valign "center"
|
||||
(label :class "row-title" :xalign 0 :limit-width 28 :text {ev.title})
|
||||
(label :class "row-sub" :xalign 0 :limit-width 36 :visible {ev.sub != ""} :text {ev.sub}))
|
||||
(button :class "notif-close" :valign "center" :visible {ev.kind == "reminder"}
|
||||
:tooltip "Cancel reminder" :onclick "rice-reminder cancel ${ev.id}" ""))))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {arraylength(agenda?.items ?: []) == 0}
|
||||
(empty :text {(agenda?.status ?: "") != "" ? agenda.status : "Nothing planned"}))))
|
||||
30
home/.config/eww/panels/display.yuck
Normal file
30
home/.config/eww/panels/display.yuck
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
;; Display: brightness over DDC, resolution, refresh rate, bar, style shortcuts.
|
||||
(defwindow display
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Display"
|
||||
(head-action :glyph "" :tip "Wallpaper" :onclick "rice-panel close; rice-menu wallpaper")
|
||||
(head-action :glyph "" :tip "Theme" :onclick "rice-panel close; rice-menu theme"))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {display?.ddc == true}
|
||||
(slider-row :glyph "" :value {display?.brightness ?: 0}
|
||||
:onchange "rice-display brightness {}"))
|
||||
(box :orientation "v" :space-evenly false :visible {display?.ddc != true}
|
||||
(row :glyph "" :title "Brightness" :sub {display?.ddcHint ?: ""} :dim true))
|
||||
|
||||
(section :text {display?.output ?: "Output"})
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for m in {display?.modes ?: []}
|
||||
(row :glyph "" :title {m.mode} :active {m.current} :onclick "rice-display mode ${m.id}")))
|
||||
|
||||
(section :text "Refresh rate")
|
||||
(box :class "pills" :space-evenly true
|
||||
(for r in {display?.rates ?: []}
|
||||
(button :class "pill ${r.current ? 'active' : ''}" :onclick "rice-display rate ${r.id}" {r.label})))
|
||||
|
||||
(sep)
|
||||
(switch-row :glyph "" :title "Bar" :on {display?.bar == true} :onclick "rice-bar toggle")))
|
||||
50
home/.config/eww/panels/hub.yuck
Normal file
50
home/.config/eww/panels/hub.yuck
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
;; Control centre (super + x): levels, a line per subsystem, quick switches, now playing.
|
||||
(defwindow hub
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "400px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Control Centre"
|
||||
(head-action :glyph "" :tip "Rice menu" :onclick "rice-panel close; rice-menu main")
|
||||
(head-action :glyph "" :tip "Power menu" :onclick "rice-panel close; rice-menu power"))
|
||||
|
||||
(slider-row :glyph {audio?.sink?.muted == true ? "" : ""}
|
||||
:value {audio?.sink?.vol ?: 0} :muted {audio?.sink?.muted ?: false}
|
||||
:onglyph "rice-volume mute" :onchange "rice-volume set {}")
|
||||
(slider-row :glyph {audio?.source?.muted == true ? "" : ""}
|
||||
:value {audio?.source?.vol ?: 0} :muted {audio?.source?.muted ?: false}
|
||||
:onglyph "rice-audio mic-mute" :onchange "rice-audio mic {}")
|
||||
(box :orientation "v" :space-evenly false :visible {display?.ddc == true}
|
||||
(slider-row :glyph "" :value {display?.brightness ?: 0} :onchange "rice-display brightness {}"))
|
||||
|
||||
(sep)
|
||||
(row :glyph {net?.active?.type == "ethernet" ? "" : (net?.active?.type == "wifi" ? "" : "")}
|
||||
:title "Network" :value {net?.active?.name ?: "offline"} :chev true :onclick "rice-panel network")
|
||||
(row :glyph "" :title "Bluetooth" :chev true :onclick "rice-panel bluetooth"
|
||||
:value {bt?.powered != true ? "off" : (bt?.connected > 0 ? "${bt.connected} connected" : "on")})
|
||||
(row :glyph "" :title "Sound" :value {audio?.sink?.name ?: ""} :chev true :onclick "rice-panel audio")
|
||||
(row :glyph "" :title "Display" :chev true :onclick "rice-panel display"
|
||||
:value "${display?.mode ?: ''} · ${round(display?.rate ?: 0, 0)} Hz")
|
||||
(row :glyph "" :title "System" :chev true :onclick "rice-panel power"
|
||||
:value "CPU ${power?.cpu?.load ?: 0}% · Memory ${power?.memory?.percent ?: 0}%")
|
||||
(row :glyph "" :title "Calendar" :value {formattime(EWW_TIME, "%a %-d %b")} :chev true :onclick "rice-panel calendar")
|
||||
|
||||
(sep)
|
||||
(switch-row :glyph "" :title "Do not disturb" :on {notifs?.dnd == true} :onclick "rice-notify dnd toggle"
|
||||
:sub {(notifs?.count ?: 0) > 0 ? "${notifs.count} in the notification centre" : ""})
|
||||
(switch-row :glyph "" :title "Stay awake" :on {idle?.awake == true} :onclick "rice-idle toggle"
|
||||
:sub {idle?.awake == true ? "screensaver and lock paused" : ""})
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {media?.status == "Playing" || media?.status == "Paused"}
|
||||
(sep)
|
||||
(box :class "row" :space-evenly false
|
||||
(label :class "glyph accent" :text "")
|
||||
(eventbox :hexpand true :onclick "rice-panel media"
|
||||
(box :orientation "v" :space-evenly false :valign "center"
|
||||
(label :class "row-title" :xalign 0 :limit-width 22 :text {media?.title ?: ""})
|
||||
(label :class "row-sub" :xalign 0 :limit-width 26 :text {media?.artist ?: ""})))
|
||||
(button :class "media-btn" :onclick "playerctl previous" "")
|
||||
(button :class "media-btn accent" :onclick "playerctl play-pause" {media?.status == "Playing" ? "" : ""})
|
||||
(button :class "media-btn" :onclick "playerctl next" "")))))
|
||||
39
home/.config/eww/panels/media.yuck
Normal file
39
home/.config/eww/panels/media.yuck
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
;; Media: what is playing, a seek bar, and transport controls.
|
||||
(defpoll media_pos :interval "1s" :initial "{}" :run-while {open_panel == "media"} "rice-media position")
|
||||
|
||||
(defwindow media
|
||||
:monitor 0
|
||||
:geometry (geometry :x "0" :y "47px" :width "380px" :anchor "top center")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Media"
|
||||
(label :class "dim" :text {media?.player ?: ""}))
|
||||
|
||||
(box :orientation "v" :space-evenly false
|
||||
:visible {media?.status != "Playing" && media?.status != "Paused"}
|
||||
(empty :text "Nothing is playing"))
|
||||
|
||||
(box :orientation "v" :space-evenly false
|
||||
:visible {media?.status == "Playing" || media?.status == "Paused"}
|
||||
(box :class "row" :space-evenly false
|
||||
(box :class "art" :visible {(media?.art ?: "") != ""}
|
||||
:style "background-image: url('${media?.art ?: ''}');")
|
||||
(box :orientation "v" :space-evenly false :valign "center" :hexpand true
|
||||
(label :class "media-title" :xalign 0 :limit-width 26 :text {media?.title ?: ""})
|
||||
(label :class "media-artist" :xalign 0 :limit-width 32 :text {media?.artist ?: ""})
|
||||
(label :class "media-artist" :xalign 0 :limit-width 32 :visible {(media?.album ?: "") != ""}
|
||||
:text {media?.album ?: ""})))
|
||||
|
||||
(box :class "row slider-row" :space-evenly false :visible {(media?.length ?: 0) > 0}
|
||||
(label :class "media-time" :width 36 :xalign 0 :text {media_pos?.text ?: "0:00"})
|
||||
(scale :class "slider" :hexpand true :min 0 :max {media?.length ?: 1}
|
||||
:value {media_pos?.pos ?: 0} :onchange "rice-media seek {}")
|
||||
(label :class "media-time" :width 36 :xalign 1 :text {media?.lengthText ?: ""}))
|
||||
|
||||
(box :class "row" :space-evenly true
|
||||
(button :class "media-btn" :tooltip "Previous" :onclick "playerctl previous" "")
|
||||
(button :class "media-btn accent" :tooltip "Play / pause" :onclick "playerctl play-pause"
|
||||
{media?.status == "Playing" ? "" : ""})
|
||||
(button :class "media-btn" :tooltip "Next" :onclick "playerctl next" "")))))
|
||||
37
home/.config/eww/panels/network.yuck
Normal file
37
home/.config/eww/panels/network.yuck
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
;; Network: Wi-Fi radio, the active connection, nearby networks and VPNs.
|
||||
(defwindow network
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Network"
|
||||
(head-action :glyph "" :tip "Rescan" :onclick "rice-net rescan")
|
||||
(head-action :glyph "" :tip "Share Wi-Fi as a QR code" :onclick "rice-panel close; rice-net share")
|
||||
(head-action :glyph "" :tip "Connection editor" :onclick "rice-panel close; setsid -f nm-connection-editor"))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {net?.active?.type == "ethernet"}
|
||||
(row :glyph "" :title "Ethernet" :sub {net?.active?.name ?: ""} :active true))
|
||||
|
||||
;; Machines without a Wi-Fi adapter (like a wired desktop) skip this part.
|
||||
(box :orientation "v" :space-evenly false :visible {net?.hasWifi == true}
|
||||
(switch-row :glyph "" :title "Wi-Fi" :on {net?.radio == true}
|
||||
:onclick "rice-net radio toggle"
|
||||
:sub {net?.active?.type == "wifi" ? net.active.name : (net?.radio == true ? "not connected" : "off")}))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {net?.hasWifi == true && net?.radio == true}
|
||||
(section :text "Networks")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for w in {net?.wifi ?: []}
|
||||
(row :glyph {w.glyph} :title {w.ssid} :sub {w.sub} :active {w.active}
|
||||
:onclick {w.active ? "rice-net disconnect" : "rice-net connect ${w.id}"})))
|
||||
(box :visible {arraylength(net?.wifi ?: []) == 0}
|
||||
(empty :text "No networks found yet")))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {arraylength(net?.vpn ?: []) > 0}
|
||||
(section :text "VPN")
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for v in {net?.vpn ?: []}
|
||||
(row :glyph {v.active ? "" : ""} :title {v.name} :sub {v.active ? "connected" : ""}
|
||||
:active {v.active} :onclick "rice-net vpn ${v.id}"))))))
|
||||
37
home/.config/eww/panels/notifications.yuck
Normal file
37
home/.config/eww/panels/notifications.yuck
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
;; Notification centre: recent notifications, dismiss one or all, do-not-disturb.
|
||||
(defwindow notifications
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Notifications"
|
||||
(head-action :glyph {notifs?.dnd == true ? "" : ""} :active {notifs?.dnd == true}
|
||||
:tip "Do not disturb" :onclick "rice-notify dnd toggle")
|
||||
(head-action :glyph "" :tip "Clear all" :onclick "rice-notify clear"))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {notifs?.dnd == true && (notifs?.waiting ?: 0) > 0}
|
||||
(row :glyph "" :title "Held back" :sub "They appear when do-not-disturb is off"
|
||||
:value "${notifs?.waiting ?: 0}" :dim true))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {(notifs?.count ?: 0) == 0}
|
||||
(empty :text "You're all caught up"))
|
||||
|
||||
(box :orientation "v" :space-evenly false
|
||||
(for n in {notifs?.items ?: []}
|
||||
(eventbox :class "notif-hit"
|
||||
:onclick "rice-panel close; rice-notify open ${n.id}"
|
||||
(box :class "notif ${n.urgency == 'CRITICAL' ? 'critical' : ''}" :space-evenly false
|
||||
(box :orientation "v" :hexpand true :space-evenly false
|
||||
(box :space-evenly false
|
||||
(label :class "notif-app" :xalign 0 :hexpand true :limit-width 30 :text {n.app})
|
||||
(label :class "notif-ago" :text {n.ago}))
|
||||
(label :class "notif-summary" :xalign 0 :limit-width 36 :text {n.summary})
|
||||
(label :class "notif-body" :xalign 0 :wrap true :limit-width 140
|
||||
:visible {n.body != ""} :text {n.body}))
|
||||
(button :class "notif-close" :valign "start" :tooltip "Dismiss"
|
||||
:onclick "rice-notify remove ${n.id}" "")))))
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {(notifs?.count ?: 0) > 8}
|
||||
(row :glyph "" :title "${notifs?.count - 8} older" :sub "Clear all to start fresh" :dim true))))
|
||||
31
home/.config/eww/panels/power.yuck
Normal file
31
home/.config/eww/panels/power.yuck
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
;; Power: what the machine is doing, the power profile, and session actions.
|
||||
(defwindow power
|
||||
:monitor 0
|
||||
:geometry (geometry :x "-10px" :y "47px" :width "380px" :anchor "top right")
|
||||
:stacking "fg"
|
||||
:wm-ignore true
|
||||
:resizable false
|
||||
(box :class "panel" :orientation "v" :space-evenly false
|
||||
(head :title "Power"
|
||||
(head-action :glyph "" :tip "Activity monitor" :onclick "rice-panel close; setsid -f st -c rice-float -e btop"))
|
||||
|
||||
(row :glyph "" :title "CPU"
|
||||
:value "${power?.cpu?.load ?: 0}%${power?.cpu?.temp != 'null' && power?.cpu?.temp != '' ? ' ' + power.cpu.temp + '°' : ''}")
|
||||
(row :glyph "" :title "GPU" :sub {power?.gpu?.vram ?: ""}
|
||||
:value "${power?.gpu?.load ?: 0}%${power?.gpu?.temp != 'null' && power?.gpu?.temp != '' ? ' ' + power.gpu.temp + '°' : ''}")
|
||||
(row :glyph "" :title "Memory" :value "${power?.memory?.used ?: '-'} / ${power?.memory?.total ?: '-'}")
|
||||
(row :glyph "" :title "Uptime" :value {power?.uptime ?: ""})
|
||||
|
||||
(box :orientation "v" :space-evenly false :visible {arraylength(power?.profiles ?: []) > 0}
|
||||
(section :text "Power profile")
|
||||
(box :class "row" :space-evenly true
|
||||
(for p in {power?.profiles ?: []}
|
||||
(button :class "pill ${p.active ? 'active' : ''}" :onclick "rice-power profile ${p.name}" {p.label}))))
|
||||
|
||||
(sep)
|
||||
(box :space-evenly true :class "row"
|
||||
(button :class "media-btn" :tooltip "Lock" :onclick "rice-power lock" "")
|
||||
(button :class "media-btn" :tooltip "Suspend" :onclick "rice-power suspend" "")
|
||||
(button :class "media-btn" :tooltip "Log out" :onclick "rice-power logout" "")
|
||||
(button :class "media-btn" :tooltip "Reboot" :onclick "rice-power reboot" "")
|
||||
(button :class "media-btn urgent" :tooltip "Shut down" :onclick "rice-power shutdown" ""))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue