Props Reference

Complete reference for all Scheduler props, types, and configuration.

Props Reference

<Scheduler />

The main component. All props are optional except categories, employees, shifts, and onShiftsChange.

Required props

PropTypeDescription
categoriesResource[]The row groups (teams, roles, departments)
employeesResource[]Staff members — each belongs to a category
shiftsBlock[]The blocks rendered on the grid
onShiftsChange(shifts: Block[]) => voidCalled whenever shifts are created, moved, resized, or deleted

View props

PropTypeDefaultDescription
initialViewViewType"week"Starting view
configSchedulerConfigDomain preset config (see below)

ViewType values: "day", "week", "month", "year", "list", "timeline"

Callback props

PropTypeDescription
onShiftClick(block: Block, resource: Resource) => voidCalled when user clicks a shift block
onAddShift(date: Date, categoryId?: string, empId?: string) => voidCalled when user clicks the + button on a cell
onBlockMoved(block: Block, newDate: string, newStartH: number, newEndH: number) => voidCalled after a drag-drop move
onBlockCreate(block: Block) => voidCalled when a new block is created
onBlockDelete(block: Block) => voidCalled when a block is deleted
onBlockMove(block: Block) => voidCalled during every pointermove while dragging
onBlockResize(block: Block) => voidCalled during resize
onBlockPublish(block: Block) => voidCalled when a draft block is published
onDeleteShift(shiftId: string) => voidOverride default delete behaviour
onAuditEvent(entry: AuditEntry) => voidReceives every audit trail event
onVisibleRangeChange(start: Date, end: Date) => voidReports visible date range — use for data prefetching

Display props

PropTypeDefaultDescription
readOnlybooleanfalseDisables all editing interactions
isLoadingbooleanfalseShows loading skeletons
zoomnumber1Zoom level (0.5–2). Use with setZoom for controlled zoom
setZoomDispatch<SetStateAction<number>>Controls zoom externally
bufferDaysnumber15Days to render before/after focused date in day view
prefetchThresholdnumber0.8Scroll ratio (0–1) at which onVisibleRangeChange fires

Render slot props

Override any part of the scheduler UI with your own React components:

PropTypeDescription
headerSlot() => ReactNodeRenders above the scheduler toolbar
footerSlot({ onSettingsChange }) => ReactNodeRenders in the toolbar footer area
blockSlot(block: Block) => ReactNodeCustom content inside each shift block
sidebarSlot(resource: Resource) => ReactNodeCustom sidebar row content

Block type

interface Block {
  id: string
  categoryId: string
  employeeId: string
  employee: string        // Display name (shown on block)
  date: string            // YYYY-MM-DD
  startH: number          // 0–24 (e.g. 9 = 9:00 AM, 13.5 = 1:30 PM)
  endH: number            // 0–24
  status: 'draft' | 'published'
  draggable?: boolean     // default true
  resizable?: boolean     // default true
  color?: string          // override category colour
  breakStartH?: number    // break start (optional)
  breakEndH?: number      // break end (optional)
  meta?: Record<string, unknown>  // your custom data
}

Half-hour shifts

Use decimal hours for half-hour precision:

// 9:30 AM to 5:30 PM
{ startH: 9.5, endH: 17.5 }

// 1:00 AM to 2:30 AM  
{ startH: 1, endH: 2.5 }

Resource type

interface Resource {
  id: string
  name: string
  kind: 'category' | 'employee'
  colorIdx: number          // 0–11, maps to the scheduler's colour palette
  categoryId?: string       // required for employees
  role?: string             // displayed in sidebar
  avatar?: string           // URL, shown in sidebar
  meta?: Record<string, unknown>
}

SchedulerConfig

Created with createSchedulerConfig() or a domain preset function:

const config = createSchedulerConfig({
  // Working hours per day (0=Sunday … 6=Saturday, null=closed)
  workingHours: {
    0: null,                     // Sunday: closed
    1: { from: 8, to: 18 },     // Monday: 8am–6pm
    2: { from: 8, to: 18 },
    3: { from: 8, to: 18 },
    4: { from: 8, to: 18 },
    5: { from: 8, to: 18 },
    6: { from: 10, to: 14 },    // Saturday: 10am–2pm
  },

  // Visible hour range (what the grid shows)
  visibleFrom: 7,    // Start at 7am
  visibleTo: 22,     // End at 10pm

  // Snap grid in minutes (15 or 30)
  snapMinutes: 30,

  // Custom labels
  labels: {
    category: 'Department',
    employee: 'Staff member',
    shift: 'Booking',
    draft: 'Pending',
    published: 'Confirmed',
  },

  // Scroll to current time on load
  initialScrollToNow: true,
})

Domain preset functions

Each preset helper calls createSchedulerConfig internally with sensible defaults for that domain. Import and call directly — no need to pass preset manually:

import {
  createRosterConfig,
  createTvConfig,
  createConferenceConfig,
  createFestivalConfig,
  createHealthcareConfig,
  createGanttConfig,
  createVenueConfig,
} from '@sushill/shadcn-scheduler'

// Workforce roster
const config = createRosterConfig({ initialScrollToNow: true })

// TV / EPG guide
const tvConfig = createTvConfig()

// Conference / event
const conferenceConfig = createConferenceConfig({ snapMinutes: 15 })

// Music festival
const festivalConfig = createFestivalConfig()

// Healthcare rota
const healthcareConfig = createHealthcareConfig()

// Project / gantt
const ganttConfig = createGanttConfig({ snapMinutes: 60 })

// Venue / room booking
const venueConfig = createVenueConfig()

AuditEntry type

Every user action produces an audit entry:

interface AuditEntry {
  id: string
  timestamp: Date
  action: 'create' | 'move' | 'resize' | 'delete' | 'publish' | 'unpublish' | 'copy' | 'cut' | 'paste'
  blockId: string
  employeeName: string
  categoryName: string
  before?: Partial<Block>
  after?: Partial<Block>
}
<Scheduler
  onAuditEvent={(entry) => {
    console.log(`${entry.action}: ${entry.employeeName} — ${entry.blockId}`)
    // Save to your audit log
  }}
/>

→ Live demo | → Examples