Skip to content
weftGitHub

Agenda

A day at a time for a phone: a week strip, swipeable days and a button to add.

SourcePackage @weft-js/warp

Preview

tsx
import { state } from '@weft-js/core'import { Agenda } from '@weft-js/warp'import type { CalEvent } from '@weft-js/warp-core'export function TeamWeek() {  const events = state(TEAM_EVENTS)  const move = (e: CalEvent, to: { start: string; end: string }) => (events.value = events.value.map(x => (x.id === e.id ? { ...x, ...to } : x)))  return (    <div style="block-size:620px;position:relative">      <Agenda events={events.value} calendars={TEAM_CALENDARS} defaultDate={TODAY} today={TODAY} now={SCHEDULE_NOW} timeZone={TEAM_ZONE} locale="en-GB" firstDayOfWeek={1} onMove={move} onCreate={e => (events.value = [...events.value, e])} />    </div>  )}const TODAY = '2026-11-03'const SCHEDULE_NOW = '2026-11-03T10:40'const TEAM_ZONE = 'Europe/Stockholm'const TEAM_CALENDARS = ['Platform', 'Web', 'Data', 'Mobile', 'Releases', 'Time off'].map((name, i) => ({ id: i + 1, name }))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 },]

Installation

npm install @weft-js/warp

Usage

tsx
import { Agenda } from '@weft-js/warp'

When to use

Use it for

  • A calendar on a phone or in a narrow column

Reach for something else

  • Calendar, when there is room for a whole week

Accessibility

LeftandRight
Move between days in the strip
Shift+F10
Moves the focused event
  • The week strip is a set of tabs. A long press always has a keyboard path.

API Reference

PropTypeDefaultDescription
eventsCalEvent[]—The events.
datestring | State<string>—The day it opens on: a state it writes as you page, or a plain value.
defaultDatestring—The day it opens on.
titleunknown—The heading.
calendarsCalendarSource[]—The calendars the events belong to, for their colours and names.
timeZonestring—The IANA zone times are shown in, such as Europe/Berlin. The browser's otherwise.
todaystring—Pins today's date, for server rendering and tests. The browser's clock otherwise.
nowstring—Pins the current time, for server rendering and tests. The browser's clock otherwise.
localestring—The language and region used to format values.
hourCyclestring—h12 for AM and PM, h23 for a 24-hour clock. The locale's otherwise.
firstDayOfWeeknumber—0 is Sunday, 1 is Monday.
EventTypeDefaultDescription
onDateChange((d: string) => void)—Called with the new day when you page or jump to today.
onLongPress((e: CalEvent) => void)—Long press: open your own sheet. Without it the built-in MoveSheet opens and calls onMove.
onMove((e: CalEvent, to: { start: string; end: string; resource?: string | und…—An event was moved. Without onLongPress, the built-in MoveSheet does this.
onOpen((e: CalEvent) => void)—An event was pressed.
onCreate((e: CalEvent) => void)—Adds the + button, which opens the editor.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="agenda"] [data-part="row"]

rowrootapp-barapp-titlespacerstripviewporttrackpageday-title

RelatedAgenda dayMove sheetEvent editor