react-availability-grid
v0.1.2
Published
React component for selecting time availability across multiple days. Perfect for meeting schedulers and booking systems.
Downloads
289
Maintainers
Readme
react-availability-grid
A React component for selecting time availability across multiple days. Perfect for building meeting schedulers, booking systems, and "when are you free?" tools.
Features
- Drag to select - Click and drag to quickly select multiple time slots
- Lightweight - Small bundle size (13KB gzipped)
- Fully accessible - ARIA support and complete keyboard navigation
- Easy to customize - Style with CSS variables or custom classes
- TypeScript ready - Full type definitions included
- Flexible configuration - Set intervals, date ranges, and disabled times
- Modern React - Built with hooks, works with React 16.8+
Installation
npm install react-availability-grid dayjs react react-domor
yarn add react-availability-grid dayjs react react-domQuick Start
import { useState } from 'react';
import { TimeGrid } from 'react-availability-grid';
import type { Dayjs } from 'react-availability-grid';
import 'react-availability-grid/styles.css';
import dayjs from 'dayjs';
function App() {
const [selection, setSelection] = useState<Dayjs[]>([]);
return (
<TimeGrid
selection={selection}
setSelection={setSelection}
startDate={dayjs()}
endDate={dayjs().add(2, 'weeks')}
earliestStart={dayjs().hour(9).minute(0)}
latestEnd={dayjs().hour(17).minute(0)}
/>
);
}Props API
Required Props
| Prop | Type | Description |
|------|------|-------------|
| selection | Dayjs[] | Array of selected time slots |
| setSelection | (selection: Dayjs[] \| ((prev: Dayjs[]) => Dayjs[])) => void | Function to update selection |
| startDate | Dayjs | First day to display in the grid |
| endDate | Dayjs | Last day to display in the grid |
| earliestStart | Dayjs | Earliest time of day to show (e.g., 9:00 AM) |
| latestEnd | Dayjs | Latest time of day to show (e.g., 5:00 PM) |
Optional Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| intervalSize | number | 60 | Size of each time slot in minutes |
| allowedTimes | Dayjs[] | undefined | Whitelist of allowed time slots. If omitted, all future times are allowed. Must be memoized to avoid re-renders. |
| onSelectionChange | (selection: Dayjs[]) => void | undefined | Callback fired when selection changes |
| className | string | undefined | Additional CSS class for the grid container |
| style | React.CSSProperties | undefined | Inline styles for the grid container |
Usage Examples
Basic Weekly Schedule
import { TimeGrid } from 'react-availability-grid';
import dayjs from 'dayjs';
function WeeklySchedule() {
const [availability, setAvailability] = useState<Dayjs[]>([]);
return (
<TimeGrid
selection={availability}
setSelection={setAvailability}
startDate={dayjs().startOf('week')}
endDate={dayjs().endOf('week')}
earliestStart={dayjs().hour(9).minute(0)}
latestEnd={dayjs().hour(17).minute(0)}
intervalSize={60}
/>
);
}30-Minute Intervals
<TimeGrid
selection={selection}
setSelection={setSelection}
startDate={dayjs()}
endDate={dayjs().add(7, 'days')}
earliestStart={dayjs().hour(8).minute(0)}
latestEnd={dayjs().hour(20).minute(0)}
intervalSize={30}
/>With Selection Callback
<TimeGrid
selection={selection}
setSelection={setSelection}
startDate={dayjs()}
endDate={dayjs().add(1, 'week')}
earliestStart={dayjs().hour(9).minute(0)}
latestEnd={dayjs().hour(17).minute(0)}
onSelectionChange={(newSelection) => {
console.log(`Selected ${newSelection.length} time slots`);
// Send to analytics, update UI, etc.
}}
/>Custom Styling
<TimeGrid
selection={selection}
setSelection={setSelection}
startDate={dayjs()}
endDate={dayjs().add(1, 'week')}
earliestStart={dayjs().hour(9).minute(0)}
latestEnd={dayjs().hour(17).minute(0)}
className="my-custom-grid"
style={{ maxWidth: '900px', margin: '0 auto' }}
/>Restrict Available Times
import { useMemo } from 'react';
function MyScheduler() {
const [selection, setSelection] = useState<Dayjs[]>([]);
// IMPORTANT: Memoize allowedTimes to prevent unnecessary re-renders
const businessHours = useMemo(() => {
const times: Dayjs[] = [];
let current = dayjs().startOf('week').add(1, 'day'); // Monday
while (current.isBefore(dayjs().endOf('week'))) {
if (current.day() !== 0 && current.day() !== 6) { // Skip weekends
for (let hour = 9; hour < 17; hour++) {
times.push(current.hour(hour).minute(0).second(0).millisecond(0));
}
}
current = current.add(1, 'day');
}
return times;
}, []); // Recalculate if date range changes
return (
<TimeGrid
selection={selection}
setSelection={setSelection}
startDate={dayjs().startOf('week')}
endDate={dayjs().endOf('week')}
earliestStart={dayjs().hour(9).minute(0)}
latestEnd={dayjs().hour(17).minute(0)}
allowedTimes={businessHours}
/>
);
}Styling & Theming
The component uses CSS variables for easy theming. Import the CSS file and override variables as needed:
:root {
--timegrid-cell-bg: #f0f0f0;
--timegrid-cell-selected-bg: #346dee5e;
--timegrid-cell-disabled-color: #c5c5c5ad;
--timegrid-cell-border-color: #fff;
--timegrid-cell-text-color: #2f2f2fad;
--timegrid-day-bg: #f0f0f0;
--timegrid-day-number-color: #156ff7;
--timegrid-weekend-bg: #dedee2;
--timegrid-border-radius: 4px;
--timegrid-cell-width: 50px;
--timegrid-cell-height: 25px;
--timegrid-day-height: 60px;
}Custom Theme Example
/* Dark theme */
:root {
--timegrid-cell-bg: #2a2a2a;
--timegrid-cell-selected-bg: #4a9eff;
--timegrid-cell-border-color: #1a1a1a;
--timegrid-cell-text-color: #e0e0e0;
--timegrid-day-bg: #333;
--timegrid-weekend-bg: #252525;
}Accessibility
TimeGrid is built with accessibility in mind:
- ARIA Roles: Grid uses proper
role="grid",role="row",role="gridcell", androle="columnheader"attributes - Screen Reader Support: All cells have descriptive
aria-labelattributes announcing the day, time, and selection state - Keyboard Navigation:
- Tab: Focus cells in sequential order
- Arrow Keys: Navigate between cells (Up/Down for hours, Left/Right for days)
- Space/Enter: Toggle selection of focused cell
- Focus Management: Visual focus indicators and proper
tabIndexmanagement
Browser Support
Works in all modern browsers that support:
- ES6+
- React 16.8+ (Hooks)
- CSS Grid
- CSS Custom Properties
Tested in:
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
TypeScript
Full TypeScript support included. Import types as needed:
import type { TimeGridProps, Dayjs } from 'react-availability-grid';
const props: TimeGridProps = {
selection: [],
setSelection: () => {},
startDate: dayjs(),
endDate: dayjs().add(1, 'week'),
earliestStart: dayjs().hour(9).minute(0),
latestEnd: dayjs().hour(17).minute(0),
};Development
# Install dependencies
npm install
# Start development server
npm start
# Build library
npm run build:lib
# Run tests
npm testLicense
MIT
