# Examples
URL: https://pro.rv-grid.com/guides/event-scheduler/examples/
Source: src/content/docs/guides/event-scheduler/examples.mdx
Description: Working Event Scheduler examples for setup, templates, menus, availability, read-only mode, cancelable selection, and custom themes.
This page collects small, product-neutral Event Scheduler examples. The same APIs work for shifts, bookings, appointments, staffing, rooms, maintenance, tasks, equipment, and team planning.

The runnable demo catalog includes these complete scheduler stories:

| Demo | Use it for |
| --- | --- |
| Event Staff Scheduler | Resource timeline, coverage, conflicts, templates, saved views, and remote-mode controls. |
| Employee Shift Planner | Week view with days on the x-axis, time on the y-axis, drag-create, move, resize, delete, and closed hours. |
| Room Booking Scheduler | Resource booking with availability windows, blocked time, conflicts, and grouped resources. |
| Equipment / Machine Scheduler | Maintenance planning, utilization, capacity rows, and exportable workload data. |
| Developer Sprint Scheduler | Team/task planning, custom ranges, unassigned work, templates, and workload balancing. |

## Basic weekly scheduler

```ts
import {
  EventSchedulerPlugin,
  type EventSchedulerConfig,
  type EventSchedulerEventEntity,
} from '@revolist/revogrid-enterprise';

const events: EventSchedulerEventEntity[] = [
  {
    id: 'booking-1',
    title: 'Customer onboarding',
    resourceId: 'room-a',
    startDateTime: '2026-06-08T09:00:00.000Z',
    endDateTime: '2026-06-08T11:00:00.000Z',
    type: 'booking',
    status: 'confirmed',
  },
];

const eventScheduler: EventSchedulerConfig = {
  view: 'week',
  weekStartDate: '2026-06-08',
  weekStartsOn: 1,
  visibleDays: [1, 2, 3, 4, 5],
  timeRange: { start: '06:00', end: '22:00' },
  slotMinutes: 30,
  locale: 'en-US',
  timeZone: 'UTC',
  editable: true,
  allowCreate: true,
  allowMove: true,
  allowResize: true,
  allowDelete: true,
  todayHighlight: true,
  showCurrentTimeMarker: true,
};

grid.plugins = [EventSchedulerPlugin];
grid.eventScheduler = eventScheduler;
grid.eventSchedulerEvents = events;
```

## Custom event template

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  eventProperties: ({ event, isSelected, hasConflict, isLocked }) => ({
    class: [
      'planner-event',
      isSelected ? 'planner-event--selected' : '',
      hasConflict ? 'planner-event--conflict' : '',
      isLocked ? 'planner-event--locked' : '',
    ].filter(Boolean).join(' '),
    style: {
      '--planner-event-accent': event.color ?? '#2563eb',
    },
  }),
  eventContentTemplate: (h, { event, resource, start, end, isShortEvent }) =>
    h('span', { class: 'planner-event__body' }, [
      h('strong', { class: 'planner-event__title' }, event.title),
      isShortEvent ? null : h('span', { class: 'planner-event__time' }, `${start.slice(11, 16)}-${end.slice(11, 16)}`),
      resource ? h('small', { class: 'planner-event__resource' }, resource.name) : null,
    ]),
  eventTooltipTemplate: ({ event, resource, duration }) =>
    `${event.title}\n${resource?.name ?? 'Unassigned'}\n${duration} minutes`,
};
```

## Custom day header

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  dayHeaderFormatter: (date) =>
    new Intl.DateTimeFormat('en-US', {
      weekday: 'short',
      month: 'short',
      day: 'numeric',
      timeZone: 'UTC',
    }).format(date),
  dayHeaderTemplate: (h, context) =>
    h('span', { class: 'planner-day-header' }, [
      h('strong', null, context.defaultLabel),
      context.today ? h('span', { class: 'planner-day-header__badge' }, 'Today') : null,
      context.holiday ? h('span', { class: 'planner-day-header__holiday' }, context.holidayLabel) : null,
      h('small', null, `${context.eventCount ?? 0} events`),
    ]),
  dayHeaderProperties: ({ today, weekend, holiday }) => ({
    class: [
      today ? 'planner-day-header--today' : '',
      weekend ? 'planner-day-header--weekend' : '',
      holiday ? 'planner-day-header--holiday' : '',
    ].filter(Boolean).join(' '),
  }),
};
```

## Custom slot context menu

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  contextMenu: {
    enabled: true,
    getSlotContextMenuItems: ({ slot }) => slot
      ? [
          {
            id: 'create-booking',
            label: 'Create booking here',
            shortcut: 'C',
            action: () => createBooking(slot),
          },
          {
            id: 'hold-slot',
            label: 'Block this time',
            group: 'availability',
            action: () => createHold(slot),
          },
        ]
      : [],
    onContextMenuAction: ({ itemId, target, slot }) =>
      analytics.track('scheduler_menu_action', { itemId, target, slot }),
  },
};
```

## Custom current time marker

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  showCurrentTimeMarker: true,
  currentTimeUpdateInterval: 60_000,
  currentTimeLabelFormatter: ({ dateTime }) =>
    new Intl.DateTimeFormat('en-US', {
      hour: 'numeric',
      minute: '2-digit',
    }).format(new Date(dateTime)),
  currentTimeMarkerProperties: ({ orientation }) => ({
    class: `planner-now planner-now--${orientation}`,
    style: {
      '--event-scheduler-current-time-color': '#dc2626',
    },
  }),
  currentTimeMarkerTemplate: (h, { label }) =>
    h('span', { class: 'planner-now__label' }, label),
};
```

## Closed hours and availability

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  workingHours: {
    byDay: {
      1: { start: '08:00', end: '18:00' },
      2: { start: '08:00', end: '18:00' },
      3: { start: '08:00', end: '18:00' },
      4: { start: '08:00', end: '18:00' },
      5: { start: '08:00', end: '16:00' },
      0: false,
      6: false,
    },
  },
  closedHours: [
    {
      id: 'lunch',
      days: [1, 2, 3, 4, 5],
      ranges: { start: '12:00', end: '13:00' },
      title: 'Closed',
      reason: 'Lunch break',
    },
  ],
  closedSlotTooltip: ({ title, reason }) =>
    [title, reason].filter(Boolean).join(' - '),
  closedSlotTemplate: (h, { reason }) =>
    h('span', { class: 'planner-slot__closed' }, reason ?? 'Closed'),
  isTimeSlotAvailable: ({ date, startMinutes }) =>
    date !== '2026-06-19' && startMinutes >= 8 * 60,
};
```

## Read-only mode

```ts
grid.eventScheduler = {
  ...grid.eventScheduler,
  editable: false,
  allowCreate: false,
  allowMove: false,
  allowResize: false,
  allowDelete: false,
  keyboardShortcuts: {
    enabled: true,
    shortcuts: {
      copy: 'Mod+c',
      paste: false,
      duplicate: false,
      delete: false,
      lock: false,
    },
  },
};
```

Read-only mode keeps rendering, selection, tooltips, context menus, and custom templates active while blocking scheduler mutations.

## Cancelable selection state

```ts
let selectedEventIds: readonly string[] = [];

grid.addEventListener('event-scheduler-before-event-select', (event) => {
  event.preventDefault();
  selectedEventIds = event.detail.eventIds.map(String);
  renderScheduler();
});

function renderScheduler() {
  grid.eventScheduler = {
    ...grid.eventScheduler,
    selectionMode: 'multiple',
    selection: {
      selectedEventIds,
      clipboard: true,
      onChange: ({ eventIds }) => {
        selectedEventIds = eventIds.map(String);
        renderScheduler();
      },
    },
    onSelectionChange: ({ events }) =>
      inspector.show(events),
    onEventMove: ({ events }) => {
      grid.eventSchedulerEvents = [...events];
      void saveEvents(events);
    },
  };
}
```

Use the before-select event when selection lives in application state. Prevent the pending scheduler selection, update host state, then pass the accepted ids back through `selection.selectedEventIds`. Event arrays, visible ranges, and filters follow the same ownership model: the scheduler emits callbacks and the host updates `eventScheduler`, `eventSchedulerEvents`, and related props.

## Custom styling and theme

```css
.booking-scheduler revo-grid {
  --event-scheduler-accent: #0f766e;
  --event-scheduler-accent-soft: #ccfbf1;
  --event-scheduler-grid-line: #d8dee6;
  --event-scheduler-current-time-color: #dc2626;
  --event-scheduler-weekend-bg: rgba(15, 118, 110, 0.05);
  --event-scheduler-event-bg: #eef7f3;
  --event-scheduler-event-color: #0f766e;
}

.planner-event--conflict {
  --event-scheduler-event-color: #b45309;
  --event-scheduler-event-bg: #fff7ed;
}

.planner-day-header--today {
  box-shadow: inset 0 -2px 0 var(--event-scheduler-accent);
}
```

Use CSS variables for broad theme changes. Use `eventProperties`, `dayHeaderProperties`, `slotProperties`, `closedSlotProperties`, and `currentTimeMarkerProperties` when styling depends on scheduler state.

## Related guides

- [Week View](../week-view/) covers day/time configuration, visible range, week start, locale, timezone, and edit ownership.
- [Customization](../customization/) documents the full visual customization category. Use [Event Rendering](../customization/events/) for templates and tooltips, [Slots, Hours, and Markers](../customization/slots-hours/) for slot and current-time examples, [Context Menus](../customization/context-menu/) for commands, and [Styling and Themes](../customization/styling/) for CSS hooks.
- [Availability](../scheduling-rules/availability/) covers calendars, working hours, blocked time, breaks, holidays, and outside-hours styling.
- [Editing and Interaction](../event-editing/) covers read-only mode, permissions, cancelable hooks, mutation events, selection, clipboard, keyboard shortcuts, custom editors, and persistence.
