Theme Customization Guide

DayFlow Calendar's appearance is controlled by a set of namespaced CSS custom properties (--df-color-*). All tokens are defined inside @layer df-theme, so host applications can override them without !important — regardless of whether they use Tailwind or plain CSS.

DayFlow's shared foundation CSS is the single source of truth for theme tokens, component primitives, and semantic helper classes such as df-fill-primary and df-focus-ring.

Table of Contents

Custom Calendar Type Colors

Basic Custom Colors

Define unique colors for each calendar type with separate light and dark variants:

const calendar = useCalendarApp({
  calendarTypes: [
    {
      id: 'personal',
      name: 'Personal',
      colors: {
        lineColor: '#0891b2', // cyan-600
        eventColor: '#cffafe', // cyan-100
        eventSelectedColor: '#a5f3fc', // cyan-200
        textColor: '#164e63', // cyan-900
      },
      darkColors: {
        lineColor: '#22d3ee', // cyan-400
        eventColor: '#164e63', // cyan-900
        eventSelectedColor: '#083344', // cyan-950
        textColor: '#cffafe', // cyan-100
      },
    },
  ],
});

Color Properties Explained

  • lineColor: Border and accent color (left bar on events)
  • eventColor: Event background fill
  • eventSelectedColor: Background fill when an event is selected
  • textColor: Text color for event title and time

Brand Color Integration

{
  id: 'brand',
  name: 'Brand Events',
  colors: {
    lineColor: '#6366f1',       // Brand indigo
    eventColor: '#e0e7ff', // Indigo-100
    eventSelectedColor: '#c7d2fe', // Indigo-200
    textColor: '#312e81',       // Indigo-900
  },
  darkColors: {
    lineColor: '#a5b4fc',       // Indigo-300
    eventColor: '#312e81', // Indigo-900
    eventSelectedColor: '#1e1b4b', // Indigo-950
    textColor: '#e0e7ff',       // Indigo-100
  },
}

Color Generation Helper

// utils/colorGenerator.ts
interface ColorSet {
  lineColor: string;
  eventColor: string;
  eventSelectedColor: string;
  textColor: string;
}

export function generateLightColors(baseColor: string): ColorSet {
  return {
    lineColor: baseColor,
    eventColor: lighten(baseColor, 0.9),
    eventSelectedColor: lighten(baseColor, 0.8),
    textColor: darken(baseColor, 0.4),
  };
}

export function generateDarkColors(baseColor: string): ColorSet {
  return {
    lineColor: lighten(baseColor, 0.3),
    eventColor: darken(baseColor, 0.6),
    eventSelectedColor: darken(baseColor, 0.7),
    textColor: lighten(baseColor, 0.8),
  };
}

CSS Variable Reference

All DayFlow theme tokens use the --df-color- prefix to avoid collisions with any host application variables.

VariablePurpose
--df-color-backgroundCalendar background
--df-color-foregroundPrimary text color
--df-color-hoverHover state background
--df-color-borderBorders and dividers
--df-color-cardCard / panel background
--df-color-card-foregroundCard text color
--df-color-mutedSubtle background areas
--df-color-muted-foregroundMuted / secondary text
--df-color-primaryPrimary accent (buttons, selected states)
--df-color-primary-foregroundText on primary-colored backgrounds
--df-color-secondarySecondary accent
--df-color-secondary-foregroundText on secondary-colored backgrounds
--df-color-destructiveDestructive actions
--df-color-destructive-foregroundText on destructive backgrounds

Semantic Helper Classes

In addition to CSS variables, DayFlow now exposes theme-aware semantic helper classes. These are useful when you render custom content inside slots, plugin UI, or wrappers that should visually match the built-in controls.

Class NameMeaning
df-fill-primaryPrimary filled surface with automatic foreground text
df-fill-secondarySecondary filled surface with automatic foreground text
df-fill-destructiveDestructive filled surface with automatic foreground text
df-tint-primarySubtle primary selection tint
df-hover-primaryPrimary-themed hover state
df-hover-primary-solidHover state for filled primary buttons
df-text-primaryPrimary text color
df-border-primaryPrimary border color
df-ring-primaryPrimary ring color token
df-focus-ringFocus helper that applies both primary border and ring

Prefer these df-* helpers or --df-color-* overrides when styling DayFlow. Avoid depending on old internal Tailwind semantic names such as bg-primary, text-primary, or hover:bg-primary/90.

Override Methods

Method 1 — Container-level override (works everywhere)

Set variables directly on .df-calendar-container. Because this rule is outside any @layer, it always wins over the library's defaults regardless of Tailwind version or CSS setup.

In practice, you will often want to target both .df-calendar-container and .df-portal:

  • .df-calendar-container is the root container for the visible calendar surface
  • .df-portal is the root class DayFlow uses for floating UI rendered via portals into document.body, such as dialogs, dropdowns, and some picker panels

If you only override .df-calendar-container, the main calendar can pick up your theme while portal-based overlays may still use the default tokens.

/* styles/globals.css */
.df-calendar-container,
.df-portal {
  --df-color-primary: #6366f1;
  --df-color-background: #f9fafb;
  --df-color-border: #e0e7ff;
}

/* Dark mode — target the container when the .dark class is on an ancestor */
.dark .df-calendar-container,
.dark .df-portal {
  --df-color-primary: #a5b4fc;
  --df-color-background: #1e1e2e;
  --df-color-border: #312e81;
}

This is the recommended approach for most projects. The variables are scoped to the calendar and do not affect anything outside it.

Tailwind v4 Integration

Tailwind v4 is configured entirely through CSS — there is no tailwind.config.js. DayFlow's distributed CSS already includes the shared foundation layer, so theme tokens and semantic helper classes are available immediately after import.

Choosing the right CSS file

DayFlow ships two CSS bundles:

FileContentsUse when
styles.cssFull bundle including Tailwind preflight (CSS reset)Not using Tailwind
styles.components.cssComponent styles only, no CSS resetAlready using Tailwind

Minimal setup

/* app.css — for Tailwind projects */
@import '@dayflow/core/dist/styles.components.css';
@import 'tailwindcss';

If your project does not use Tailwind, import the full bundle instead:

/* app.css — for non-Tailwind projects */
@import '@dayflow/core/dist/styles.css';

Dark mode

DayFlow respects the .dark class on any ancestor element (including <html>). Apply it with JavaScript:

document.documentElement.classList.toggle('dark', isDark);

System-preference dark mode (no explicit class) is also supported automatically.

Using theme.mode with Tailwind v4

DayFlow's distributed CSS already includes the .dark variant it needs for theme.mode. In Tailwind v4 projects, importing @dayflow/core/dist/styles.components.css is enough for DayFlow itself to respond to the .dark class on <html>.

If you also want your app's own Tailwind dark: utilities to follow the same class toggle, add the class-based variant in your CSS entry:

@import '@dayflow/core/dist/styles.components.css';
@import 'tailwindcss';

/* Optional: only needed for your app's own Tailwind dark: utilities */
@variant dark (.dark &);

Without this extra line, DayFlow still switches correctly via theme.mode; only your own Tailwind dark: utilities stay on Tailwind's default media-query behavior.

Practical recommendation

For most apps, use this order of precedence:

  1. Override --df-color-* tokens on .df-calendar-container, .df-portal, or your own wrapper.
  2. Reuse DayFlow's semantic helpers such as df-fill-primary and df-focus-ring in custom slot/plugin markup.
  3. Only reach for low-level utility overrides when you are changing layout rather than theme.

Applying overrides with @theme

@import '@dayflow/core/dist/styles.css' layer(dayflow);
@import 'tailwindcss';

@theme {
  --df-color-primary: #6366f1;
  --df-color-primary-foreground: #ffffff;
  --df-color-secondary: #8b5cf6;
  --df-color-secondary-foreground: #ffffff;
}

Wrapping the calendar with Tailwind utilities

function ThemedCalendar({ calendar }) {
  return (
    <div className='rounded-2xl shadow-xl ring-1 ring-gray-200 dark:ring-gray-700'>
      <DayFlowCalendar calendar={calendar} />
    </div>
  );
}

Creating a Custom Theme

// themes/oceanTheme.ts
export const oceanTheme = {
  mode: 'light' as const,
  calendarTypes: [
    {
      id: 'deep-ocean',
      name: 'Deep Ocean',
      colors: {
        lineColor: '#0369a1',
        eventColor: '#e0f2fe',
        eventSelectedColor: '#bae6fd',
        textColor: '#0c4a6e',
      },
      darkColors: {
        lineColor: '#7dd3fc',
        eventColor: '#0c4a6e',
        eventSelectedColor: '#083344',
        textColor: '#e0f2fe',
      },
    },
    {
      id: 'coral-reef',
      name: 'Coral Reef',
      colors: {
        lineColor: '#ea580c',
        eventColor: '#ffedd5',
        eventSelectedColor: '#fed7aa',
        textColor: '#7c2d12',
      },
      darkColors: {
        lineColor: '#fb923c',
        eventColor: '#7c2d12',
        eventSelectedColor: '#431407',
        textColor: '#ffedd5',
      },
    },
  ],
};

Pair it with CSS variable overrides for full visual consistency:

/* Ocean theme CSS tokens */
.df-calendar-container {
  --df-color-primary: #0369a1;
  --df-color-background: #f0f9ff;
  --df-color-border: #bae6fd;
}

.dark .df-calendar-container {
  --df-color-primary: #7dd3fc;
  --df-color-background: #0c1220;
  --df-color-border: #0c4a6e;
}

Resources

Tools

Libraries

Tailwind Resources

On this page