Skip to content

Feat(tui): month, week and day views for the Tasks calendar - #30

Merged
adibhanna merged 13 commits into
ZenNotes:zn-0.14.0from
spirit-of-light:calendar-modes
Nov 1, 2026
Merged

adibhanna merged 13 commits into
ZenNotes:zn-0.14.0from
spirit-of-light:calendar-modes

Conversation

@spirit-of-light

Copy link
Copy Markdown
Contributor

:tasks calendar used to show a small month grid next to a list of the selected day's tasks. It now opens on a full-page month grid, and Esc cycles between month, week and day views. Each day box lists its tasks and ends with +N more when they don't all fit. Tasks are placed on their due date and, unlike the desktop calendar, also on their scheduled date, marked with ». Undated tasks are listed in a No-date strip under the grid.

Week and day view show an hour list next to the day columns: hourly by default, half-hourly after z (Vim mode). It scrolls with j/k, <C-D>/<C-U> or the mouse wheel when it doesn't fit. When the whole list fits, j/k scroll a busy day's column instead. h/j/k/l and the arrow keys move the day, [/] the month, t goes to today and o opens the day's daily note. A new session always opens on the month grid, and the view you picked is kept for the rest of the session.

Enter and Tab move focus between the grid, the selected day's tasks and the No-date strip. With a task focused, the usual task keys act on it, and T opens a due-date menu: today, tomorrow, next week, the selected day, clear, or another date. Clicking, double-clicking and right-clicking work on days, entries and strip tasks in every view, and keyboard menus open next to the selected task. Without Vim mode, the arrow keys, Enter, Tab and Esc do the same jobs, and no printable key is taken.

Each view has a minimum body size: month 72×18, week 64×12, day 40×10. Below it, the page shows Terminal too small, and Esc still cycles the views. The side calendar panel and BucketTasksByDueDate are unchanged, and guard tests pin them.

Two fixes are in their own commits:

  • Right-click measured its position from the pane's outer edge instead of its content. In a framed pane every view saw the click two columns right and one row down, so context menus opened for the wrong row or not at all. This affected Tasks, Tags, the note list, Home and Database, not only the calendar.
  • In narrow boxes the overflow line was cut to +4 mor. It now reads +N when +N more doesn't fit.

The README's Views section and the calendar's key hints describe the new keys. No new dependency, setting or stored state.

Checked with go test -race ./..., go vet ./..., go build ./cmd/zn, gofmt -l internal cmd, git diff --check and bash scripts/sandbox.sh --smoke. I also checked it by hand in the sandbox with default settings: at 132×35, at the month minimum (111×24 with the sidebar), one cell below it, and at 250×70.

Month view, the default:

Week view:

The T due-date menu on a focused task:

Day view with the half-hourly hour list (z):

Month view at its minimum size; a box with one line shows +6:

One column below the minimum:

🤖 Generated with Claude Code

spirit-of-light and others added 13 commits October 31, 2026 16:39
The Tasks calendar is getting month, week and day views, and each needs
to know which open tasks fall on which day. Until now only the due date
counted, through the grouping the side calendar and Home share.

bucketCalendarEntries places a task on its due day and, when it has a
different scheduled date, on that day too, flagged as scheduled; a task
whose two dates match shows once. Due entries come before scheduled
ones and each group keeps the scan order. Done, cancelled and forwarded
tasks are left out. Tasks with no date are returned for a separate
"No date" list, ordered by priority and then alphabetically.

The calendar uses its own grouping so the side calendar panel and
BucketTasksByDueDate stay exactly as they are; new tests pin the
panel's rendering and click mapping and the existing grouping, so a
later change to the Tasks calendar cannot alter them by accident.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The calendar mode drew a 35-column mini-grid with the selected day's
tasks listed underneath, so a month's work could only be read one day
at a time. It now fills the page: weekday names across the top, a box
per day with its date in the top-left corner and its tasks inside, cut
to the box's width (wide characters included) and closed with "+N more"
when they do not fit. The selected day's tasks sit in a panel beside
the grid and tasks without a date in a strip below it; an entry placed
by its scheduled date carries a "»" marker. Week numbers and the week
start follow the existing calendar preferences, and the task filter
applies as before.

Below 72x18 cells the body says "Terminal too small" instead of
drawing a grid too cramped to read.

The calendar moves into its own component that computes the layout
once per frame; drawing, mouse hit-testing and the selection position
all read that layout, so they cannot disagree about where a day is.
The side calendar panel keeps its own renderer and is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the month grid, the half-page keys (Ctrl+D and Ctrl+U by default)
now show the next and previous month, the same move as ] and [, and
the selected day follows into the month shown. They go through the
keymap, so a user who rebinds nav.halfPageDown or nav.halfPageUp gets
the move on their own keys, with Vim mode on or off.

The new tests also pin the month keys that already worked: hjkl and
the arrows, Enter into the day's tasks and Esc or h back to the grid,
the due-date keys, t for today and o for the daily note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The calendar showed only a month. Esc on the grid now steps through
month, week and day and back, keeping the selected day, so the week
shown is the one that contains it. Esc still works below a layout's
minimum size, which is how to reach a smaller layout when the terminal
is too small for the current one; nothing switches by itself.

Week view shows seven columns in the configured week-start order and
day view one full-width column, each with its tasks listed from the
top, "+N more" when they overflow, and the "No date" strip pinned
below. An hour list runs down the left, 00 to 23 or 12 AM to 11 PM
following time_format. Tasks have no time of day yet, so the list only
gives the day its shape and no task is placed in an hour row. Week
numbers stay in the month view only.

The layout chosen lasts for the session, across switching Tasks views
and :tasks calendar, and every new session starts on the month. It is
never written to the configuration, so tasks_view_mode, which the
desktop app shares, still only says "calendar".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the week and day views the half-page keys moved a whole month, as
on the month grid. They now move by the layout's own unit: a month in
month view, a week in week view, a day in day view, and the selected
day follows.

Tab, and Enter on a day with tasks, move focus from the grid into the
selected day's tasks, where j and k pick an entry and the usual task
keys act on it: Enter or o opens it, x toggles it, < and > move its
due date and the menu key opens its task menu. Esc, Left or h return
to the grid. Tab skips a day with no tasks, and Enter on such a day
still opens its daily note. Tab also works without Vim mode.

h and l, the arrows across week edges, t, o and n already behaved the
same in every layout; new tests pin that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With Vim mode on, z switches the week and day hour list between hourly and
half-hourly rows. The variant goes back to hourly each time the calendar is
opened, and stays put while moving between days, weeks and the two column
views.

When the list does not fit the body, j/k, the arrow keys and the mouse wheel
scroll it by one row, clamped at both ends. The position is kept as a time of
day rather than a row index, so it survives a change of variant and moving to
other days. On the grid in week and day view, j/k no longer move the selected
day; h/l and the half-page keys do that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the whole hour list fits, j/k and the arrow keys on the grid scroll the
selected day's column one entry at a time instead, so a day with more tasks
than lines can be read without leaving the grid. A scrolled column counts the
entries hidden above it with a "+N more" line at its top, as well as those
still below. Picking another day returns the column to its top.

With focus inside the column, the column follows the selection, so the
selected task never sits off screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tab now cycles the calendar between the grid, the selected day's tasks and
the strip of undated tasks below, skipping whichever of the two is empty.
In the strip, j/k and the arrow keys move the selection and the usual task
keys act on it, so undated tasks can be opened, toggled or given a date
without leaving the calendar.

When a task leaves the strip, for example because it got a due date, the
selection stays at the same position, and focus goes back to the grid once
the strip is empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With focus on the selected day's tasks or the No-date strip, T now
opens a menu for the selected task's due date: Today, Tomorrow, Next
week, the day selected in the calendar, Clear due date, or Other…,
which opens the usual due-date prompt. Arrow keys and Enter pick a
choice; Esc, q and Ctrl+C close the menu and leave the task as it was.
The menu works with Vim mode on or off. On the grid, T still jumps to
today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Right-click measured its position from the pane's outer edge instead of
its content, so in a framed pane every view saw the click two columns to
the right and one row lower than where it happened, and context menus
opened for the wrong row or not at all. It now measures from the content
area like a left click does, and a right-click on the frame itself does
nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In week and day view, clicking a task in a day's column now selects it
and moves focus into the column, a double-click opens its note, and a
right-click opens its menu, as the month view's task list already did.
Clicking, double-clicking or right-clicking a task in the No-date strip
does the same there, in every view.

Menus opened from the keyboard now appear next to the selected task in
the strip and in week and day columns, instead of at a fixed spot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A day with more tasks than its box or column can show ends with a
"+N more" line, but in narrow boxes it was cut to the width, so it read
"+4 mor" or "+2 mo". When "+N more" does not fit, the line now reads
just "+N".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README's Views section now describes the calendar's month, week and
day views, the hourly and half-hourly hour list, moving focus between the
grid, the day's tasks and the No-date strip, and the due-date menu. It
also notes that, unlike the desktop calendar, the terminal calendar
places tasks on their scheduled date too. The key hints at the bottom of
the calendar list the new keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@spirit-of-light
spirit-of-light marked this pull request as draft November 1, 2026 20:51
@adibhanna
adibhanna changed the base branch from main to zn-0.14.0 November 1, 2026 20:53
adibhanna added a commit that referenced this pull request Nov 1, 2026
…it-of-light)

With six review follow-ups on top of the contributor's commits. The merge also updates ownsKey from #27's follow-up, which read v.dayFocus, a field #30 removes: it now checks that the calendar grid has focus, so [ and ] still change the month at once.
@adibhanna
adibhanna merged commit e80c3fc into ZenNotes:zn-0.14.0 Nov 1, 2026
5 checks passed
@adibhanna

Copy link
Copy Markdown
Contributor

Thanks for this! The full-page month with the No date strip, Tab moving between the grid, the day's tasks and the strip, the mouse work and the right-click fix make the calendar much more usable, and the tests made the review easy. It's merged into zn-0.14.0 as 072a386 and ships in zn 0.14.0, with these follow-ups on top:

  • 32a7f85: a focused calendar task takes no letters with Vim off. The grid followed the rule, but a task in the day's list or the strip still took T, c (cancel), d, e and the rest, and one test asserted that T opens the menu with Vim off. With Vim off, letters now do nothing there, and in Vim mode : on a focused task opens the ex line.
  • 557e86a: T moves a focused task to today, and @ opens your due-date menu. Those are the two keys' meanings in the desktop calendar, so both apps now agree. The menu itself is unchanged.
  • fc819fc: the key hints follow the focus and the view (no z on the month grid, no "T due menu" on the grid where T goes to today), and zn help lists the new keys.
  • 591d660: a compact month below 72x18. In an 80x24 terminal with the sidebar, the default view showed "Terminal too small". It now shows a line per week with a count per day, the day's tasks under it and the strip, built on your layout regions, so keys and clicks work unchanged.
  • a00fe96: dropped the // AC.. ids from the due-menu tests and an unused tab in the Kanban key gate.
  • 9d1c18d: week and day views without the hour axis. Tasks have a date but no time, and the columns list them from the top (as your test pins), so the hour labels made the first task read as midnight and the next as 01:00 (or 00:30 after z). The columns now use the full height; z and hour scrolling are gone, and j/k still scroll a busy day's column.

The merge also updates ownsKey from #27's follow-up, which read v.dayFocus; it now checks that the grid has focus, so [ and ] still change the month at once.

Left as you had them: Esc cycling month, week and day; task notes also placed on their scheduled: date; and forwarded [>] records left off the calendar (zn's forwarded copy keeps its due:, so showing both would list the task twice).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants