react-appointment-scheduler
v1.2.0
Published
A production-ready React scheduler component for appointment management with day/week views, drag-and-drop, and TypeScript support
Maintainers
Readme
react-appointment-scheduler
A production-ready React scheduler component for appointment management. Features day/week views, drag-and-drop rescheduling, create-appointment modal with multiple jobs per appointment (service + technician per job), and a minimal, themeable UI.
Features
- Day & Week Views - Toggle between single day and full week layouts
- Drag & Drop - Reschedule appointments by dragging to new times or days
- Create Appointment - Modal to add appointments with multiple jobs (each job = one service + optional technician)
- Overlap Handling - Automatically stacks overlapping appointments
- Detail Views - Modal or side panel for appointment details
- Responsive - Desktop-first with mobile support
- TypeScript - Full type definitions included
- Accessible - Keyboard navigation and ARIA labels
- Theming - CSS variables and built-in light/dark mode
Installation
npm install react-appointment-schedulerPeer Dependencies
This package requires React 18+ or 19+:
npm install react react-domStyles
Import the component styles once in your app (e.g. root layout or main entry):
import 'react-appointment-scheduler/styles.css';The scheduler needs a defined height (e.g. height: 600px or min-height: 70vh).
Quick start
import { Scheduler } from 'react-appointment-scheduler';
import type { Appointment, Service, Technician } from 'react-appointment-scheduler';
import 'react-appointment-scheduler/styles.css';
const appointments: Appointment[] = [
{
id: '1',
client: { name: 'Sarah Johnson', path: '' },
serviceType: 'classic-lashes',
artist: 'tech-1',
startTime: new Date('2025-02-17T09:00:00'),
duration: 60,
email: '[email protected]',
},
];
const services: Service[] = [
{ id: 'classic-lashes', name: 'Classic Lashes', category: 'Lashes', duration: 60 },
{ id: 'quick-touchup', name: 'Quick Touch-up', category: 'Lashes', duration: 30 },
];
const technicians: Technician[] = [
{ id: 'tech-1', name: 'Emma Wilson', color: '#fb7185' },
{ id: 'tech-2', name: 'Alex Chen', color: '#a78bfa' },
];
function App() {
return (
<div style={{ height: '600px' }}>
<Scheduler
appointments={appointments}
services={services}
technicians={technicians}
technicianServices={{ 'tech-1': ['classic-lashes', 'quick-touchup'], 'tech-2': ['classic-lashes'] }}
startHour={8}
endHour={21}
view="week"
detailDisplay="modal"
onSelectAppointment={(apt) => console.log('Selected:', apt)}
onNewAppointment={(data) => console.log('Create:', data)}
onRescheduleAppointment={(id, newTime) => console.log('Reschedule:', id, newTime)}
/>
</div>
);
}Documentation for your project
→ USAGE.md – Integration guide for using this package in another app. It includes:
- Data model –
Appointment,Service,Technician,Job,NewAppointmentData,Client,TechnicianServices - Styling – Importing CSS, CSS variables, dark mode
- Create appointment flow – Multiple jobs per appointment, handling
onNewAppointmentand persistingjobs - Props reference – All Scheduler props and callbacks
- TypeScript – Exported types
- Checklist – Steps to wire the scheduler into your backend
API overview
Main props
| Prop | Type | Description |
|------|------|-------------|
| appointments | Appointment[] | Appointments to display |
| services | Service[] or string[] | Bookable services (with duration for correct times) |
| technicians | Technician[] | Staff; optional, used in Create modal and block colors |
| technicianServices | Record<string, string[]> | Map tech ID → service IDs; filters technician dropdown by service |
| startHour / endHour | number | Grid hours (default 8–21) |
| view | 'day' \| 'week' | View mode |
| detailDisplay | 'modal' \| 'panel' | How details are shown |
| onNewAppointment | (data: NewAppointmentData) => void | Called when user creates an appointment (includes jobs[]) |
| onSelectAppointment | (apt: Appointment) => void | Click on appointment |
| onUpdateAppointment | (apt: Appointment) => void | User saved edits (includes updated jobs when present) |
| onDeleteAppointment | (id: string) => void | User deleted |
| onRescheduleAppointment | (id: string, newStart: Date) => void | After drag-and-drop |
Data shapes (summary)
- Appointment:
id,client: { name, path },jobs?,serviceType,artist?,startTime,duration,email,phone?,notes? - NewAppointmentData (from Create modal):
client,jobs: { serviceType, technicianId? }[],startTime,duration,email,phone?,notes? - Service:
id,name,category(string or{ id, name }),duration?(minutes) - Technician:
id,name,color?
Advanced usage
SSR (Next.js, Remix, etc.)
Use the scheduler in a client component and import the styles once:
'use client';
import { Scheduler } from 'react-appointment-scheduler';
import 'react-appointment-scheduler/styles.css';
export default function SchedulerPage() {
return (
<div style={{ height: '600px' }}>
<Scheduler appointments={appointments} services={services} />
</div>
);
}Theme (light/dark)
Set data-theme="dark" on the document root for dark mode. You can use the package helpers:
import { ThemeToggle, initializeTheme } from 'react-appointment-scheduler';
import { useEffect } from 'react';
useEffect(() => { initializeTheme(); }, []);
// Then render <ThemeToggle /> and <Scheduler {...props} />See THEME_DOCS.md for details.
Custom styling
Override CSS variables in your app (all prefixed with --scheduler-*):
:root {
--scheduler-bg-primary: #ffffff;
--scheduler-text-primary: #1c1917;
--scheduler-border-primary: #e7e5e4;
--scheduler-slot-height: 60px;
}Full list and dark-mode variables are in USAGE.md.
Sub-components and utilities
import {
DayView,
WeekView,
TimeGrid,
AppointmentBlock,
CreateAppointmentModal,
useScheduler,
useDragDrop,
formatTime,
formatFullDate,
} from 'react-appointment-scheduler';TypeScript
Types are exported for use in your app:
import type {
Appointment,
NewAppointmentData,
Job,
Service,
Technician,
TechnicianServices,
Client,
SchedulerProps,
ViewMode,
DetailDisplayMode,
} from 'react-appointment-scheduler';License
MIT
