Ir al contenido
uiify

Arquitectura

uiify tiene cinco capas, publicadas por separado y sin importar nunca una capa superior. Todas siguen una regla: cada componente debe funcionar antes de la hidratación.

El intervalo antes de la hidratación

El SSR en streaming deja un intervalo entre la primera visualización y el fin de la hidratación. Con Suspense, cada límite que llega tarde tiene su propio intervalo. Durante ese tiempo, un acordeón con useState se ve, pero no responde; uno con <details> funciona desde la primera visualización.

Dos documentos renderizan el mismo acordeón sin ninguna etiqueta <script>: uno basado en `<details>` y otro basado en `useState`. Abre ambos: el primero se despliega; el segundo no puede hacerlo. Revisa el código fuente para comprobarlo.

El objetivo es evitar los renderizados innecesarios, la propagación de actualizaciones a todo el proveedor y el trabajo síncrono de disposición causado por el JavaScript de la biblioteca. El estado tiene que renderizarse en algún lugar. De forma predeterminada no hay JavaScript; solo se añade una capa mínima donde la accesibilidad lo exige.

Niveles

Cada componente declara un nivel en un manifiesto que se lee durante la compilación. El manifiesto determina el límite de tamaño, el lint de pureza RSC, las pruebas de Playwright y la insignia de nivel en la página de cada componente.

NivelLímiteSin JavaScriptQué significa
Tier 0
RSC — sin JavaScript de cliente
0 kBSupera todas las pruebas sin JavaScript.El estado reside en un elemento nativo o no existe. Se prohíben todos los hooks de React, incluidos useMemo y useRef.
Tier 1
Envoltura RSC + isla de cliente mínima
≤ 1 kBComportamiento reducido, documentado por componente.El elemento nativo sigue gestionando el estado. JavaScript solo sincroniza ARIA o añade lo que falta en la plataforma, como detectar la intención del puntero o cerrar automáticamente.
Tier 2
Componente de cliente — SSR antes de la hidratación
por componenteRenderiza marcado útil antes de la hidratación.Una única entrada de cliente. El servidor genera marcado que prioriza los mecanismos nativos cuando es posible; la navegación con teclado, el filtrado y la sincronización de ARIA esperan a la hidratación.

Los niveles también sirven para las migraciones: los controles se activan por componente, de modo que la arquitectura se vuelve más estricta de forma gradual.

La pila de capas

@gunkin/uiify/hooks       SSR-safe React hooks — the substrate
@gunkin/uiify/core        headless behaviour: focus scope, dismiss layers, anchoring
@gunkin/uiify/elements    native-mechanism wrappers — zero client JavaScript
@gunkin/uiify/components  unstyled components, RSC by default
@gunkin/uiify/styles      optional CSS design layer

Las capas inferiores nunca importan capas superiores. @gunkin/uiify/elements es la más estricta: solo puede importar @gunkin/uiify/core/render y tipos de React.

Por qué elements es una capa pública

La mayoría de las aplicaciones nunca importa @gunkin/uiify/elements directamente. Esta capa se publica por dos motivos.

Primero, permite verificar el diseño. Cuando una página de componente indica _basado en elements/dialog_, la página de ese elemento muestra el marcado exacto y el contrato data-* que lo sustentan.

Segundo, la composición: si la anatomía del componente no encaja con tu diseño, crea una propia sobre las mismas conexiones, sin volver a implementar el mecanismo.

Un módulo entra en esta capa solo si cumple cinco reglas: un mecanismo nativo, ningún comportamiento en JavaScript, dos o más consumidores en @gunkin/uiify/components, estado legible por un selector CSS y menos marcado duplicado sin añadir indirección.

Los módulos toman el nombre de funciones de la plataforma —details, dialog, popover, invoker—, no de conceptos de interfaz. Un componente nunca comparte nombre con un elemento; por eso Modal se basa en dialog. Explora los elementos

Por qué se prohíbe el contexto de React en Tier 0

Llevar el estado al DOM no sirve si las partes siguen comunicándose mediante el contexto de React. Los Server Components no pueden usar contexto, así que un Root y un Item que comparten un proveedor no pueden renderizarse en el servidor, por nativo que sea su marcado.

Las conexiones deben sobrevivir a la serialización, así que las partes se vinculan mediante HTML: <details name> para agrupar, commandfor y popovertarget para referencias que resuelve el navegador, e ids derivados de props. Un valor de useId no puede llegar a las partes hermanas sin contexto.

<Accordion id="faq">
  <Accordion.Item value="shipping">   {/* id="faq-shipping" */}

El costo: la raíz necesita un id. Cuando no hace falta composición, el componente recibe datos y renderiza el árbol por sí mismo. Consulta Server Components

Esta página se tradujo automáticamente y aún no se ha revisado.