Theming y textos

Paletas integradas, tonos de superficie, modo oscuro dirigido por clase y reemplazo de cada texto integrado para i18n.

Theming

// paleta integrada por lista
defineListConfig({ colorTheme: 'teal', /* … */ })

// default global
<ListKitProvider theme="teal">…</ListKitProvider>

// tema personalizado (colores de marca) — pasa un objeto ThemeClasses donde se acepta un tema
const brand: ThemeClasses = {
  primaryBg: 'bg-[#121c38]',
  primaryText: 'text-white',
  focusRing: 'focus:ring-indigo-500',
  focusBorder: 'focus:border-indigo-500',
  /* … */
}
defineListConfig({ colorTheme: brand, /* … */ })

Tones de tabla y cards

colorTheme maneja los acentos; tones maneja el chrome neutro — header de la tabla, divisores, hover/selección de filas y el panel alrededor de la tabla y de las cards default. Elige un preset integrado ('gray' es el default, 'contrast' invierte el header) o pasa un objeto SurfaceTones completo de clases Tailwind. Los dos ejes componen: colorTheme: 'teal', tones: 'slate'.

// preset: 'gray' | 'slate' | 'zinc' | 'contrast'
defineListConfig({ tones: 'slate' /* … */ })

// custom — todo background opaco: las celdas pinned heredan el de la fila
defineListConfig({
	tones: {
		container: 'border-indigo-100 bg-white shadow-sm',
		headerBg: 'bg-indigo-50',
		headerText: 'text-indigo-700',
		headerDivider: 'border-indigo-200',
		rowBg: 'bg-white',
		rowHover: 'hover:bg-indigo-50',
		rowSelected: 'bg-indigo-100 hover:bg-indigo-100',
		divider: 'divide-indigo-100',
	},
	/* … */
})

La primitiva Table acepta el mismo valor como prop tones para uso suelto, y getSurfaceTones resuelve un preset si necesitas las clases directamente.

Dark mode

Cada componente trae variantes dark: aditivas, activadas por una clase .dark en un ancestro (normalmente <html>) — no por prefers-color-scheme — para que tu app controle el toggle. listkit/tailwind.css registra la variante por ti:

@custom-variant dark (&:where(.dark, .dark *));

Con importar ese archivo basta. Sin él, Tailwind v4 lee dark: como prefers-color-scheme, y una app sin modo oscuro renderiza sus listas en oscuro para todo lector cuyo SO lo esté — con el resto de la página intacta.

Haz document.documentElement.classList.toggle('dark') y toda lista — tabla, tarjetas, menús, filtros, diálogos, skeletons — lo sigue. Las paletas integradas traen acentos dark; un ThemeClasses propio puede agregar sus clases dark: dentro de cada campo. El render claro no cambia cuando la clase no está.

Labels (i18n)

Los controles que un icono describe por sí solo (toggle de vista, botón de filtros, conteo de resultados) son solo-icono, así que se leen igual en cualquier idioma; sus nombres viven en aria-label/title. Todo el resto de los textos integrados sale de un objeto labels que por defecto está en inglés — sobreescríbelo para toda la app en el provider, o por lista con config.labels.

Camino más corto — DEFAULT_LABELS (inglés) y ES_LABELS (español) cubren los casos comunes en una línea (encima puedes sobreescribir claves sueltas):

import { ListKitProvider, ES_LABELS } from 'listkit'
// toda la app en español (el inglés es el default, así que no necesita prop)
;<ListKitProvider labels={ES_LABELS}></ListKitProvider>

O elige los textos a mano:

// para toda la app (el idioma de la app)
;<ListKitProvider
	labels={{
		tableView: 'Vista tabla',
		cardsView: 'Vista tarjetas',
		filters: 'Filtros',
		applyFilters: 'Aplicar',
		clearFilters: 'Limpiar',
		empty: 'Sin resultados',
		yes: 'Sí',
		no: 'No',
		results: n => `${n} resultado${n === 1 ? '' : 's'}`,
	}}
>

</ListKitProvider>

// o por lista (gana sobre el provider)
defineListConfig({ labels: { empty: 'Sin pedidos' } /* … */ })

NextListView acepta la misma prop labels (y theme) y la reenvía a su provider interno: <NextListView labels={ES_LABELS} config={…} adapter={…} />.

Orden de resolución: config.labelslabels del provider → DEFAULT_LABELS. Las props por elemento que ya existen siguen ganando donde aplican (config.emptyMessage, config.filtersTitle, el trueLabel/falseLabel de un filtro). Consulta ListLabels para la lista completa de claves.

On this page