YearView
Twelve small months with a dot for how busy each day was.
SourcePackage @weft-js/warp
Preview
tsx
import { YearView } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function Deploys() { return ( <YearView counts={DEPLOYS_BY_DAY} events={TEAM_EVENTS} label="Deploys in 2026" year={2026} today={TODAY} locale="en-GB" firstDayOfWeek={1} direct={false} /> )}const TODAY = '2026-11-03'const TEAM_EVENTS: CalEvent[] = [ { id: 'e1', title: 'Platform standup', start: '2026-11-02T09:00', end: '2026-11-02T09:15', cal: 1, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR', location: 'Room Atlas', attendees: ['Mara Lindqvist', 'Jun Tanaka'] }, { id: 'e2', title: 'Platform standup', start: '2026-11-03T09:00', end: '2026-11-03T09:15', cal: 1, recurrence: 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR', location: 'Room Atlas', attendees: ['Mara Lindqvist', 'Jun Tanaka'] }, { id: 'e3', title: 'Checkout review', start: '2026-11-03T10:00', end: '2026-11-03T11:00', cal: 2, video: true, attendees: ['Priya Raman', 'Tomás Oliveira', 'Mara Lindqvist'] }, { id: 'e4', title: 'Incident review: mobile-bff', start: '2026-11-03T13:00', end: '2026-11-03T13:45', cal: 4, video: true, location: 'Room Birch', attendees: ['Sam Okafor', 'Inés Vidal', 'Jun Tanaka'] }, { id: 'e5', title: 'Ranking v2 handover', start: '2026-11-03T15:00', end: '2026-11-03T16:00', cal: 3, location: 'Room Cedar', attendees: ['Lena Fischer', 'Noor Haddad'] }, { id: 'e6', title: 'Priya out of office', start: '2026-11-03', end: '2026-11-03', allDay: true, cal: 6 }, { id: 'e7', title: 'Release 2026.11', start: '2026-11-04T11:00', end: '2026-11-04T12:00', cal: 5, attendees: ['Mara Lindqvist', 'Jun Tanaka', 'Tomás Oliveira'] }, { id: 'e8', title: 'Design crit', start: '2026-11-04T14:00', end: '2026-11-04T15:00', cal: 2, tentative: true, video: true }, { id: 'e9', title: 'Cost review', start: '2026-11-05T10:00', end: '2026-11-05T11:00', cal: 1, recurrence: 'FREQ=MONTHLY', attendees: ['Mara Lindqvist', 'Lena Fischer'] }, { id: 'e10', title: 'On-call handover', start: '2026-11-06T16:00', end: '2026-11-06T16:30', cal: 1, recurrence: 'FREQ=WEEKLY', video: true },]const DEPLOYS_BY_DAY: Record<string, number> = Object.fromEntries( Array.from({ length: 307 }, (_, i) => { const day = new Date(Date.UTC(2026, 0, 1 + i)) const weekend = day.getUTCDay() % 6 === 0 return [day.toISOString().slice(0, 10), weekend ? (i % 5 === 0 ? 1 : 0) : 1 + ((i * 7) % 9)] as const }).filter(([, n]) => n > 0),)Installation
npm install @weft-js/warpUsage
tsx
import { YearView } from '@weft-js/warp'<YearView counts={DEPLOYS_BY_DAY} events={TEAM_EVENTS} label="Deploys in 2026" year={2026} today={TODAY} locale="en-GB" firstDayOfWeek={1} direct={false} />When to use
Use it for
- Seeing a year at a glance
- Jumping to a day or month
Accessibility
- Arrowkeys
- Move between days, across months
- Enter
- Opens the day
- M
- Opens the month
- T
- Goes to today
- All twelve months share one tab stop.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
counts | Record<string, number> | — | Each day's number, keyed by date. |
label | string | — | Names the section when the year is not enough. |
events | CalEvent[] | — | Events for the picked day's detail. |
year | number | — | The year on show. |
today | string | — | Pins today's date, for server rendering and tests. The browser's clock otherwise. |
locale | string | — | The language and region used to format values. |
hourCycle | string | — | h12 for AM and PM, h23 for a 24-hour clock. The locale's otherwise. |
firstDayOfWeek | number | — | The day each month's rows start on, 0 for Sunday to 6. The locale's otherwise. |
openDay | ((iso: `${number}-${number}-${number}`) => boolean | void) | — | Open a day yourself. Return true when you did. |
openMonth | ((iso: `${number}-${number}-${number}`) => boolean | void) | — | Open a month yourself. Return true when you did. |
direct | boolean | true | Opens a day right away. Off, a pick shows the detail first. |
| Event | Type | Default | Description |
|---|---|---|---|
onYearChange | ((y: number) => void) | — | Called with the new year when you page. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="year"] [data-part="month-title"]
month-titletoolbartitlelegenddotsmonthsyear-monthnumdetail
RelatedAgenda