CourseKitFrontend
Components
Pre-styled schedule components — TimetableGrid, EventCard, ConflictBadge, AvailabilityOverlay
TimetableGrid
A week/day grid view with configurable time axis and custom event rendering.
import { TimetableGrid } from '@hfu.digital/coursekit-react';Props
interface TimetableGridProps {
weekStart: string;
startHour?: number; // default: 8
endHour?: number; // default: 20
days?: string[]; // default: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
events?: TimetableGridEvent[];
renderEvent?: (event: TimetableGridEvent) => ReactNode;
hourHeight?: number; // default: 60 (pixels per hour)
className?: string;
}| Prop | Type | Default | Description |
|---|---|---|---|
weekStart | string | — | ISO date of the first day (Monday) |
startHour | number | 8 | First hour displayed on the time axis |
endHour | number | 20 | Last hour displayed on the time axis |
days | string[] | ['Mon'..'Fri'] | Day labels for columns |
events | TimetableGridEvent[] | [] | Events to render on the grid |
renderEvent | function | — | Custom event renderer (overrides default block) |
hourHeight | number | 60 | Pixel height per hour row |
className | string | — | CSS class (disables built-in styles) |
TimetableGridEvent
interface TimetableGridEvent {
id: string;
title: string;
startTime: string;
durationMin: number;
dayIndex: number; // 0-based index into the days array
}Example
<TimetableGrid
weekStart="2026-03-02"
startHour={8}
endHour={18}
events={[
{ id: '1', title: 'Math 101', startTime: '2026-03-02T09:00:00', durationMin: 90, dayIndex: 0 },
{ id: '2', title: 'Physics', startTime: '2026-03-03T14:00:00', durationMin: 60, dayIndex: 1 },
]}
/>Custom Rendering
<TimetableGrid
weekStart="2026-03-02"
events={events}
renderEvent={(event) => (
<div className="my-event-card">
<strong>{event.title}</strong>
<span>{event.durationMin}min</span>
</div>
)}
/>When className is provided, all built-in inline styles are disabled so you can style the grid entirely with CSS.
EventCard
Displays a single event with visual styling for exceptions.
import { EventCard } from '@hfu.digital/coursekit-react';Props
interface EventCardProps {
title: string;
startTime: string;
durationMin: number;
room?: string | null;
instructor?: string | null;
isException?: boolean;
exceptionType?: 'cancelled' | 'modified' | 'added' | null;
className?: string;
children?: ReactNode;
onClick?: () => void;
}Exception Styling
| Exception Type | Visual Treatment |
|---|---|
cancelled | Reduced opacity, strikethrough, red background |
modified | Yellow background with amber border |
added | Green background with green border |
Example
<EventCard
title="Math 101"
startTime="2026-03-02T09:00:00"
durationMin={90}
room="Room A1"
instructor="Prof. Smith"
isException={true}
exceptionType="modified"
onClick={() => console.log('Card clicked')}
/>ConflictBadge
An inline badge that displays a conflict message with severity-based styling.
import { ConflictBadge } from '@hfu.digital/coursekit-react';Props
interface ConflictBadgeProps {
severity: 'error' | 'warning';
message: string;
type?: string;
className?: string;
}| Severity | Visual Treatment |
|---|---|
error | Red background, red text |
warning | Yellow background, amber text |
Example
<ConflictBadge
severity="error"
message="Room A1 has overlapping events"
type="room-overlap"
/>AvailabilityOverlay
Renders colored overlays on the timetable grid to show availability blocks.
import { AvailabilityOverlay } from '@hfu.digital/coursekit-react';Props
interface AvailabilityOverlayProps {
blocks: AvailabilityBlock[];
startHour?: number; // must match TimetableGrid (default: 8)
hourHeight?: number; // must match TimetableGrid (default: 60)
dayCount?: number; // must match TimetableGrid (default: 5)
className?: string;
}AvailabilityBlock
interface AvailabilityBlock {
startTime: string;
endTime: string;
dayIndex: number;
type: 'available' | 'blocked' | 'preferred';
hardness: 'hard' | 'soft';
}Color Scheme
| Type + Hardness | Color |
|---|---|
blocked-hard | Strong red overlay |
blocked-soft | Light red overlay |
available-hard | Green overlay |
available-soft | Light green overlay |
preferred-hard | Blue overlay |
preferred-soft | Light blue overlay |
Example
<div style={{ position: 'relative' }}>
<TimetableGrid weekStart="2026-03-02" />
<AvailabilityOverlay
blocks={[
{
startTime: '2026-03-02T12:00:00',
endTime: '2026-03-02T13:00:00',
dayIndex: 0,
type: 'blocked',
hardness: 'hard',
},
]}
/>
</div>The overlay is positioned absolutely and uses pointerEvents: 'none' so it doesn't interfere with click events on the grid.