K
KoreUI

Theming

Getting Started

Sistema de tokens semánticos con CSS custom properties, colores OKLCH y soporte completo para dark mode.

Sistema de tokens

KoreUI usa un sistema de design tokens basado en CSS custom properties con el prefijo --kore-*. Estos tokens definen colores, radios y animaciones que todos los componentes consumen de forma consistente.

Los tokens se definen en kore-theme.css y se registran en Tailwind v4 usando la directiva @theme inline, lo que genera clases utilitarias automáticamente (ej: bg-kore-primary, text-kore-fg, rounded-kore-md).

kore-theme.css — Registro en Tailwind v4
@theme inline {
  --color-kore-primary: var(--kore-primary);
  --color-kore-primary-fg: var(--kore-primary-fg);
  --color-kore-secondary: var(--kore-secondary);
  --color-kore-secondary-fg: var(--kore-secondary-fg);
  --color-kore-bg: var(--kore-bg);
  --color-kore-fg: var(--kore-fg);
  --color-kore-surface: var(--kore-surface);
  --color-kore-border: var(--kore-border);
  --radius-kore-sm: var(--kore-radius-sm);
  --radius-kore-md: var(--kore-radius-md);
  --radius-kore-lg: var(--kore-radius-lg);
  --radius-kore-xl: var(--kore-radius-xl);
  /* ... más tokens */
}
@theme inline {
  --color-kore-primary: var(--kore-primary);
  --color-kore-primary-fg: var(--kore-primary-fg);
  --color-kore-secondary: var(--kore-secondary);
  --color-kore-secondary-fg: var(--kore-secondary-fg);
  --color-kore-bg: var(--kore-bg);
  --color-kore-fg: var(--kore-fg);
  --color-kore-surface: var(--kore-surface);
  --color-kore-border: var(--kore-border);
  --radius-kore-sm: var(--kore-radius-sm);
  --radius-kore-md: var(--kore-radius-md);
  --radius-kore-lg: var(--kore-radius-lg);
  --radius-kore-xl: var(--kore-radius-xl);
  /* ... más tokens */
}

Colores OKLCH

Todos los colores usan el espacio de color OKLCH para mejor interpolación perceptual y consistencia visual.

OKLCH (Lightness, Chroma, Hue) ofrece ventajas sobre HSL y HEX: los colores con la misma luminosidad percibida realmente se ven igual de brillantes, y las transiciones entre colores son más suaves y naturales.

Formato OKLCH
/* oklch(luminosidad crominancia tono) */
--kore-primary: oklch(0.55 0.25 250);     /* Azul vibrante */
--kore-destructive: oklch(0.58 0.25 27);  /* Rojo */
--kore-success: oklch(0.62 0.19 145);     /* Verde */
--kore-warning: oklch(0.75 0.18 85);      /* Amarillo/naranja */
/* oklch(luminosidad crominancia tono) */
--kore-primary: oklch(0.55 0.25 250);     /* Azul vibrante */
--kore-destructive: oklch(0.58 0.25 27);  /* Rojo */
--kore-success: oklch(0.62 0.19 145);     /* Verde */
--kore-warning: oklch(0.75 0.18 85);      /* Amarillo/naranja */

Ventaja: Al usar OKLCH, puedes cambiar solo el tono (hue) para obtener un color diferente manteniendo la misma luminosidad y saturación percibida. Esto facilita crear paletas consistentes.

Light y Dark mode

KoreUI soporta light mode, dark mode y modo sistema. Los tokens se redefinen automáticamente cuando el tema cambia.

El dark mode se activa mediante la clase .dark o el atributo [data-theme="dark"] en el elemento <html>. Los componentes no necesitan clases condicionales: el mismo token produce el color correcto en ambos temas.

Definición de tokens light/dark
@layer base {
  /* --- Light mode (default) --- */
  :root {
    --kore-bg: oklch(1 0 0);         /* Blanco */
    --kore-fg: oklch(0.15 0 0);      /* Casi negro */
    --kore-primary: oklch(0.55 0.25 250);
    --kore-surface: oklch(1 0 0);
    --kore-border: oklch(0.92 0 0);
  }

  /* --- Dark mode --- */
  .dark, [data-theme="dark"] {
    --kore-bg: oklch(0.13 0 0);      /* Casi negro */
    --kore-fg: oklch(0.93 0 0);      /* Casi blanco */
    --kore-primary: oklch(0.70 0.20 250);
    --kore-surface: oklch(0.17 0 0);
    --kore-border: oklch(0.25 0 0);
  }
}
@layer base {
  /* --- Light mode (default) --- */
  :root {
    --kore-bg: oklch(1 0 0);         /* Blanco */
    --kore-fg: oklch(0.15 0 0);      /* Casi negro */
    --kore-primary: oklch(0.55 0.25 250);
    --kore-surface: oklch(1 0 0);
    --kore-border: oklch(0.92 0 0);
  }

  /* --- Dark mode --- */
  .dark, [data-theme="dark"] {
    --kore-bg: oklch(0.13 0 0);      /* Casi negro */
    --kore-fg: oklch(0.93 0 0);      /* Casi blanco */
    --kore-primary: oklch(0.70 0.20 250);
    --kore-surface: oklch(0.17 0 0);
    --kore-border: oklch(0.25 0 0);
  }
}

Tokens de color

Los colores semánticos disponibles y su propósito. Cada color tiene una variante -fg para texto sobre ese color.

Token Light Dark Uso
--kore-primary oklch(0.55 0.25 250) oklch(0.70 0.20 250) Color principal, acciones primarias
--kore-secondary oklch(0.97 0.01 260) oklch(0.25 0.01 260) Acciones secundarias, fondos alternos
--kore-accent oklch(0.92 0.01 260) oklch(0.30 0.01 260) Acentos, highlights
--kore-destructive oklch(0.58 0.25 27) oklch(0.55 0.25 27) Eliminar, errores, acciones peligrosas
--kore-success oklch(0.62 0.19 145) oklch(0.58 0.19 145) Confirmaciones, operaciones exitosas
--kore-warning oklch(0.75 0.18 85) oklch(0.70 0.18 85) Advertencias, precaución
--kore-info oklch(0.62 0.15 250) oklch(0.58 0.15 250) Información, tooltips, notas

Cada color semántico tiene una variante -fg (ej: --kore-primary-fg) que define el color de texto ideal para usarse sobre ese fondo.

Tokens de superficie

Tokens para fondos, texto, bordes y estados interactivos de la interfaz.

Token Clase Tailwind Descripción
--kore-bg bg-kore-bg Fondo principal de la página
--kore-fg text-kore-fg Color de texto principal
--kore-surface bg-kore-surface Fondo de tarjetas, modales, paneles
--kore-surface-fg text-kore-surface-fg Texto sobre superficies
--kore-muted bg-kore-muted Fondo de elementos secundarios, hovers
--kore-muted-fg text-kore-muted-fg Texto secundario, placeholders
--kore-border border-kore-border Bordes y separadores
--kore-input border-kore-input Borde de inputs de formulario
--kore-ring ring-kore-ring Anillo de foco (focus ring)

Tokens de radio

Radios de borde (border-radius) para mantener consistencia visual en toda la interfaz.

Token Valor Clase Tailwind Uso
--kore-radius-sm 0.25rem rounded-kore-sm Badges, chips, elementos pequenos
--kore-radius-md 0.375rem rounded-kore-md Inputs, botones, selects
--kore-radius-lg 0.5rem rounded-kore-lg Cards, dropdowns, modales
--kore-radius-xl 0.75rem rounded-kore-xl Contenedores grandes, tooltips

Animaciones

KoreUI incluye una animacion spring personalizada y soporte para prefers-reduced-motion.

Variables de animación
:root {
    --kore-spring-easing: linear(...);   /* Curva spring realista */
    --kore-spring-duration: 500ms;       /* Duración de la animación */
}

/* Reducción automática de movimiento */
@media (prefers-reduced-motion: reduce) {
    :root {
        --kore-spring-easing: ease;
        --kore-spring-duration: 0ms;
    }
}
:root {
    --kore-spring-easing: linear(...);   /* Curva spring realista */
    --kore-spring-duration: 500ms;       /* Duración de la animación */
}

/* Reducción automática de movimiento */
@media (prefers-reduced-motion: reduce) {
    :root {
        --kore-spring-easing: ease;
        --kore-spring-duration: 0ms;
    }
}

La animación spring se usa en toasts, overlays y transiciones. Cuando el usuario tiene activada la preferencia de movimiento reducido, las animaciones se desactivan automáticamente.

Uso en Tailwind v4

Los tokens se consumen directamente como clases Tailwind gracias a @theme inline.

Ejemplos de clases Tailwind con tokens Kore
<!-- Fondos -->
<div class="bg-kore-bg">Fondo principal</div>
<div class="bg-kore-surface">Fondo de tarjeta</div>
<div class="bg-kore-primary">Fondo primario</div>
<div class="bg-kore-muted">Fondo secundario/hover</div>

<!-- Textos -->
<p class="text-kore-fg">Texto principal</p>
<p class="text-kore-muted-fg">Texto secundario</p>
<span class="text-kore-primary">Texto de acento</span>

<!-- Bordes -->
<div class="border border-kore-border">Con borde</div>
<input class="border-kore-input focus:ring-kore-ring" />

<!-- Border radius -->
<div class="rounded-kore-md">Radio medio</div>
<div class="rounded-kore-lg">Radio grande</div>

<!-- Opacidad con tokens -->
<div class="bg-kore-primary/10">Fondo con 10% de opacidad</div>
<div class="border-kore-info/30">Borde translúcido</div>
<!-- Fondos -->
<div class="bg-kore-bg">Fondo principal</div>
<div class="bg-kore-surface">Fondo de tarjeta</div>
<div class="bg-kore-primary">Fondo primario</div>
<div class="bg-kore-muted">Fondo secundario/hover</div>

<!-- Textos -->
<p class="text-kore-fg">Texto principal</p>
<p class="text-kore-muted-fg">Texto secundario</p>
<span class="text-kore-primary">Texto de acento</span>

<!-- Bordes -->
<div class="border border-kore-border">Con borde</div>
<input class="border-kore-input focus:ring-kore-ring" />

<!-- Border radius -->
<div class="rounded-kore-md">Radio medio</div>
<div class="rounded-kore-lg">Radio grande</div>

<!-- Opacidad con tokens -->
<div class="bg-kore-primary/10">Fondo con 10% de opacidad</div>
<div class="border-kore-info/30">Borde translúcido</div>

Personalizar colores

Puedes sobrescribir cualquier token redefiniendo las CSS custom properties en tu CSS.

resources/css/app.css
@import 'tailwindcss';
@import '../../vendor/kore-ui/kore-ui/resources/css/kore-theme.css';

/* Sobrescribir el color primario */
@layer base {
  :root {
    --kore-primary: oklch(0.60 0.20 160);      /* Verde esmeralda */
    --kore-primary-fg: oklch(0.98 0 0);         /* Blanco */
    --kore-ring: oklch(0.60 0.20 160);          /* Ring del mismo color */
  }

  .dark, [data-theme="dark"] {
    --kore-primary: oklch(0.70 0.18 160);       /* Verde más claro en dark */
    --kore-primary-fg: oklch(0.15 0 0);         /* Negro */
    --kore-ring: oklch(0.70 0.18 160);
  }
}
@import 'tailwindcss';
@import '../../vendor/kore-ui/kore-ui/resources/css/kore-theme.css';

/* Sobrescribir el color primario */
@layer base {
  :root {
    --kore-primary: oklch(0.60 0.20 160);      /* Verde esmeralda */
    --kore-primary-fg: oklch(0.98 0 0);         /* Blanco */
    --kore-ring: oklch(0.60 0.20 160);          /* Ring del mismo color */
  }

  .dark, [data-theme="dark"] {
    --kore-primary: oklch(0.70 0.18 160);       /* Verde más claro en dark */
    --kore-primary-fg: oklch(0.15 0 0);         /* Negro */
    --kore-ring: oklch(0.70 0.18 160);
  }
}

Importante: Siempre define las variantes para :root (light) y .dark (dark) al sobrescribir tokens. Si solo defines uno, el otro tema usará los valores originales.

Ejemplo: cambiar radios globalmente
@layer base {
  :root {
    --kore-radius-sm: 0.125rem;   /* Más cuadrado */
    --kore-radius-md: 0.25rem;
    --kore-radius-lg: 0.375rem;
    --kore-radius-xl: 0.5rem;
  }
}
@layer base {
  :root {
    --kore-radius-sm: 0.125rem;   /* Más cuadrado */
    --kore-radius-md: 0.25rem;
    --kore-radius-lg: 0.375rem;
    --kore-radius-xl: 0.5rem;
  }
}

Anti-FOUC

El script @koreThemeScript previene el flash de tema incorrecto aplicando el tema antes del primer render.

Uso en tu layout
<head>
    @koreThemeScript  {{-- ANTES de CSS y JS --}}
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<head>
    @koreThemeScript  {{-- ANTES de CSS y JS --}}
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>

Este script inline (~200 bytes) lee localStorage('kore-theme') y aplica la clase .dark y el atributo data-theme de forma síncrona antes de que el navegador pinte. Esto evita el parpadeo de tema incorrecto al cargar la página.

wire:navigate: El Alpine store se encarga de re-aplicar el tema después de cada navegación con wire:navigate de Livewire 4, registrando un listener en livewire:navigated.