Skip to main content
WireKit
Copy for LLM

Event Calendar

A scheduling calendar for displaying events across month, week, and agenda views. The month view is a day grid with event pills and a "+N more" overflow; the week view is an hour-row time grid with overlap-split event blocks and a current-time line; the agenda view is a chronological list grouped by day. Navigation (previous / next / today) and the view switcher recompute the visible window. Clicking an event emits an event-click event you handle in Livewire.

This is the scheduling grid — distinct from calendar, which is a date-picker widget. It is token-themed with no third-party calendar library.

Month View

The default view — a 7-column day grid. Events render as pills; days with more than three events show a "+N more" indicator. All-day events and day markers (see Day Markers below) appear as full-width labels at the top of the cell.

Month view with events, overflow, and a day marker

No events in this range

Week View

The time grid positions each event by its start and duration. Overlapping events split into side-by-side columns; a red line marks the current time on today's column. All-day events and day markers sit in a dedicated band above the hour grid (timed events have an hour position; all-day ones do not).

Week view with back-to-back, overlapping, all-day, and short events

No events in this range

Agenda View

A compact chronological list — the best view on mobile and for a quick "what's next" glance.

Agenda view with a day marker

No events in this range

Day Markers

dayMarkers is a day-level dimension, separate from timed events — use it to mark holidays, working exception days, or notes. Each marker carries a date, a label, an optional type, and an optional blocked flag, and renders across all three views: a full-width band in month, a chip in the week all-day band, and its own line in agenda.

Holidays and blocked days

No events in this range

A blocked day reads as unavailable — a muted surface with a diagonal hatch, plus an "unavailable" suffix in its accessible name, so the state is never conveyed by color or texture alone. WireKit renders the visual and semantic state only; enforce any booking logic in your own application behind a blocked day.

Day-Marker Shape

Key Required Description
date yes YYYY-MM-DD (parsed date-only — no timezone, so it never drifts a day)
label yes Display name (e.g. Christmas Day)
type no holiday (default) · working · note — drives the tint
blocked no true marks the day unavailable (muted surface + hatch + accessible state)

Week Start

weekStartsOn sets the first column of the month and week grids — 0 for Sunday through 6 for Saturday (1, Monday, is the default). Set it per instance or globally in config/wirekit.php.

Sunday-start month grid

No events in this range

Livewire Integration

Pass events from the server and handle clicks (and view changes) in your component:

{{-- 1. Open a detail modal when an event is clicked --}}
<x-wirekit::event-calendar
    :events="$this->events"
    view="month"
    x-on:event-click="$wire.openEvent($event.detail.id)"
    x-on:view-change="$wire.set('view', $event.detail.view)"
/>
// 2. Shape events for the calendar (start/end are ISO 8601)
public function getEventsProperty(): array
{
    return Appointment::query()
        ->whereBetween('starts_at', [now()->startOfMonth(), now()->endOfMonth()])
        ->get()
        ->map(fn ($a) => [
            'id' => $a->id,
            'title' => $a->title,
            'start' => $a->starts_at->toIso8601String(),
            'end' => $a->ends_at?->toIso8601String(),
            'intent' => $a->status === 'confirmed' ? 'success' : 'warning',
        ])
        ->all();
}

// 3. Open the clicked event
public function openEvent(int $id): void
{
    $this->editing = Appointment::find($id);
}

Event Shape

Key Required Description
id yes Unique identifier (emitted on click)
title yes Event title
start yes ISO 8601 start datetime
end no ISO 8601 end (defaults to start + 1 hour)
allDay no true renders "All day" in agenda
intent no accent (default) · success · warning · danger · neutral

Props

Prop Type Default Description
events array [] Events (see shape above)
dayMarkers array [] Day-level holiday / working / note markers (see shape)
view string 'month' month · week · agenda
date string|null null ISO date the calendar opens on (default today)
weekStartsOn int 1 First column: 0 (Sunday) – 6 (Saturday); 1 (Monday) is the default
ariaLabel string 'Calendar' Accessible name for the calendar
scope string|null null Scoped personalization name

Accessibility

  • Each event is a focusable button with a full accessible label ("Design review, Wednesday June 10, 2:00 PM"), so the schedule is operable without relying on the event's color.
  • The week time grid is a labeled role="region" with tabindex="0" and a focus ring, so the scrolling grid is keyboard-reachable (WCAG 2.1.1).
  • The title is an aria-live="polite" region, so navigating months / weeks is announced.
  • The view switcher is a role="radiogroup" of role="radio" buttons with aria-checked + roving tabindex — arrow keys move and select, wrapping at the ends (the buttons own no tabpanels, so tab semantics would be a broken contract).

Keyboard Interaction

Key Action
Tab Move through navigation, the view switcher, and event blocks
Enter / Space Activate an event, navigate, or switch view

Design Tokens

Element Token
Today highlight --color-wk-accent
Current-time line --color-wk-danger
Grid borders --color-wk-border
Out-of-month days --color-wk-bg-subtle
Event (accent / success / warning / danger) --color-wk-accent / --color-wk-success / --color-wk-warning / --color-wk-danger
Focus ring --color-wk-ring

Customization

Set the default view and week start via config/wirekit.php:

'components' => [
    'event-calendar' => [
        'view' => 'week',
        'week-starts-on' => 0, // Sunday
    ],
],

Usage & Conventions

This build focuses on displaying a schedule. Drag-to-create / move / resize, recurrence (RRULE), the multi-resource view, and ICS export are planned as follow-ups.

Further Reading