Move bar indicators into AGS, add calendar navigation and tooltips

Claude-Session: https://claude.ai/code/session_014ADhvRXuiTvrXSbConxUey
This commit is contained in:
2026-08-19 14:27:34 -04:00
parent 85652bd0b3
commit e9616a67c9
6 changed files with 159 additions and 71 deletions
+19 -27
View File
@@ -587,32 +587,9 @@
color: @foreground;
}
.agent-model-bar {
.agent-model-row {
min-height: 22px;
}
.agent-model-bar trough {
min-height: 22px;
border-radius: 0;
background-color: alpha(@foreground, 0.08);
}
.agent-model-bar block {
min-height: 22px;
min-width: 0;
border-radius: 0;
}
.agent-model-bar block.filled {
background-color: alpha(@foreground, 0.18);
}
.agent-model-bar block.empty {
background-color: transparent;
}
.agent-model-text {
padding: 0 8px;
padding: 3px 8px;
}
.agent-model-label {
@@ -713,11 +690,25 @@
}
.cc-calendar-month {
font-size: 13px;
font-size: 15px;
font-weight: bold;
color: @accent;
}
.cc-calendar-nav {
color: @foreground;
font-size: 13px;
min-width: 24px;
padding: 2px 4px;
background-color: transparent;
border: none;
}
.cc-calendar-nav:hover {
color: @accent;
background-color: alpha(@foreground, 0.1);
}
.cc-calendar-time {
font-size: 13px;
color: @foreground;
@@ -725,6 +716,7 @@
.cc-calendar-grid {
font-family: "JetBrainsMono Nerd Font", monospace;
font-size: 13px;
font-size: 17px;
color: @foreground;
padding: 4px 2px;
}
+7 -11
View File
@@ -236,18 +236,14 @@ function DayRow({ day }: { day: DayUsage }) {
}
function ModelRow({ model }: { model: ModelUsage }) {
const fillPercent = Math.round(model.fraction * 100)
const fill = `linear-gradient(to right, alpha(@foreground, 0.18) ${fillPercent}%, alpha(@foreground, 0.06) ${fillPercent}%)`
return (
<overlay
tooltipText={model.detail}
overlays={[
<box class="agent-model-text" spacing={8}>
<label class="agent-model-label" label={model.label} xalign={0} halign={Gtk.Align.START} hexpand />
<label class="agent-model-value" label={model.tokens} xalign={1} halign={Gtk.Align.END} />
</box>,
]}
>
<levelbar class="agent-model-bar" value={model.fraction} />
</overlay>
<box class="agent-model-row" spacing={8} tooltipText={model.detail} css={`background-image: ${fill};`}>
<label class="agent-model-label" label={model.label} xalign={0} halign={Gtk.Align.START} hexpand />
<label class="agent-model-value" label={model.tokens} xalign={1} halign={Gtk.Align.END} />
</box>
)
}
+118 -17
View File
@@ -1,5 +1,5 @@
import app from "ags/gtk3/app"
import { Astal, Gtk } from "ags/gtk3"
import { Astal, Gdk, Gtk } from "ags/gtk3"
import { createState } from "ags"
import { createPoll, interval } from "ags/time"
import { sh, shell } from "../lib/utils"
@@ -52,6 +52,21 @@ const [nightLight, setNightLight] = pollBool(
2000,
)
const [stayAwake, setStayAwake] = pollBool(
"omarchy-toggle-idle status 2>/dev/null | grep -q '\"enabled\":true' && echo on || echo off",
2000,
)
const [dictating] = pollBool(
"omarchy-voxtype-status 2>/dev/null | grep -q recording && echo on || echo off",
2000,
)
const [recording] = pollBool(
"pgrep -f '^gpu-screen-recorder' >/dev/null && echo on || echo off",
2000,
)
const clock = createPoll("", 1000, shell("date '+%H:%M'"), (stdout) => stdout.trim())
const today = createPoll("", 10000, shell("date '+%A, %B %-d'"), (stdout) => stdout.trim())
@@ -109,16 +124,19 @@ function Tile({
icon,
label,
active,
tooltip,
onClicked,
}: {
icon: string
label: string
active?: any
tooltip?: any
onClicked: () => void
}) {
return (
<button
class={active ? active.as((on: boolean) => (on ? "qs-tile active" : "qs-tile")) : "qs-tile"}
tooltipText={tooltip ?? label}
onClicked={onClicked}
hexpand
>
@@ -172,9 +190,37 @@ function Toggles() {
sh("omarchy-toggle-nightlight")
}}
/>
<Tile icon={""} label="Record" onClicked={() => { closePanel(); sh("omarchy-capture-screenrecording") }} />
<Tile
icon={""}
label="Record"
active={recording}
tooltip={recording.as((on: boolean) => (on ? "Stop screen recording" : "Start a screen recording"))}
onClicked={() => {
closePanel()
sh(recording.get()
? "omarchy-capture-screenrecording --stop-recording"
: "omarchy-menu toggle trigger.capture.screenrecord")
}}
/>
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile
icon={"󰅶"}
label="Stay Awake"
active={stayAwake}
tooltip={stayAwake.as((on: boolean) => (on ? "Allow idle lock and screensaver" : "Keep the screen awake"))}
onClicked={() => {
setStayAwake(!stayAwake.get())
sh("omarchy-toggle-idle toggle")
}}
/>
<Tile
icon={"󰍬"}
label="Dictate"
active={dictating}
tooltip={dictating.as((on: boolean) => (on ? "Stop dictation" : "Start voxtype dictation"))}
onClicked={() => sh("voxtype record toggle")}
/>
<Tile icon={""} label="Pick Color" onClicked={() => { closePanel(); sh("hyprpicker -a") }} />
<Tile
icon={""}
@@ -204,6 +250,7 @@ function VolumeSlider() {
</button>
<slider
class="qs-slider"
tooltipText={volume.as((level: number) => `Volume ${Math.round(level)}%`)}
hexpand
min={0}
max={100}
@@ -227,6 +274,7 @@ function BrightnessSlider() {
<label class="qs-slider-icon" label={""} />
<slider
class="qs-slider"
tooltipText={brightness.as((level: number) => `Brightness ${Math.round(level)}%`)}
hexpand
min={1}
max={100}
@@ -292,13 +340,13 @@ function MediaPlayer() {
}}
/>
<box class="cc-media-controls" spacing={14} halign={Gtk.Align.CENTER}>
<button onClicked={() => sh("playerctl previous")}>
<button tooltipText="Previous track" onClicked={() => sh("playerctl previous")}>
<label label={""} />
</button>
<button onClicked={() => sh("playerctl play-pause")}>
<button tooltipText="Play / pause" onClicked={() => sh("playerctl play-pause")}>
<label label={media.as((m) => (m.status === "Playing" ? "" : ""))} />
</button>
<button onClicked={() => sh("playerctl next")}>
<button tooltipText="Next track" onClicked={() => sh("playerctl next")}>
<label label={""} />
</button>
</box>
@@ -307,22 +355,75 @@ function MediaPlayer() {
)
}
const monthName = createPoll("", 60000, shell("date '+%B %Y'"), (stdout) => stdout.trim())
const monthGrid = createPoll(
"",
60000,
shell("cal | sed '1d'"),
(stdout) => stdout.replace(/\s+$/, ""),
)
const [monthOffset, setMonthOffset] = createState(0)
const [monthName, setMonthName] = createState("")
const [monthGrid, setMonthGrid] = createState("")
const loadMonth = (offset: number) => {
const firstOfMonth = `$(date +%Y-%m-01) ${offset} months`
const command =
`date -d "${firstOfMonth}" '+%B %Y'; ` +
`cal $(date -d "${firstOfMonth}" '+%m %Y') | sed '1d'`
sh(command).then((stdout) => {
const lines = String(stdout).replace(/\s+$/, "").split("\n")
setMonthName(lines[0]?.trim() ?? "")
setMonthGrid(lines.slice(1).join("\n"))
})
}
const shiftMonth = (delta: number) => {
const next = monthOffset.get() + delta
setMonthOffset(next)
loadMonth(next)
}
const resetMonth = () => {
setMonthOffset(0)
loadMonth(0)
}
loadMonth(0)
interval(3600000, () => { if (monthOffset.get() === 0) loadMonth(0) })
function CalendarSection() {
return (
<box class="cc-calendar" vertical spacing={6}>
<box class="cc-calendar-head" spacing={8}>
<label class="cc-calendar-month" label={monthName} xalign={0} hexpand halign={Gtk.Align.START} />
<eventbox
onScroll={(_self: any, event: any) => {
const direction = event?.direction
const deltaY = Number(event?.delta_y ?? 0)
if (direction === Gdk.ScrollDirection.UP || deltaY < 0) shiftMonth(-1)
else if (direction === Gdk.ScrollDirection.DOWN || deltaY > 0) shiftMonth(1)
}}
>
<box class="cc-calendar" vertical spacing={6}>
<box class="cc-calendar-head" spacing={8}>
<label
class="cc-calendar-month"
label={monthName}
xalign={0}
hexpand
halign={Gtk.Align.START}
tooltipText="Scroll to change month"
/>
<button class="cc-calendar-nav" tooltipText="Previous month" onClicked={() => shiftMonth(-1)}>
<label label={""} />
</button>
<button
class="cc-calendar-nav"
tooltipText="Back to this month"
visible={monthOffset.as((offset) => offset !== 0)}
onClicked={resetMonth}
>
<label label={""} />
</button>
<button class="cc-calendar-nav" tooltipText="Next month" onClicked={() => shiftMonth(1)}>
<label label={""} />
</button>
</box>
<label class="cc-calendar-grid" label={monthGrid} halign={Gtk.Align.CENTER} />
</box>
<label class="cc-calendar-grid" label={monthGrid} halign={Gtk.Align.CENTER} />
</box>
</eventbox>
)
}
+6 -1
View File
@@ -75,7 +75,12 @@ function Metric({
detail: any
}) {
return (
<box class="sys-metric" vertical spacing={4}>
<box
class="sys-metric"
vertical
spacing={4}
tooltipText={detail.as((value: string) => `${name}: ${value}`)}
>
<box spacing={8}>
<label class="sys-metric-icon" label={icon} />
<label class="sys-metric-name" label={name} xalign={0} halign={Gtk.Align.START} hexpand />
+9 -6
View File
@@ -14,10 +14,10 @@ Ported from the old `waybar/config.jsonc`, section for section:
| `hyprland/workspaces` | `blob.workspaces` (cloned plugin) |
| `clock` | `blob.clock` (custom module) |
| `custom/update` | `omarchy.system-update` |
| `custom/voxtype` | `omarchy.indicators` -> `Dictation` |
| `custom/screenrecording-indicator` | `omarchy.indicators` -> `ScreenRecording` |
| `custom/idle-indicator` | `omarchy.indicators` -> `StayAwake` |
| `custom/notification-silencing-indicator` | `omarchy.indicators` -> `Dnd` |
| `custom/voxtype` | AGS quick settings -> Dictate tile |
| `custom/screenrecording-indicator` | AGS quick settings -> Record tile |
| `custom/idle-indicator` | AGS quick settings -> Stay Awake tile |
| `custom/notification-silencing-indicator` | AGS quick settings -> Silence tile |
| `group/tray-expander` | `omarchy.tray` |
| `bluetooth` | `omarchy.bluetooth` |
| `network` | `omarchy.network` |
@@ -28,8 +28,11 @@ Ported from the old `waybar/config.jsonc`, section for section:
| (new in Omarchy 4) | `omarchy.agents` - AI agent usage |
| (new in Omarchy 4) | `omarchy.monitor` - brightness and display controls |
Drop the `items` list from `omarchy.indicators` to show all six indicators
(adds `NightLight` and `Reminder`).
The bar carries no `omarchy.indicators` widget: those four toggles live in the
AGS quick settings panel instead, so the bar keeps only the clock and the
update indicator in its center. Add `{ "id": "omarchy.indicators" }` back to
`center` to restore them (omit `items` for all six, which adds `NightLight`
and `Reminder`).
## Custom modules
-9
View File
@@ -29,15 +29,6 @@
},
{
"id": "omarchy.system-update"
},
{
"id": "omarchy.indicators",
"items": [
"Dictation",
"ScreenRecording",
"StayAwake",
"Dnd"
]
}
],
"right": [