Fix clock layout shift with tabular digits and fixed width

This commit is contained in:
Joshua Yuen 2026-09-12 16:48:54 -04:00
parent 38dad86683
commit 334d50db1f
Signed by: josh
GPG Key ID: 530DA0331EFE99F5
2 changed files with 36 additions and 1 deletions

View File

@ -77,6 +77,7 @@ $module-bg: transparentize($base02, 0.4);
.clock { .clock {
font-weight: bold; font-weight: bold;
font-feature-settings: "tnum";
} }
.clock icon { .clock icon {

View File

@ -1,4 +1,6 @@
import GLib from "gi://GLib" import GLib from "gi://GLib"
import Pango from "gi://Pango"
import Gtk from "gi://Gtk?version=3.0"
import { Variable, bind } from "astal" import { Variable, bind } from "astal"
const time = Variable("").poll(1000, () => { const time = Variable("").poll(1000, () => {
@ -7,11 +9,43 @@ const time = Variable("").poll(1000, () => {
return `${now.format("%a, %d %b")}, ${clock}` return `${now.format("%a, %d %b")}, ${clock}`
}) })
// widest possible tick: days 1-7 always cover every weekday, sampled across
// all months with a double-digit hour in both meridiems; measured once at
// realize with the label's own font (tnum forced on) so the fixed
// widthRequest stops the bar from shifting every minute
function widestTick(self: Gtk.Label): number {
const layout = self.create_pango_layout("")
const attrs = new Pango.AttrList()
attrs.insert(Pango.attr_font_features_new("tnum"))
layout.set_attributes(attrs)
let widest = 0
for (let month = 1; month <= 12; month++) {
for (let day = 1; day <= 7; day++) {
for (const hour of [10, 22]) {
const d = GLib.DateTime.new_local(2026, month, day, hour, 0, 0)
const tick =
`${d.format("%a, %d %b")}, ${d.format("%I:%M %p")!.replace(/^0/, "")}`
layout.set_text(tick, -1)
const [w] = layout.get_pixel_size()
widest = Math.max(widest, w)
}
}
}
return Math.ceil(widest) + 2
}
export default function Clock() { export default function Clock() {
return ( return (
<box spacing={6}> <box spacing={6}>
<icon icon="clock-hands-symbolic" /> <icon icon="clock-hands-symbolic" />
<label className="clock" label={bind(time)} /> <label
className="clock"
label={bind(time)}
onRealize={(self) => {
self.width_request = widestTick(self as Gtk.Label)
}}
/>
</box> </box>
) )
} }