Calendar Widget¶
The Monthly widget renders a full monthly calendar in the terminal with
per-day event styling, optional surrounding days, weekday headers, and a
month/year title.
The widget is backed by ratatui's built-in widget-calendar feature and uses
the time crate for date handling.
Imports¶
CalendarDate¶
Wraps time::Date. Represents a specific calendar day.
# From explicit year/month/day
d = CalendarDate.from_ymd(2024, 3, 15) # March 15, 2024
# Today (UTC)
today = CalendarDate.today()
# Properties
print(today.year) # int
print(today.month) # int (1-12)
print(today.day) # int
from_ymd raises ValueError for invalid dates (e.g. Feb 30).
CalendarEventStore¶
A mapping from CalendarDate to Style that the Monthly widget uses
to style individual days.
store = CalendarEventStore()
# Mark a specific date
store.add(CalendarDate.from_ymd(2024, 12, 25), Style().fg(Color.red()).bold())
# Mark today
store.add_today(Style().fg(Color.green()).bold())
# Create a store with today pre-highlighted
store = CalendarEventStore.today_highlighted(Style().fg(Color.green()).bold())
Monthly¶
The calendar widget itself.
store = CalendarEventStore.today_highlighted(Style().fg(Color.green()).bold())
cal = (
Monthly(CalendarDate.today(), store)
.block(Block().bordered().title(" My Calendar "))
.show_month_header(Style().bold().fg(Color.cyan()))
.show_weekdays_header(Style().italic().fg(Color.white()))
.show_surrounding(Style().dim())
.default_style(Style().fg(Color.white()))
)
# Render like any other widget
frame.render_widget(cal, area)
Constructor¶
display_date — any date in the month to display.
events — the event store providing per-day styles.
Builder methods¶
| Method | Description |
|---|---|
.block(Block) |
Wrap in a Block with border/title |
.default_style(Style) |
Style for all un-styled days |
.show_surrounding(Style) |
Show adjacent-month days in this style |
.show_month_header(Style) |
Show the "Month Year" header in this style |
.show_weekdays_header(Style) |
Show "Su Mo Tu …" header in this style |
All builder methods return a new Monthly instance (immutable builder
pattern). The original is not modified.
Minimum size¶
The Monthly widget requires at least 9 columns × 8 rows for a single
month without any surrounding days. Add 2 rows for headers.
Full interactive example¶
Controls: ←/→ change months, ↑/↓ change years, t jump to today, q quit.
Weekend highlighting recipe¶
import calendar
def make_store_with_weekends(year: int, month: int) -> CalendarEventStore:
store = CalendarEventStore()
store.add_today(Style().fg(Color.green()).bold())
_, days = calendar.monthrange(year, month)
for day in range(1, days + 1):
if calendar.weekday(year, month, day) >= 5: # Sat/Sun
store.add(
CalendarDate.from_ymd(year, month, day),
Style().fg(Color.yellow()).dim(),
)
return store