PersonalizaciónSe aplica aLite y Pro
Temas, tokens, Tailwind y modo oscuro
Importa la hoja de estilos una vez: vive en @layer super-scheduler con selectores de especificidad cero, así que tu CSS sin capa gana sin !important. Personalízalo con tokens --super-scheduler-*; los tokens de componente funcionan en cualquier sitio, pero la familia del acento debe fijarse en :root y .dark (para todo el sitio, con el colorScheme por defecto, 'inherit') o en la raíz del control con un colorScheme explícito. Por defecto, el modo oscuro sigue una clase .dark o un atributo data-theme de un ancestro, y solo sigue al sistema operativo con colorScheme: 'auto'.
SuperScheduler se estiliza por completo mediante propiedades CSS personalizadas, clases y atributos de datos. Puedes adaptarlo a tu producto sin hacer un fork de la hoja de estilos y sin !important. Esta guía describe el contrato, las recetas que llegan con fiabilidad a todos los colores, el modo oscuro, las clases por slot, la densidad, el modo sin estilos y Tailwind. Casi todo se aplica a Pro; la última sección trata Lite.
El contrato CSS
Importa la hoja de estilos una sola vez, junto al CSS de tu aplicación:
@import 'super-scheduler/styles.css';(Con un bundler también puedes escribir import 'super-scheduler/styles.css' en un módulo). El archivo es un único bloque @layer super-scheduler de selectores :where() de especificidad cero. Cualquier regla tuya sin capa gana sobre él, sea cual sea su especificidad.
| Superficie | Selector o prefijo |
|---|---|
| Raíz | .super-scheduler, con data-color-scheme, data-density, data-lod y data-unstyled |
| Partes | Clases .super-scheduler__* (__event, __event-inner, __event-bar, __cell, __row-header-cell, __link, ...) |
| Marcadores de parte | [data-super-scheduler-part="event"], "cell", "event-meta", "now-line", "minimap", "pane", ... |
| Estado | data-selected, data-hovered, data-dragging, data-conflict, data-today, data-weekend, data-disabled, data-expanded, ... |
| Contenido React | data-super-scheduler-slot, data-super-scheduler-slot-ready, data-super-scheduler-fallback |
| Tokens | --super-scheduler-* |
No dependas de los nombres de los archivos de chunks ni de identificadores generados. Los tokens de geometría como --super-scheduler-cell-width, -row-height y -row-header-width los escribe el motor: cambia los tamaños mediante opciones (cellWidth, eventHeight, rowHeaderWidth), no con CSS.
Tokens
Hay tres tipos de tokens, y el lugar donde se declaran decide dónde puedes sobrescribirlos.
- Primitivos, declarados en
:root:--super-scheduler-white, deneutral-50aneutral-950, deaccent-50aaccent-950,danger-400/600,warning-400/600,success-400/600,duration,ease,ease-spring. - Tokens semánticos, declarados para cada esquema (los valores claros en
:rooty en los ámbitos claros, los oscuros en.dark,[data-theme="dark"]y[data-color-scheme="dark"]):
| Grupo | Tokens (todos con el prefijo --super-scheduler-) |
|---|---|
| Superficies y texto | surface, surface-raised, text, text-muted, on-accent |
| Líneas | border, border-strong, grid-line, grid-break, row-line |
| Acento | accent-rgb, accent, accent-emphasis, accent-soft, accent-text, accent-border |
| Estados | danger, danger-soft, warning, warning-soft, success |
| Sombreado del calendario | today-bg, weekend-bg, non-business-bg, group, group-row, hatch |
| Interacción | hover-row, hover-cell, selection, selection-border, focus-ring, micro-bar, duration-bar |
| Superposiciones y carga | overlay, overlay-text, overlay-muted, overlay-subtle, overlay-border, skeleton-base, skeleton-highlight, de shadow-1 a shadow-3 |
- Tokens de componente, que nunca se declaran: se leen con un valor de reserva allí donde se usan, así que puedes fijarlos en cualquier ancestro. Por ejemplo:
--super-scheduler-radius,-event-radius,-event-padding,-event-bg,-event-text,-event-border,-event-bar,-link,-link-hover,-now-line,-handle-target,-hover-*,-minimap-*,-pane-splitter,-zoom-hud-bg.
Recetas de personalización que funcionan
Como los tokens semánticos se declaran por esquema, y algunos se vuelven a declarar en la raíz del control, no todas las sobrescrituras llegan a todos los tonos. Estas cuatro recetas se han comprobado en el navegador con la hoja de estilos de la 0.1.0.
Tokens de componente en cualquier sitio
Los tokens de componente funcionan en cualquier ancestro y con cualquier modo de esquema de color:
.planning {
--super-scheduler-radius: 8px;
--super-scheduler-event-radius: 6px;
--super-scheduler-event-padding: 2px 6px;
--super-scheduler-link: #8b5cf6;
--super-scheduler-now-line: #e11d48;
}Colores neutros en un elemento envolvente
Con el valor por defecto colorScheme: 'inherit', la mayoría de los tokens semánticos se pueden sobrescribir en un elemento envolvente: superficies, texto, líneas, sombreados y tonos de selección.
.planning {
--super-scheduler-surface: #fbfaf7;
--super-scheduler-border: #e6e1d6;
--super-scheduler-weekend-bg: rgb(120 100 60 / 0.05);
}
.dark .planning {
--super-scheduler-surface: #16140f;
--super-scheduler-border: rgb(255 255 255 / 0.08);
}Dos límites: con un colorScheme explícito ('light', 'dark' o 'auto'), la raíz del control declara ella misma los tokens semánticos y un elemento envolvente ya no llega a ellos (usa la última receta). Además, accent, duration-bar, grid-break, hatch, overlay-text, overlay-muted, overlay-subtle y el color de la barra de scroll se declaran siempre en la raíz.
Un acento de marca para todo el sitio
La familia del acento se calcula a partir de un token de canales, --super-scheduler-accent-rgb (tres números separados por espacios), más algunos primitivos para los rellenos suaves y el texto. Decláralos sin capa en :root y en el ámbito oscuro que use tu sitio:
:root {
--super-scheduler-accent-rgb: 10 140 80;
--super-scheduler-accent-100: #e0f2e9; /* accent-soft: event fills */
--super-scheduler-accent-200: #c9e6d6; /* border in light mode */
--super-scheduler-accent-800: #04361f; /* accent-text, accent-emphasis */
}
:root.dark {
--super-scheduler-accent-rgb: 80 200 140;
--super-scheduler-accent-950: #0c2a1b; /* accent-soft in dark mode */
--super-scheduler-accent-100: #d8f5e6; /* accent-text in dark mode */
}La selección, el día de hoy, el anillo de foco, los tonos de hover y las microbarras lo siguen, en ambos esquemas. Esta receta necesita el valor por defecto colorScheme: 'inherit'.
Un acento de marca para un solo scheduler
Para aplicar la marca a un solo scheduler, o para usar un colorScheme explícito, pon una clase en la raíz del control con cssClass y apunta a ella junto con el atributo del esquema:
.brand[data-color-scheme='light'] {
--super-scheduler-accent-rgb: 10 140 80;
--super-scheduler-accent-100: #e0f2e9;
--super-scheduler-accent-200: #c9e6d6;
--super-scheduler-accent-800: #04361f;
}
.brand[data-color-scheme='dark'] {
--super-scheduler-accent-rgb: 80 200 140;
--super-scheduler-accent-950: #0c2a1b;
--super-scheduler-accent-100: #d8f5e6;
}
.job--late {
--super-scheduler-event-bg: var(--super-scheduler-danger-soft);
--super-scheduler-event-border: var(--super-scheduler-danger);
--super-scheduler-event-text: var(--super-scheduler-danger);
}import { useMemo } from 'react'
import { SuperSchedulerComponent } from 'super-scheduler'
import type { SchedulerProps, SuperScheduler } from 'super-scheduler'
import 'super-scheduler/styles.css'
type Job = { status: 'planned' | 'late' | 'done' }
// Stable objects: a new classNames or styles object is applied again on every render.
const CLASS_NAMES: SuperScheduler.SchedulerClassNames = {
event: 'planning-event',
rowHeaderCell: 'planning-row-header',
}
const STYLES: SuperScheduler.SchedulerStyles = {
timeHeaderCell: { fontVariantNumeric: 'tabular-nums' },
}
// A class per state; the colors live in CSS, so they follow light and dark mode.
const statusClass: NonNullable<SchedulerProps['onBeforeEventRender']> = (args) => {
const job = args.data as SuperScheduler.EventRenderData<Job>
args.data.cssClass = `job job--${job.status}`
}
export function BrandedPlanner(props: {
theme: 'light' | 'dark'
resources: SuperScheduler.ResourceData[]
jobs: SuperScheduler.EventData<Job>[]
}) {
const events = useMemo(() => props.jobs.slice(), [props.jobs])
return (
<SuperSchedulerComponent
// Extra class on the control root: the brand CSS targets `.brand[data-color-scheme=...]`.
cssClass="brand"
// Follows the application's own theme switch.
colorScheme={props.theme}
density="compact"
classNames={CLASS_NAMES}
styles={STYLES}
onBeforeEventRender={statusClass}
startDate="2026-10-01"
days={31}
scale="Day"
resources={props.resources}
events={events}
/>
)
}Deberías ver la selección y los rellenos de los eventos en verde en modo claro, sus equivalentes oscuros cuando theme es 'dark', y los trabajos con retraso en los colores de peligro de cada esquema. Con colorScheme: 'auto', escribe las mismas reglas sobre .brand y sobre .brand dentro de @media (prefers-color-scheme: dark).
Esquema de color y modo oscuro
colorScheme se escribe en la raíz como data-color-scheme:
| Valor | Sigue a |
|---|---|
'inherit' (por defecto) | El ancestro más cercano con la clase dark o con un atributo data-theme="dark" / data-theme="light" |
'light', 'dark' | Forzado; se impone a cualquier ancestro |
'auto' | El prefers-color-scheme del sistema operativo |
Solo 'auto' lee el sistema operativo. Un sitio claro en un sistema oscuro sigue en claro con el modo por defecto, que es normalmente lo que quiere un producto con su propio selector de tema. El modo oscuro basado en clases de Tailwind (<html class="dark">) funciona tal cual con 'inherit'.
Los menús, las burbujas y las tarjetas emergentes se montan en document.body, fuera del scheduler. Llevan el esquema y los tokens del scheduler, así que encajan con él.
Colores y estados por evento
Los colores simples no necesitan CSS: backColor, fontColor, borderColor, barColor y barBackColor en los datos del evento, o fijados en onBeforeEventRender. SuperScheduler.ColorUtil.contrasting(color) elige un color de texto legible.
Para colores que deben seguir el modo oscuro, usa preferentemente una clase por estado y tokens de componente, como en la receta de arriba: cssClass en el evento y después --super-scheduler-event-bg, -event-text, -event-border y -event-bar en el CSS. Los eventos también exponen su estado de interacción como atributos: data-hovered, data-dragging y data-resizing en el evento que se está cambiando, y data-conflict con conflictHighlight. En la 0.1.0, los eventos seleccionados necesitan una clase propia (consulta selección de eventos). La barra fina de duración usa --super-scheduler-duration-bar de forma global o --super-scheduler-event-bar por evento; durationBarVisible: false la quita.
classNames y styles
classNames y styles añaden clases o estilos en línea a partes con nombre. Los slots son root, scroll, corner, timeHeader, timeHeaderCell, rowHeader, rowHeaderCell, treeToggle, grid, row, cell, event, eventInner, eventBar, area, separator, link, selection, shadow, rectangle, crosshair, dragCard, tooltip, skeleton, empty, error y message.
Aceptan utilidades de Tailwind además de tus propios nombres de clase. Define ambos objetos a nivel de módulo o memorízalos, y deja la posición, el tamaño, el overflow y el z-index en manos del motor: cambiarlos rompe la detección de punteros, las cabeceras fijas y la virtualización. cssClass es un atajo para añadir una clase más a la raíz.
Densidad
density cambia los tamaños por defecto sin tocar tus opciones:
| Preset | Alto de evento | Alto de cabecera | Además |
|---|---|---|---|
'comfortable' | 35 px | 30 px | Aspecto por defecto |
'compact' | 28 px | 26 px | Relleno de evento 2px 4px, texto de evento de 11 px |
'dense' | 20 px | 22 px | Relleno 0 4px, texto de 10 px, oculta [data-super-scheduler-part="event-meta"] |
Los tamaños del preset solo se aplican mientras eventHeight y headerHeight mantienen sus valores por defecto; los valores explícitos ganan. control.update({ density: 'dense' }) recalcula la disposición sin volver a montar. Las filas densas son objetivos difíciles en pantallas táctiles; en móviles, ofrécelas como opción y no como valor por defecto.
Modo sin estilos
Para un aspecto totalmente personalizado, activa unstyled y no importes la hoja de estilos. La raíz recibe data-unstyled, el motor sigue escribiendo solo los estilos en línea estructurales (posiciones, tamaños, apilamiento, cabeceras fijas) y la región live de los anuncios sigue oculta visualmente. Todo lo demás es tuyo, incluidos los indicadores de foco, la selección, el hover y el soporte de colores forzados.
Tailwind
Los tokens son el contrato; Tailwind es una forma de consumirlos.
Tailwind v3
super-scheduler/tailwind es un preset para v3. Añade colores (bg-super-scheduler-surface, text-super-scheduler-text-muted, bg-super-scheduler-accent/20, text-super-scheduler-ink/60, ...), radios (rounded-super-scheduler, rounded-super-scheduler-event), sombras (de shadow-super-scheduler-1 a -3) y duration-super-scheduler / ease-super-scheduler.
import superSchedulerPreset from 'super-scheduler/tailwind'
// Tailwind v3. The preset adds colors, radii, shadows and easing utilities that read the
// --super-scheduler-* tokens (bg-super-scheduler-surface, rounded-super-scheduler-event...),
// so they follow the scheduler's light and dark values.
// In a CommonJS config: presets: [require('super-scheduler/tailwind')].
export default {
content: ['./index.html', './src/**/*.{ts,tsx}'],
darkMode: 'class',
presets: [superSchedulerPreset],
}El preflight de Tailwind v3 no tiene capa, así que se impondría a los bordes de la librería, que sí la tienen. Pon el preflight en una capa por debajo de la librería:
@layer tw-base, super-scheduler;
@import 'super-scheduler/styles.css';
@layer tw-base {
@tailwind base;
}
@tailwind components;
@tailwind utilities;Tailwind v4
Tailwind v4 no tiene presets: mapea los tokens en @theme inline, después de declarar el orden de las capas. Los mapeos inline leen el valor del token más cercano, así que los temas oscuros anidados funcionan, y también los modificadores de opacidad como bg-super-scheduler-accent/20.
@layer theme, base, super-scheduler, components, utilities;
@import 'tailwindcss';
@import 'super-scheduler/styles.css';
@custom-variant dark (&:where(.dark, .dark *));
@theme inline {
--color-super-scheduler-surface: var(--super-scheduler-surface);
--color-super-scheduler-surface-raised: var(--super-scheduler-surface-raised);
--color-super-scheduler-text: var(--super-scheduler-text);
--color-super-scheduler-text-muted: var(--super-scheduler-text-muted);
--color-super-scheduler-border: var(--super-scheduler-border);
--color-super-scheduler-border-strong: var(--super-scheduler-border-strong);
--color-super-scheduler-grid-line: var(--super-scheduler-grid-line);
--color-super-scheduler-grid-break: var(--super-scheduler-grid-break);
--color-super-scheduler-row-line: var(--super-scheduler-row-line);
--color-super-scheduler-accent: var(--super-scheduler-accent);
--color-super-scheduler-accent-emphasis: var(--super-scheduler-accent-emphasis);
--color-super-scheduler-accent-soft: var(--super-scheduler-accent-soft);
--color-super-scheduler-accent-text: var(--super-scheduler-accent-text);
--color-super-scheduler-accent-border: var(--super-scheduler-accent-border);
--color-super-scheduler-on-accent: var(--super-scheduler-on-accent);
--color-super-scheduler-ink: rgb(var(--super-scheduler-ink-rgb));
--color-super-scheduler-danger: var(--super-scheduler-danger);
--color-super-scheduler-danger-soft: var(--super-scheduler-danger-soft);
--color-super-scheduler-warning: var(--super-scheduler-warning);
--color-super-scheduler-warning-soft: var(--super-scheduler-warning-soft);
--color-super-scheduler-success: var(--super-scheduler-success);
--color-super-scheduler-today-bg: var(--super-scheduler-today-bg);
--color-super-scheduler-weekend-bg: var(--super-scheduler-weekend-bg);
--color-super-scheduler-non-business-bg: var(--super-scheduler-non-business-bg);
--color-super-scheduler-group: var(--super-scheduler-group);
--color-super-scheduler-group-row: var(--super-scheduler-group-row);
--color-super-scheduler-hover-row: var(--super-scheduler-hover-row);
--color-super-scheduler-hover-cell: var(--super-scheduler-hover-cell);
--color-super-scheduler-selection: var(--super-scheduler-selection);
--color-super-scheduler-selection-border: var(--super-scheduler-selection-border);
--color-super-scheduler-focus-ring: var(--super-scheduler-focus-ring);
--color-super-scheduler-micro-bar: var(--super-scheduler-micro-bar);
--color-super-scheduler-duration-bar: var(--super-scheduler-duration-bar);
--color-super-scheduler-hatch: var(--super-scheduler-hatch);
--color-super-scheduler-overlay: var(--super-scheduler-overlay);
--color-super-scheduler-overlay-text: var(--super-scheduler-overlay-text);
--color-super-scheduler-overlay-muted: var(--super-scheduler-overlay-muted);
--color-super-scheduler-overlay-subtle: var(--super-scheduler-overlay-subtle);
--color-super-scheduler-overlay-border: var(--super-scheduler-overlay-border);
--color-super-scheduler-skeleton-base: var(--super-scheduler-skeleton-base);
--color-super-scheduler-skeleton-highlight: var(--super-scheduler-skeleton-highlight);
--radius-super-scheduler: var(--super-scheduler-radius, 12px);
--radius-super-scheduler-event: var(--super-scheduler-event-radius, 8px);
--shadow-super-scheduler-1: var(--super-scheduler-shadow-1);
--shadow-super-scheduler-2: var(--super-scheduler-shadow-2);
--shadow-super-scheduler-3: var(--super-scheduler-shadow-3);
--ease-super-scheduler: var(--super-scheduler-ease);
--ease-super-scheduler-spring: var(--super-scheduler-ease-spring);
}Temas en Lite
Lite (super-scheduler-lite/styles.css) tiene seis tokens: --super-scheduler-background, -text, -border, -header, -event y -focus. Se declaran en el propio elemento .super-scheduler-lite, así que fíjalos en ese elemento, no en un ancestro:
.bookings .super-scheduler-lite {
--super-scheduler-event: #dcfce7;
--super-scheduler-focus: #15803d;
}
.dark .bookings .super-scheduler-lite {
--super-scheduler-background: #111827;
--super-scheduler-text: #f3f4f6;
--super-scheduler-border: #374151;
--super-scheduler-header: #1f2937;
--super-scheduler-event: #14532d;
}Lite no tiene un esquema oscuro integrado, así que los valores oscuros los declaras tú. Su hoja de estilos también usa capas y adapta los bordes y el foco a los colores forzados. Por evento, Lite acepta backColor, fontColor y cssClass.
De qué es dueña tu aplicación
- El contraste de cada color que introduces, en los modos claro, oscuro y de alto contraste.
- El propio selector de tema: dónde va la clase
darkodata-theme, o quécolorSchemepasas. - Los estilos del contenido personalizado (HTML de los hooks, slots de React, tarjetas emergentes): usa los tokens para que siga el esquema.
- Revisar tus sobrescrituras después de cada actualización. Los tokens y los selectores de partes son el contrato estable; el orden interno de las clases y el marcado entre partes no lo son.
Relacionado
Reservas de pistas en un club deportivoA media mañana se rompe la red de una pista de pádel. Mueve la clase, cierra la pista y respeta el turno de cada monitor. Planificación de escenarios de un festivalUna prueba de sonido invade el margen de una actuación. Amplía a cinco minutos, recórtala y mira qué salas y equipos dependen del artista. Planning de habitaciones de hotelGotea la ducha de la 104. Recoloca al siguiente cliente, bloquea la habitación para el fontanero y localiza las noches que ya están llenas.
- Teclado, accesibilidad y táctil para el movimiento reducido, el alto contraste y los colores forzados.
- Slots de renderizado React y tarjetas emergentes para los tokens de las tarjetas emergentes.
Ejemplos relacionados
- Court ClubReservas de pistas en un club deportivoA media mañana se rompe la red de una pista de pádel. Mueve la clase, cierra la pista y respeta el turno de cada monitor.
- Aurora LivePlanificación de escenarios de un festivalUna prueba de sonido invade el margen de una actuación. Amplía a cinco minutos, recórtala y mira qué salas y equipos dependen del artista.
- Casa NomaPlanning de habitaciones de hotelGotea la ducha de la 104. Recoloca al siguiente cliente, bloquea la habitación para el fontanero y localiza las noches que ya están llenas.