Theming and customization
Use optional themes or style Calix with your own system.
Calix has no styling dependency. The built-in components expose stable class names and state attributes, so plain CSS, CSS Modules, Tailwind, CSS-in-JS, and design-system wrappers can all target the same markup.
Optional themes
Built-in components use the dark theme by default. Pass theme="light" to a
calendar, date picker, or time field for the light variant. The theme also
responds to prefers-contrast: more.
CSS variables
The provided themes are CSS-variable based. Override a variable in your app to match your design system:
Common tokens include --calix-accent, --calix-on-accent, --calix-surface,
--calix-surface-raised, --calix-text, --calix-muted, --calix-border,
--calix-hover, --calix-radius, --calix-radius-sm, --calix-cell-size,
--calix-gap, --calix-font, and --calix-transition. The default accent
remains #8b7cff.
For component states and layout, use --calix-focus-ring,
--calix-disabled-opacity, --calix-weekend, --calix-outside-month,
--calix-selected-shadow, --calix-calendar-padding, and
--calix-popover-z-index.
--calix-font is inherited by Calendar, a DatePicker popover (including
its time-selection step), and standalone TimeField. Load the font in your app
as usual, then set this token.
Common recipes
Set tokens globally in :root to theme every picker. To theme one picker,
attach the same class to its rendered root: use classNames.root for
Calendar, classNames.popover for DatePicker, and className for
TimeField. A DatePicker popover is portalled, so styling the input wrapper
alone will not affect it.
Keep focus indicators visible when overriding --calix-focus-ring, and let
the built-in prefers-reduced-motion rule disable non-essential motion.
State contract
Day buttons carry the following attributes when their state is active:
| Attribute | Meaning |
|---|---|
data-selected | The day is selected. |
data-today | The day is today. |
data-disabled | The day cannot be selected. |
data-outside-month | The day belongs to an adjacent month. |
data-range-start / data-range-end | A range boundary. |
data-in-range | A day inside a selected or previewed range. |
data-focused | The roving-focus day. |
data-weekend | Saturday or Sunday. |
data-holiday | A named holiday is visible on the day. |
data-holiday-name | The visible holiday's name. |
The default theme marks holidays and shows their name on hover. Target these attributes to replace that presentation; see Holidays for the data contract.
Slot class names
Pass classNames to Calendar or DatePicker to add classes to every
built-in calendar slot: root, header, heading, navButton, months,
grid, weekdays, weekday, week, day, footer, footerButton,
presets, preset, picker, pickerBody, month, and year. DatePicker
also exposes popover, field, input, toggle, clear, dateTime,
timeStep, timeBack, timeTitle, and timeActions.
Use DatePicker's extra slots to target the field and time flow without
replacing their markup:
Custom content and layout
Use renderDay to replace a day's content without reimplementing selection or
accessibility. header and footer accept either a node or a callback which
receives the complete useCalendar API, so custom titles and buttons retain the
built-in navigation and selection behavior.
For markup beyond the calendar, compose DatePicker.Root, .Trigger, .Input,
and .Content, or render from useCalendar. See Hooks.