This month like cal, today bracketed, time ticking below.
This month laid out like the cal command, today in brackets, with the
weekday and the running time along the bottom: upstream's calendar,
which it is by default. Give it a date and it shows that month and day
instead, and is a date picker that keys and clicks move.
Reads the clock from env.now (see Ascii.Kit.Clock), for today and
the running time.
Options
Give them to Ascii.new/2 as options:, and new ones while it plays
with Ascii.put_options/2 (or a Phoenix player's options): the page
is drawn anew from them.
date- a day to show, as"2026-10-12": its month, the day bracketed as the one selected, and along the bottom its weekday (and the time, iftime)."2026-10"shows a month with nothing selected. Default"", as is any string that is not a date: this month, today bracketed, as upstream.marks- days to mark, as["2026-10-03", "2026-10-19"]: those in the month shown wear a·after their number (a bracketed one, only where its cell has room). Default[].monday- weeks start on Monday rather than Sunday. Defaultfalse.time- the running time at the right of the bottom line, from the clock, with adatetoo. Defaulttrue;falsefor a plain date picker.months,weekdays- the names to use, twelve from January and seven from Sunday; the heading shows each weekday's first two letters. English by default; a list of another length is ignored.cols,rows- the frame's size, 32 to 200 by 13 to 60; 32 by 13 by default. The days' cells widen to fill the width, and the page sits in the middle.
Colours
In one ink, or a gradient, with :ink and :gradient (see
Ascii.Ink); part by part with :parts (see Ascii.Parts),
parts: true taking the colours suggested here:
title- the month and year.rule- the rules above and below the weeks, grey.weekday- the heading's days, grey;weekday.weekend, Saturday's and Sunday's, cyan.day- a date;day.weekend, one on a weekend, cyan; andday.marked, one inmarks, yellow.today- today, bracketed, blue; orselected, thedategiven, blue.date,time- the weekday and day, and the time, along the bottom.
Keys and clicks
With a date, it is a date picker: Ascii.handle_event/2 takes keys
and clicks, and the day chosen is the new date, from which the app
reads it:
- ← and → move the selection a day, ↑ and ↓ a week.
- Page up and page down move it a month (to that month's last day, if it is shorter).
- Home and end go to the month's first and last day.
- A click on a day selects it.
- From a month with nothing selected (
"2026-10"), a key selects its first day (end, its last), and page up and page down change the month.
Years stay within 1 to 9999. Without a date, the clock says which
month it is, so there is none to move in: it takes none, and keys and
clicks are ignored. In Phoenix, give the player interactive (and
notify to be told of each key and click); in ExRatatui,
Ascii.ExRatatui.handle_event/3; in a terminal,
mix ascii.play calendar --option date=2026-10-08 --option time=false --interactive.
Screen readers
Ascii.describe/1 tells the month shown, the day selected and the
days marked in it, as "calendar: october 2026, 8 selected, marked 24",
the month in the names given. Showing this month from the clock, it
gives the piece's name and note.
Example
options = %{date: "2026-10-08", time: false, marks: ["2026-10-24"]}
picker = Ascii.new!("calendar", options: options, parts: true)
Ascii.describe(picker)
#=> "calendar: october 2026, 8 selected, marked 24"
{:ok, picker} = Ascii.handle_event(picker, {:key, "right"})
{:ok, picker} = Ascii.handle_event(picker, {:key, "page_down"})
picker.options.date
#=> "2026-11-09"
# Upstream's: this month, at a given moment.
now = DateTime.new!(~D[2026-03-14], ~T[15:09:26], "Etc/UTC")
{frame, _} = Ascii.new!("calendar") |> Ascii.frame(0.0, now: now)
frame.text =~ "[14]"
#=> true<Ascii.Phoenix.live_player id="day" piece="calendar" options={%{date: @today, time: false, marks: @deadlines}} parts interactive notify />Ported from src/pieces/calendar.ts in bas3line/ascii (MIT).