Theming
All colours come from CSS variables named --rs-*. Override them on :root, or on any ancestor of the scheduler.
:root { --rs-primary: #7c3aed; /* focus, today's date, selection and drag footprint */ --rs-accent: #ede9fe; /* hover in the toolbar and menus */ --rs-today: #f8f6ff; /* today's column */ --rs-border: #d1d5db;}Popovers render in a portal outside the scheduler, so put overrides on :root (or on body) rather than on a wrapper.
Dark mode
Section titled “Dark mode”Three ways, all setting the same dark tokens:
<html class="dark"> <!-- class, as in shadcn and Tailwind --><html data-theme="dark"> <!-- explicit attribute --><html data-theme="system"> <!-- follows prefers-color-scheme -->Any ancestor works, not only html. Popovers render in a portal outside the scheduler, so put the class or attribute on html or body if you want them themed too. data-theme="system" is in the npm stylesheet only; the shadcn install keeps just .dark (shadcn cannot express a media query on an attribute), so there you toggle the class yourself. Your own event colours are yours to adapt.
Radius and spacing
Section titled “Radius and spacing”--rs-radius (default 0.75rem) is the corner radius of the outer frame. Spacing is not a free variable: row and event sizes come from density, because the layout maths needs the real pixel heights.
Tokens
Section titled “Tokens”| Variable | Used for |
|---|---|
--rs-background, --rs-foreground |
Base surfaces and text |
--rs-surface, --rs-surface-muted, --rs-surface-hover |
Grid, header and hover backgrounds |
--rs-muted, --rs-muted-foreground |
The header band, group rows and secondary text |
--rs-today |
Today’s column (week and longer views) |
--rs-primary, --rs-ring |
Focus ring, the cursor, today’s date, and a tint of it for selections and the drag footprint. It is also small text and a pill background, so it should reach 4.5:1 against white (or against --rs-primary-foreground) |
--rs-primary-text-mix |
How much of the primary is kept where it is text (100%; 60% in dark mode, mixed toward the foreground so it stays readable) |
--rs-accent |
Hover in the toolbar and menus |
--rs-unavailable |
The hatching on unavailable time |
--rs-warning |
Utilization bars at 90% and over |
--rs-destructive |
Rejected places, utilization over 100% and the now line |
--rs-border, --rs-input |
Lines and inputs |
--rs-popover, --rs-popover-foreground |
Event details popover |
--rs-radius |
Corner radius of the outer frame |
--rs-shadow-xs, --rs-shadow-sm, --rs-shadow, --rs-shadow-md |
Elevation |
Every surface and text colour in the grid reads from these tokens, so a dark theme is just a second set of values. The demo above is one.
It does not leak
Section titled “It does not leak”The stylesheet has no global reset and no body or html rules. Base styles are scoped to the class rs-root, and the variables are prefixed so they cannot clash with your own --background or --primary. This holds for the shadcn install too.
Classes for the main parts
Section titled “Classes for the main parts”Tokens change colours everywhere. To restyle one part, pass classNames:
<ResourceScheduler resources={resources} classNames={{ toolbar: "border-b-2", dateHeader: "uppercase tracking-wide", resourceCell: "text-start font-semibold", groupHeader: "bg-slate-100", slot: "border-dashed", event: "rounded-none shadow-md", }}/>| Part | What it styles |
|---|---|
root |
The outer element (.rs-root) |
toolbar |
The bar with the date, arrows, Today and the view select |
dateHeader |
Each column header: an hour in the day view, a day in the others |
resourceCell |
The cell in the left column with a resource’s name |
groupHeader |
A group header in the left column |
slot |
Each empty slot of the grid |
event |
The default event card (not one you draw with renderTimeSlot) |
Your classes are merged after the defaults with tailwind-merge, so a utility that conflicts with a default replaces it: rounded-none removes the card’s rounded. Without classNames the output is exactly what it was.
The utilities have to exist in your CSS. The npm package ships a precompiled stylesheet with only the utilities it uses, so a class like bg-slate-100 works only if your own Tailwind build generates it. If it does not, the conflicting default is still removed and the part loses that style. With the shadcn install the source is in your project, so Tailwind sees the class. Plain CSS class names work in both: add the class, then write the rule yourself (and avoid a conflicting Tailwind utility if you want the default to stay).
Density
Section titled “Density”density="compact" makes rows shorter so more resources fit on screen:
<ResourceScheduler resources={resources} density="compact" />A lane of events is 38 px instead of 52, the event card is 34 px instead of 48, and the card shows its title and time on one line (the time is cut first when the card is narrow). Resource names get less padding. A row with a utilization bar is never shorter than 60 px, because the name and the bar need that much, so compact saves the most on rows with several lanes of events.
The default is "comfortable", which is exactly what the scheduler looked like before the option existed.
Custom rendering
Section titled “Custom rendering”To replace whole parts (the toolbar, the event card, the popover, the headers) with your own components, use components. The older render props still work: renderEventPopover, renderTimeSlot (replace the event card), renderResourceHeader, renderDateHeader and renderEmptyCell. See the props reference.