Zephora UI

Configuración

Ajustes globales para cada componente de Zephora — envuelve tu aplicación una sola vez con ZephoraConfigProvider y configura la locale, las capas de z-index de los overlays, el contenedor del portal y el valor por defecto headless.

Configuración inicial

import { ZephoraConfigProvider } from "@zephora/react";

export default function App() {
  return (
    <ZephoraConfigProvider
      locale="tr"
      zIndex={{ modal: 2000, toast: 2100 }}
      appendTo={typeof document !== "undefined" ? document.body : null}
      unstyled={false}
    >
      <YourApp />
    </ZephoraConfigProvider>
  );
}

ZephoraConfigProvider props

PropTipoPredeterminadoDescripción
localestring"en"Active locale for component UI strings. Only "en" is embedded; load others from @zephora/theme/locales/* (module or JSON) and register with addLocale().
zIndex{ dropdown?, overlay?, modal?, popover?, toast?, tooltip?: number }Overrides the layering of floating elements. Written as --z-index-* CSS variables on the root element.
appendToHTMLElement | nulldocument.bodyContainer that Portal-based overlays (Dialog, Select menus, Tooltip…) render into.
unstyledbooleanfalseMakes every component headless by default for Tailwind-first apps. A per-component unstyled prop still wins.

Leer la configuración

import { useZephoraConfig, useLocale } from "@zephora/react";

function MyField() {
  const config = useZephoraConfig(); // { locale, zIndex, appendTo, unstyled }
  const { t, messages, locale } = useLocale();
  return <button aria-label={t("close")} />;
}

Capas de z-index

Los componentes toman su orden de apilamiento de variables CSS con valores de reserva integrados, de modo que tanto el provider como el CSS plano pueden reajustarlas:

:root {
  --z-index-dropdown: 1000;
  --z-index-overlay: 1040;
  --z-index-modal: 1050;
  --z-index-popover: 1060;
  --z-index-toast: 1070;
  --z-index-tooltip: 1080;
}

Modo oscuro

@zephora/theme incluye utilidades automáticas de modo oscuro. El hook useColorScheme resuelve un esquema (con mode: "system" sigue la preferencia del sistema operativo en vivo) y por defecto aplica el tema resuelto de forma global:

import { useColorScheme } from "@zephora/theme";

function App() {
  // mode: "light" | "dark" | "system" (default "system")
  const { scheme, theme } = useColorScheme({ mode: "system" });
  return <span>Active scheme: {scheme}</span>;
}

useColorScheme(options) props

PropTipoPredeterminadoDescripción
mode"light" | "dark" | "system""system""system" follows the OS preference live; "light"/"dark" force a scheme.
light / darkThemelightTheme / darkThemeTheme objects used for each scheme.
applybooleantrueWrite the resolved theme to document.documentElement via applyTheme.
→ returns{ scheme: "light" | "dark"; theme: Theme }The resolved scheme and the theme object in effect.

Las primitivas de nivel inferior también se exportan:

import { getSystemColorScheme, watchSystemColorScheme } from "@zephora/theme";

// Reads the OS color scheme (SSR-safe; defaults to "light").
const scheme = getSystemColorScheme(); // "light" | "dark"

// Subscribes to OS changes. Returns an unsubscribe function.
const stop = watchSystemColorScheme((next) => console.log(next));
stop();

SSR sin FOUC

Para el renderizado en el servidor, colorSchemeCss(light?, dark?) construye una hoja de estilos estática que cambia de tema según la preferencia del sistema operativo — sin destello del tema incorrecto, sin necesidad de JavaScript antes del paint. Establecer data-zephora-scheme en <html> sobrescribe la media query (conéctalo a un interruptor del usuario):

import { colorSchemeCss } from "@zephora/theme";

// Next.js app router — app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <style dangerouslySetInnerHTML={{ __html: colorSchemeCss() }} />
      </head>
      <body>{children}</body>
    </html>
  );
}

classNames de slots

Los componentes multi-slot (Dialog, Sheet, Tabs, Card, Popover, Tooltip…) exponen un contrato de clases por slot: la raíz acepta classNames tipado como Partial<Record<<Name>Slot, string>> (las uniones de nombres de slot como DialogSlot se exportan). Las clases de slot se añaden después de las clases del módulo y no dependen de unstyled — funcionan tanto en modo con estilo como sin estilo; en modo sin estilo son las únicas clases. classNames.root se combina junto al prop className existente, que sigue apuntando a la raíz y se aplica en último lugar. Para componentes compuestos, classNames se establece una vez en la raíz y se traslada a las partes mediante el context.

Componentes de servidor

El bundle publicado @zephora/react se distribuye con una directiva "use client", por lo que puedes importar los componentes directamente dentro de árboles de React Server Component (app router de Next.js) sin añadir tú mismo la directiva — cada componente de Zephora es un componente de cliente.