Theme Customization
The scheduler's appearance comes from a set of namespaced CSS custom properties (--df-color-*). They are declared inside @layer df-theme, which sits below your application styles in the cascade, so overriding them never needs !important.
The pattern is always the same: pick a selector that scopes to the scheduler, then redeclare the tokens you want to change.
Scoping Selectors
Each adapter applies its own root class, and portaled UI lives outside all of them:
| Selector | Covers |
|---|---|
.df-scheduler-react | The React scheduler surface. |
.df-scheduler-vue | The Vue scheduler surface. |
.df-scheduler-angular | The Angular scheduler surface. |
.df-scheduler-svelte | The Svelte scheduler surface. |
.df-portal | Dialogs, context menus, and tooltips rendered into document.body. |
Always include .df-portal alongside your adapter's class, or menus and dialogs will keep the default palette.
CSS Variable Reference
| Variable | Purpose |
|---|---|
--df-color-background | Scheduler background |
--df-color-foreground | Primary text color |
--df-color-hover | Hover state background |
--df-color-border | Borders and dividers |
--df-color-card | Card / panel background |
--df-color-card-foreground | Card text color |
--df-color-muted | Subtle background areas |
--df-color-muted-foreground | Muted / secondary text |
--df-color-primary | Primary accent (buttons, selected states) |
--df-color-primary-foreground | Text on primary-colored backgrounds |
--df-color-secondary | Secondary accent |
--df-color-secondary-foreground | Text on secondary-colored backgrounds |
--df-color-destructive | Destructive actions |
--df-color-destructive-foreground | Text on destructive backgrounds |
Applying Overrides
.df-scheduler-react,
.df-portal {
--df-color-primary: #6366f1;
--df-color-background: #f9fafb;
--df-color-border: #e0e7ff;
}
.dark .df-scheduler-react,
.dark .df-portal {
--df-color-primary: #a5b4fc;
--df-color-background: #1e1e2e;
--df-color-border: #312e81;
}Dark values belong under a .dark ancestor because that is the selector the built-in dark tokens use. See Dark Mode.
Creating a Named Theme
Collect a full palette in one file and import it where you mount the scheduler:
.df-scheduler-react,
.df-portal {
--df-color-primary: #0369a1;
--df-color-background: #f0f9ff;
--df-color-border: #bae6fd;
--df-color-hover: #e0f2fe;
}
.dark .df-scheduler-react,
.dark .df-portal {
--df-color-primary: #7dd3fc;
--df-color-background: #0c1220;
--df-color-border: #0c4a6e;
--df-color-hover: #082f49;
}import './themes/ocean.css';Semantic Helper Classes
When you write markup inside a slot or a custom renderer, use these classes instead of hard-coded colors, as they read the same tokens and therefore follow the active theme:
| Class | Meaning |
|---|---|
df-fill-primary | Primary filled surface with automatic foreground text |
df-fill-secondary | Secondary filled surface with automatic foreground text |
df-fill-destructive | Destructive filled surface with automatic foreground text |
df-tint-primary | Subtle primary selection tint |
df-hover-primary | Primary-themed hover state |
df-hover-primary-solid | Hover state for filled primary buttons |
df-text-primary | Primary text color |
df-border-primary | Primary border color |
df-ring-primary | Primary ring color token |
df-focus-ring | Focus helper applying both primary border and ring |
Avoid depending on the scheduler's internal Tailwind semantic names such as bg-primary or hover:bg-primary/90, as those are implementation details and can change.
Tailwind v4 Integration
Tailwind v4 is configured entirely in CSS. The scheduler's distributed stylesheet already contains the shared foundation layer.
Choose the Right Stylesheet
| File | Contents | Use when |
|---|---|---|
styles.css | Full bundle, including a CSS reset | Not using Tailwind |
styles.components.css | Component styles only, no reset | Already using Tailwind |
@import '@dayflow-scheduler/core/dist/styles.components.css';
@import 'tailwindcss';@import '@dayflow-scheduler/core/dist/styles.css';Dark Mode with Tailwind
The scheduler already responds to a .dark ancestor. To make your own dark: utilities follow the same toggle, declare the variant:
@import '@dayflow-scheduler/core/dist/styles.components.css';
@import 'tailwindcss';
/* Only needed for your app's own Tailwind dark: utilities */
@variant dark (.dark &);document.documentElement.classList.toggle('dark', isDark);Overriding Tokens with @theme
@import '@dayflow-scheduler/core/dist/styles.components.css'
layer(dayflow-scheduler);
@import 'tailwindcss';
@theme {
--df-color-primary: #6366f1;
--df-color-primary-foreground: #ffffff;
--df-color-secondary: #8b5cf6;
--df-color-secondary-foreground: #ffffff;
}Resource and Event Colors
Theme tokens control chrome. The colors of the schedule content itself come from the data:
const app = useSchedulerApp({
resources: [
{ id: 'eng', name: 'Engineering', color: '#3b82f6' },
{ id: 'design', name: 'Design', color: '#8b5cf6' },
],
});Resources also accept a full style object with a darkColors variant, and individual events can override both. See Events.
Troubleshooting
Overrides apply to the grid but not to menus. Add .df-portal to your selector list.
Nothing changes at all. Confirm the selector matches your adapter's root class: a Vue app needs .df-scheduler-vue, not .df-scheduler-react.
The scheduler looks unstyled or double-reset. You are probably importing both styles.css and styles.components.css. Import exactly one.
Related Documentation
- Dark Mode: theme modes and the
.darkclass. - Events: event-level colors, variants, and style specs.
- Content Slots: where the semantic helper classes are most useful.