A bar with a calendar popup
A clock in the middle of the bar that opens a month calendar when you
click it. Escape, or a click anywhere else, closes it. It is the
clock of the guide's bar, with one when added to light it while
the calendar shows; the guide's
level 3 builds
it step by step.
The files
Put both files in your config directory, ~/.config/strand.
bar.strand
// bar.strand: a bar on every monitor with the clock in the middle
bar Top {
edge: top; height: 36
bg: $surface; font: $font.ui; color: $fg
split { pad: 0, $space.3
center { Clock }
}
}
clock.strand
component Clock {
state open = false // one per monitor
text clock.format("%a %d %H:%M") { // wakes once a minute
when cal.open { color: $accent } // lit while the calendar shows
on click { open = !open }
popup { id: cal; open: <-> open; Calendar } // anchored here; Esc or click-away closes
}
}
component Calendar {
state month = clock.today.month_start()
col { pad: $space.3; gap: $space.2; bg: $surface; radius: $radius.lg; shadow: $elevation.lg
row { align: center
button "‹" { on click { month = month.add(months: -1) } }
text month.format("%B %Y") { grow: 1; align: center }
button "›" { on click { month = month.add(months: 1) } }
}
grid { columns: 7; gap: $space.1
for d in calendar.days(month) {
text d.date.format("%e") { width: 28; height: 28; align: center
when !d.in_month { color: $fg.faint }
when d.date == clock.today { bg: $accent; color: $on_accent; radius: full }
}
}
}
}
}
Save them while strand run is running and the bar appears. Nothing
restarts. Here the clock is clicked, then › moves to the next month, and a
second click on the clock closes it:
How it works
- The popup's state lives on
Clock.state open = falseis declared in the component, so each monitor's bar has its ownopen: opening the calendar on one monitor leaves the others closed. open: <-> openis a two-way binding. The popup shows whileopenis true. When Escape or a click away closes it, the popup writesfalseback, so the next click on the clock opens it again.- A
popupis anchored to the element it is written in, here the clock's text. On a bar it opens away from the bar's edge: below the clock on a top bar. cal.openis true while the popup namedcalis open. Thewhenon the text uses it to colour the clock while its calendar shows.clock.format("%a %d %H:%M")shows minutes, so it wakes the shell once a minute.calendar.days(month)gives the days of the weeks that covermonth, padded with days of the months around it;d.in_monthtells them apart.month.add(months: -1)moves a month back.
Variations
- A popup that touches the bar. A popup keeps a 6 px gap from the
element it is anchored to unless you set its
margin;margin: 0closes the gap. - More in the popup. A popup holds any tree. Put a
colaroundCalendarand add to it, such astext clock.format("%A")for the day's name. - A clock on a bar of its own design. The clock is a component, so
Clockgoes anywhere a node does: in thestartorendof the split, or in a panel.
Every element and prop used here is in the
element reference, and
the clock and calendar services are in the
service reference.