Skip to content

Calendars & schedules

Time as a grid or a dial: month agendas, rotas, day and week schedules, heatmaps and bookings.

Installation & usage

npx @youj/cli add app-month-agenda

Also installs alert, button, calendar, card, hatched-bar, icon-chevron-left, icon-chevron-right, icon-plus, skeleton, tooltip, typography, use-controllable-state, use-now, youj-core, youj-presets, youj-ui-core.

The CLI copies the block to blocks/app/month-agenda.tsx with every component it uses, so it’s yours to edit.

Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:

monthAgenda-view.tsx
'use client'

import { MonthAgenda, type MonthAgendaProps } from '@/blocks/app/month-agenda'

export function MonthAgendaView({ events }: Pick<MonthAgendaProps, 'events'>) {
  return (
    <MonthAgenda
      events={events}
      copy={{ title: 'Subscriptions' }}
      onRetry={() => {
        // your code
      }}
      onMonthChange={(month) => {
        // your code
      }}
      onValueChange={(day) => {
        // your code
      }}
    />
  )
}

Reference

Props20 props, 1 types

Props

MonthAgenda props
PropType
themeThemeInput

Wraps the card in this theme. Default: the theme around it.

–
embeddedboolean

Inside another app: a section named by an h2, without the page around the card.

default true

true
fillboolean

Take the whole width it's given instead of stopping at its natural width (448px at 100% scale).

default false

false
copyPartial<MonthAgendaCopy>

Any of the card's strings, to rewrite or translate.

–
localestring

Formats the month, days and money (BCP 47). Default: the app's locale (YoujProvider), else en-US.

–
eventsMonthAgendaEvent[]

The events, each coming round on the day it starts.

–
format(amount: number) => string

Formats an amount. Default: US dollars in the locale's number format.

–
loadingboolean

Skeleton tiles in place of the month's events while your data loads.

default false

false
errorstring

Shown over the month when it fails to load, with Retry when onRetry is set.

–
onRetry() => void

Retries after an error.

–
emptyReactNode

Replaces the line under the month when there are no events.

default `copy.none`

`copy.none`
todayDate | string | number

Lit on the calendar. Default: the demo's day with the demo events; with your own, the browser's clock once mounted.

–
monthDate | string

The month shown (any day in it), when your app owns it.

–
defaultMonthDate | string

The month shown at first. Default: today's.

–
onMonthChange(month: Date) => void–
valuestring | null

The picked day, "2026-10-15", when your app owns it; null for none.

–
defaultValuestring | null

default null

null
onValueChange(day: string | null) => void–
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6

The first day of the week, 0 for Sunday. Default: the locale's.

–
onAdd(day: string) => void

Adds an event on a day (the picked one, else today), "2026-10-15".

–

MonthAgendaEvent

MonthAgendaEvent props
PropType
idRequiredstring–
nameRequiredstring–
amountnumber

What it costs each time it comes round, formatted by format. Leave out and no money is shown for it; leave out on every event and the card shows none at all.

–
cycleRequiredMonthAgendaCycle
'monthly''yearly'
–
startRequiredstring

The day it starts, "2025-10-10": it comes round on that day of each month, or of that month each year.

–
markMonthAgendaMark
'ring''half''diamond''kite''triangle''hex''drop''bars''orbit'

Its mark, a shape the block draws.

–
logoReactNode

Your own logo (an <img> or an icon), drawn instead of mark.

–
toneMonthAgendaTone
'accent''neutral''chart-1''chart-2''chart-3''chart-4''chart-5'
–
Strings23 keys for copy

Strings

copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.

titlesubtitleaddaddingaddedtodaypreviousnextmonthlyyearlycountnewCountperMonthperYearonDayonDayEventupcomingmonthTotalmonthCountloadingLabelretrynonefailed
Built from8 components
Accessibilitygrids, keyboard, live regions, motion

Accessibility

Month agenda is the kit's Calendar grid: the arrow keys walk the days, Page Up and Page Down the months, and a day with events is named with its date and them ("Bills Tessel, $54.99 Monthly"), which its tooltip shows on hover and keyboard focus. The month name is a polite live region, the cycle is a solid dot or a ring as well as a word, and the arrows and + are named buttons.

Shift rota groups the current shift under a label, the countdown is role="timer", and the time lanes are one tab stop where the arrow keys walk the shifts and Enter opens one, with a hidden hint.

Day schedule draws a ring that is an image with a text description, and each entry's pause switch is named for it. Its heading level follows whether it is embedded.

The week's time blocks and its clock are each one tab stop, a group named for the chart and described by a sentence on the week's total. The arrow keys step through the entries in the order of the week (Right and Down on, Left and Up back), Home and End jump to the first and last, and Escape lets go. The entry is read out by a polite live region as its day, times, kind and length, and every entry is also listed as text for screen readers. The now line and hand are decorative; the time is text beside them.

Each chart has a name and a one-sentence summary, and the metric chart's numbers are also in a real table behind View data. Wherever you can scrub a chart (the KPI tiles and the metric chart), it is a slider: Left and Right step a bucket, Home and End jump to either end, Escape lets go, and each position is read out as a sentence with the date, the figures and the change. The tile and chart headers update with it.

The activity heatmap is a grid with one tab stop. The arrow keys move a day or a week, Home and End move along a weekday, Page Up and Page Down jump four weeks, and Ctrl+Home and Ctrl+End go to the first and last day. Every day is named with its date and value, and the grid is described by a sentence on the total, the busiest day and the busiest weekday. The legend's steps are toggle buttons named with their range, and picking one says how many days it holds.

Terrain calendar draws on a canvas that is aria-hidden. Its days are exposed as an ARIA grid for the keyboard and screen readers (arrow keys move between days), the measure and category switches are labelled, the entries table has a hidden caption, and view changes are announced.

Slot booking lists each day's slots in a labelled list; every slot is a button. The service filter, the pass and the confirmation are labelled, and the grid variant adds previous and next week buttons. The review pane is a labelled region.

In Itinerary the boarding pass is a labelled group whose route line is named (Barcelona to Rome) and whose countdown is a timer with live announcements off. The days are tabs (arrow keys, Home and End), each named with its date, Today and its city or Travel to …; each day's plans are an ordered list under a heading, statuses are written out, and the copy buttons name the code they copy and announce it. The stories show other worlds, with their own names and words.

Under reduced motion rows, panes and the plane on the pass are drawn in place.