You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/docs/process/RESEARCH-blocks-references.md

59 KiB

RESEARCH — Estudio de referencia del tier blocks (paridad y superación)

Proceso, no doctrina. Alimenta las fases 0 de PLAN-blocks.md: cada fiche de F1/F2/F3/F4 verifica contra este dossier en vez de investigar de cero. Encargo del usuario (2026-07-21): "estar al menos a la par y cuanto menos superarlo". Método: 6 pistas de investigación web en paralelo sobre fuentes oficiales vivas, cada una contrastando el plan contra el panorama real y devolviendo brechas + ángulos de superación.

Estado: ✅ COMPLETA 2026-07-21 — 6/6 pistas recibidas y sintetizadas. Enmiendas E-1…E-5 presentadas al usuario (ver §Síntesis; firmas se registran en PLAN-blocks.md §Registro).

Rúbrica

  • Suelo de paridad: lo que ≥2 referencias convergen en ofrecer para un ítem (features, props, variantes, comportamientos). Un ítem nuestro no está "hecho" por debajo de su suelo salvo decisión explícita registrada.
  • Diferenciadores: features únicos de una referencia que valga la pena adoptar (con juicio, no por completismo).
  • Superación: lo que nuestra arquitectura permite y ninguna referencia tiene (contrato morfo introspectable, sema/percepción, tokens + density + RTL + dark de serie, composición real vs copy-paste).

Pistas

# Pista Cubre Estado
P1 Catálogos de blocks de marketing shadcn blocks · Tailwind Plus · Flowbite · PrimeBlocks · Relume · Untitled UI · daisyUI → F2 lanzada
P2 Blocks de aplicación + app-shell Tailwind Plus App UI · shadcn dashboard/sidebar/login · Mantine AppShell · Tremor · AntD ProComponents · Refine · auth UIs → F3 lanzada
P3 Refs F1 (5 ligeros) affix/anchor/empty/result/callout en AntD · Mantine · Radix Themes · Chakra · Polaris · GitHub/Docusaurus admonitions → F1.1–F1.4, F1.6 lanzada
P4 Refs F1 (2 pesados) prose (@tailwindcss/typography · Mantine · Primer) · sidebar (shadcn EXHAUSTIVO · AntD Sider · Mantine) → F1.5, F1.7 lanzada
P5 Docs shells + docs blocks Starlight · Fumadocs · Docusaurus · VitePress · Nextra · Mintlify · showcase/props-tables → F4 lanzada
P6 Ecosistema Svelte competidor shadcn-svelte · Bits · Melt · Skeleton · Flowbite-Svelte · svelte-ux · nuevos Svelte-5 → el listón "mejor de Svelte" lanzada

Hallazgos

P1 — Catálogos de marketing — ✅ RECIBIDA 2026-07-21 (conteos y nombres de variante en vivo)

Panorama

  • shadcn/ui blocks: CERO marketing (solo sidebar/login/signup/dashboard) — el marketing vive en registries de terceros. Su aporte es el modelo de distribución (registry + CLI + "Open in v0").
  • Tailwind Plus: ~133 ejemplos de marketing en 16 categorías (Heroes 12 · Features 15 · Pricing 12 · CTA 11 · Stats 8 · Testimonials 8 · FAQs 7 · Footers 7 · Newsletter 6 · Team 9 · Blog 7 · Contact 7 · Content 7 · Logo Clouds 6 · Bento 3 · Headers 8) + elements (Navbars 11 · Flyout 7 · Banners 13) — dump estático HTML/React/Vue; dark = segundo artefacto a la venta.
  • Flowbite: ~170 marketing en 28 categorías (Hero 18 con nombres capturados: carousel, phone-mockup+app-store, search-bar+datepicker, video, sign-up-in-hero…; auth y 404/500/maintenance clasificados como marketing).
  • PrimeBlocks (relanzado, Vue-first, $599/dev): ~168 marketing (Feature 27 · Testimonial 20 · Team 12 · Navbar 12 · CTA 12 · Logo Cloud 10…).
  • Relume (AI builder, 1.000+/plataforma): la taxonomía más ancha (31 categorías: gallery, events, careers, comparison, timeline, multi-step forms, cookie consent, link pages…); semántica débil ("Layout 249").
  • Untitled UI React: el casi-par más cercano — componentes React reales con props (no dumps), la mayor profundidad por categoría (Hero 44 · Features 42 · Footers 40 · Testimonials 26 · Pricing 22 · FAQ 16 · Metrics 16) + 105 page examples; pero React-only, PRO-gated, sin tokens/RTL/density.
  • daisyUI: sin blocks (solo templates de pago de página completa) — confirma que ninguna librería class-based shippea secciones componibles.

Suelo por bloque F2 (brechas concretas de nuestro v1)

Block Suelo/recurrencias que nos faltan
hero El esqueleto center|split es correcto; la brecha es tratamiento de media, no conteo de layouts: presets de media (screenshot enmarcado / phone mockup / background-image cover), slot form-in-hero (email sign-up), logo-strip bajo las acciones, video embed.
feature-grid LA brecha #1 de F2: el split/alternante texto-vs-screenshot con lista de features lo shippean las 5 refs y es la sección nº1 tras el hero; nuestro v1 solo tiene el grid de iconos.
testimonials Falta la cita única en spotlight (logo + quote + avatar + autor) — la variante modal en TODAS las refs; el grid es minoría (2 de 8 en TW).
faq Falta la lista estática 2/3-columnas (mayoría del formato: 6 de 7 en TW no son acordeón) + la cola "Still have questions?" (CTA a soporte).
pricing Recurren y no tenemos: tabla de comparación de features y variante single-price. Toggle + featured = paridad OK.
site-header Sin flyout/dropdown de navegación no hay paridad (todas lo traen; nuestro NavigationMenu ya lo da — es cuestión de scope del block); y falta el hermano announcement banner (13 TW · 16 Untitled — nuestro componente Banner existe: candidato a block banner o slot del header).
stats-band Paridad OK; variantes recurrentes adoptables: split-with-image, timeline/stepped. Ninguna ref puede shippear count-up (markup estático) — nuestra superación literal.
cta Paridad con centered; añadir arreglo justified (texto izq., botones dcha.) y variante split-with-media.
newsletter Añadir slot de nota de privacidad bajo el field (convergente).
site-footer Añadir slots: newsletter-form en footer (3 de 7 TW) y language selector (encaja con nuestro langs).
(ecosistema) Todas las refs shippean páginas compuestas como artefacto de prueba (TW 10 · Untitled 105) — nuestra página de integración F2 cumple ese rol; considerar promocionarla a demo pública.

Categorías de la unión que NO planeamos (decisión explícita pendiente)

≥2 refs shippean: banners · logo-cloud (diferido ya) · team · blog · contact · content/prose-section · bento grid · flyout/mega-menu (elemento) · careers · gallery/portfolio · events · comparison section · timeline section · multi-step forms · cookie consent · popups/promos. Candidatas obvias F2.5+: banner (componente ya existe), team, contact, content-section (composición de prose+Section), bento (AutoGrid?).

Superación ratificable

Variantes como props tipadas vs N dumps duplicados; dark/brand automático por tokens vs segundo artefacto; gestión de landmarks + política de heading-level (categoría que la industria NI VENDE — los dumps hardcodean h-levels y rompen jerarquías al componer); comportamiento del canon (Accordion/Drawer/ToggleGroup) vs "Requires Flowbite JS"; count-up con reduced-motion; RTL + density + cero strings horneados (i18n by construction).

P2 — Aplicación — ✅ RECIBIDA 2026-07-21 (conteos de catálogos vivos + APIs de repo)

Panorama (los dos polos y el hueco del medio)

  • Copy-paste sin API (Tailwind Plus App UI ~40 categorías con conteos — Tables 19, Input Groups 21, Stacked Lists 15, Command Palettes 8, Empty States 6…; Flowbite ~155 blocks de app con taxonomía CRUD-céntrica (create/read/update/delete × form/modal/drawer/section — tratan "la pantalla CRUD" como unidad); Tremor Blocks 303 — señal de GRANULARIDAD: Filterbar/Table Actions/KPI Cards/Chart Tooltips como categorías de primer nivel; Mantine UI 123). Cero modelo de composición: 19 tablas = 19 snapshots divergentes sin lifecycle.
  • Config-driven (AntD ProComponents, Refine): todo props + escape-hatches xxxRender (~10 en ProLayout) → acantilado de personalización; ProTable = monolito search+table+toolbar infactorizable.
  • shadcn blocks = scaffold eject-and-own: dashboard-01 copia 19 deps de registry + 6 paquetes npm a TU árbol (tanstack-table, dnd-kit, recharts, zod…). 16 sidebars porque las variantes no pueden ser props.
  • El hueco: libertad de markup de Tailwind CON el comportamiento de ProTable = exactamente la API compuesta de partes con children. Nadie lo ocupa.

Suelos de paridad por bloque F3 (brechas concretas de nuestro v1)

Block Suelo que nos falta en v1 (decidir: subir alcance o registrar excepción)
app-shell Colapso desktop a icon-rail (además de móvil→drawer; lo dan shadcn/Mantine/AntD); variante stacked/topbar-only (el primer fork en TODAS las refs); tamaños de slot responsive ({base,sm,lg} Mantine); scroll-hide del header; geometría de chrome como CSS vars (--app-shell-*-offset Mantine) para que el contenido se posicione contra ella. Skip-link: NINGUNA ref lo trae — superación nuestra. [3 correcciones — fase 0 de F3.1, 2026-08-18, leídas las fuentes] (1) El skip-link SÍ lo traen dos referencias: Polaris Frame tiene skipToContentTarget con enlace propio, y Atlassian genera un menú entero de skip-links a partir de los slots montados (id + skipLinkTitle/skipLinkLabel, skipLinksLabel = «Skip to:», Escape cierra y mueve el foco). La superación nuestra no es tenerlos: es generarlos del mismo contrato que estampa el landmark, sin que el consumidor escriba un id. (2) El icon-rail no es de Mantine — su collapsed: {mobile, desktop} es booleano, esconder o mostrar; los que sí lo tienen son shadcn (collapsible='icon', 3rem), AntD (collapsedWidth: 80), Toolpad (mini variant) y Atlassian (colapsado + flyout al pasar el ratón). (3) Esta pista nunca miró el navigation-system actual de Atlassian, y page-layout —el que sí miró— está DEPRECADO. Lo nuevo añade suelo real: atajo Ctrl+[ opt-in que se ignora bajo un modal, redimensionado con ratón y teclado, flyout que se queda abierto mientras haya capas abiertas dentro, y useExpandSideNav (la costura exacta que pide el tour de F5).
auth Slot de social providers; slot de error/mensaje top-of-card (ProComponents message); prefill; estado de carga/mounting (Clerk fallback); la unión de vistas de Supabase es 6, no 4: falta magic-link y update-password (su ViewType = sign_in·sign_up·magic_link·forgotten_password·update_password·verify_otp — la enumeración más limpia del dominio). Nuestro OTP card SUPERA el suelo copy-paste (nadie lo shippea como block).
data-table El cuarteto estándar de toolbar ProTable = reload + density + column-setting + fullscreen (density/fullscreen a decidir explícito — density además es concern de framework en nuestro caso); persistencia de layout de columnas (columnsState.persistenceKey); clear-selection en la barra bulk (el triple {selectedRowKeys, selectedRows, onCleanSelected}); historia móvil de filtros (faceted-search en drawer, Flowbite).
dashboard Stat cards con delta de tendencia (up/down + tono) y spark-chart embebido (chartPlacement left/right/bottom); selector de periodo en panels de chart; arreglo fijo v1 OK (todas las refs lo fijan). Curiosidad adoptable: StatisticCard.Group con Operation ("=" "+" entre KPIs para expresar fórmulas).
settings Completo salvo: descripción por fila como slot formal; feedback de éxito tras guardar (Flowbite "Success Message" es categoría propia de 5).
user-menu Completo (tema/idioma SUPERA las refs — son auth-céntricas); falta showName (variante avatar+nombre) y la historia de colocación en rail colapsado (patrón nav-user de shadcn: flip a dropdown-up en pie de sidebar).
notifications ¡Ya estamos SOBRE el suelo — ninguna ref shippea el inbox completo como block nombrado! Añadir explícito: timestamps + distinción visual unread.
wizard Gate por paso async (promesa que resuelve false bloquea avance — StepsForm); current controlado para saltos del app; stepper compacto móvil; semántica de merge de valores entre pasos definida.
error-page Añadir variante maintenance (Flowbite la trata como página de primera); 403 nuestro SUPERA el suelo (casi ausente en refs).
kanban Slots de metadata en card (avatar/badge/due-date) + add-card por columna; toolbar de group-by/filtros = standout no-suelo (diferir dejando slot). Empty-state por columna: ninguna ref lo tiene — superación. shadcn NO tiene kanban block.

Superación (ratificable) + debilidades ajenas a evitar

Lifecycle real (un fix de Table propaga a data-table/dashboard/kanban vs 19 snapshots); comportamiento heredado con CERO deps nuevas (vs 6 npm de dashboard-01); el punto medio composición-con-comportamiento; a11y a nivel block (skip-links, foco toolbar↔tabla↔paginación, live-regions "N seleccionados"/"todas leídas"/cambio de paso, roving en columnas kanban — NINGUNA ref lo shippea); theming/density/RTL/i18n del sustrato (todas hardcodean dark: e inglés); coherencia cross-block vía runtime compartido (sema en danger-zone/card-drop = canal que no existe fuera). Evitar: fork-and-drift (16 sidebars), monolito ProTable, Inferencer desechable, y la lección Supabase Auth UI: murió por appearance-API cerrada — nuestro auth como composición sobre handlers del app es la forma durable.

P3 — F1 ligeros — ✅ RECIBIDA 2026-07-21 (APIs a nivel de prop; AntD 6.5 · Mantine 9.4 · Bootstrap 5.3 · Chakra v3 · Polaris · Atlaskit · Base UI 1.6)

Hueco headless verificado: Base UI, Ark, React Aria y Radix Primitives shippean CERO de los cinco — seríamos los primeros headless+contrato en sticky y anchor-nav; los únicos comparables son kits estilizados (AntD) o generadores de sitios.

sticky (F1.1)

  • La plataforma ya fijó el vocabulario: CSS @container scroll-state(stuck: top|bottom) (Chrome/Edge 133+; Firefox/Safari NO ≤2026). Espejar exactamente en data-stuck + data-edge="top|bottom" → los selectores eidos traducen mecánicamente al CSS nativo cuando aterrice; seríamos el único contrato stuck CSS-direccionable cross-browser (motor = doble centinela IO bendecido por Chrome, que además cumple nuestra doctrina anti-reflow).
  • Brechas del boceto: (1) sin props de offset — la geometría del centinela está acoplada matemáticamente al inset del sticky (el -24px del artículo de Chrome espeja el top del header): offset no es opcional; (2) sin scroll-host (AntD target, MDN: sticky se pega al ancestro con overflow más cercano AUNQUE no scrollee — el root del IO debe ser ese ancestro o la detección rompe en silencio); (3) "sin eventos v1" queda BAJO suelo (AntD onChange(affixed)) — recorte declarable, pero reservar el nombre del evento en el contrato ya; (4) borde bottom = centinela DISTINTO (threshold:[1], por ratio) — es un centinela por borde con configs diferentes.
  • Pitfalls: overflow:hidden en cualquier ancestro mata el sticky en silencio (detector dev-mode con warning); IO recorta por CADA ancestro con overflow; rootMargin solo px/% (no em); frontera exacta no dispara (centinelas con altura real, no 1px); data-stuck llega un frame tarde (async — solo styling, nunca matemática de layout); Mantine Affix NO es comparable (es un slot fixed en Portal).

anchor-nav (F1.6)

  • Suelo convergente: compensación de offset del heading (targetOffset ≠ offset del affix — AntD los separa; SIN él, el click-scroll entierra headings bajo nuestro propio sticky; par CSS: scroll-margin-top en targets); anidación con indent (CSS var de profundidad — Mantine --depth-offset, nosotros tokenizada); callback de cambio; mecanismo de re-scan (Bootstrap refresh(), Mantine reinitializeRef — nuestro ciclo de registro de partes lo cubre tipado, decirlo); regla de zona muerta al fondo (Docusaurus: sin anchor bajo el umbral → el ÚLTIMO activo; su regla de lectura: si el siguiente anchor está bajo la mitad superior → el ANTERIOR es el activo — modela "qué se está leyendo").
  • Política de hash a decidir (silencio en el boceto): AntD migró a history API (replace opt-in existe porque el push del spy contamina el historial); spy → replace o nada, click → puede push; deep-link #id al cargar fija el activo inicial.
  • aria-current: liderazgo barato — solo 1 de 5 refs lo pone (Starlight "true"; Docusaurus/Bootstrap/Mantine/AntD = clase o data-attr). Valor spec-preciso: "location"; precedente shipped: "true"; NUNCA "page" (es para páginas de un set, no secciones).
  • Scroll programático barre el spy por secciones intermedias (flicker) → suprimir spy hasta asentar o closest-wins; targets ocultos (tabs/colapsados) se saltan y re-observan al mostrar.
  • Detección: IO de banda (Starlight: rootMargin calculado del chrome, recomputado en resize) — Mantine y Docusaurus usan scroll listeners crudos (la clase de bug que nuestra doctrina mata).

empty-state (F1.2) y result (F1.3) — un esqueleto, dos componentes

  • Anatomía nuestra ≈ paridad exacta con shadcn Empty/Chakra v3. Adoptar lo que nadie combina: Atlaskit headingLevel (1–6, default 4) + headingSize DESACOPLADO (la única ref que hace bien la semántica de heading); buttonGroupLabel (nombre accesible del grupo de acciones); Polaris: UNA sola acción primaria (verbo+sustantivo), variantes secondary/tertiary; Chakra size sm/md/lg — el tamaño compacto es lo que Table/Select/Command consumirán (AntD SIMPLE preset + ConfigProvider.renderEmpty = inyección global en colecciones; los headless lo tratan como render-slot de colecciones: RAC renderEmptyState estampa [data-empty]); shadcn EmptyMedia variant="icon" → nuestro data-media-kind; clamp de ilustración (Atlaskit 160×160).
  • result = solo de AntD (nadie más lo tiene; Tailwind lo vende como páginas 404). Nuestro enum semántico > su '404' stringly-typed, PERO: (1) falta warning (7º valor de AntD; mapea natural a nuestro intent risk) — decidir explícito; (2) default status (AntD: info) — sin default es contract smell; (3) AntD NO pinta 403/404/500 de rojo (son situaciones, no fallos — ilustración neutra reemplaza al icono; nuestro media debe aceptar reemplazo total); (4) foco/anuncio tras navegación SPA (mover foco al título o live region polite — ninguna ref lo hace).

callout (F1.4)

  • Nuestros 4 intents NO cubren el vocabulario de facto (5): GitHub NOTE/TIP/IMPORTANT/WARNING/CAUTION (y Docusaurus separa note-gris de info-azul). Mapeo: neutral→NOTE · affirm→TIP · risk→WARNING · threat→CAUTION; IMPORTANT (énfasis, púrpura) no tiene hueco. Opciones: documentar la pérdida / color override sobre intent (modelo Radix: intent=semántica, color=pintura) / 5º variante. No fingir que 4 cubre 5.
  • role="alert" estático = bug de shadcn, NO copiar (MDN: alert solo anuncia en UPDATE — en carga no hace nada — y es assertive). Lo correcto: role="note" + aria-labelledby→title, con escalación opt-in (prop live/role) para callouts insertados dinámicamente (ahí sema puede sonar — cosa que ninguna ref puede expresar).
  • El title NO es heading en ninguna ref (GitHub: párrafo estilizado) — y un heading contaminaría el outline que ESCANEA nuestro propio anchor-nav (interacción real intra-suite). El intent no viaja solo en color/icono: GitHub lleva LABEL de texto visible — título default por intent = patrón robusto (color-blind + SR).
  • Radix como modelo de ejes: variant soft|surface|outline × color × size × highContrast, ortogonales. Nesting (Docusaurus): CSS tolerante a callout-en-callout.

P4 — prose + sidebar — ✅ RECIBIDA 2026-07-21 (verificación a nivel de código fuente)

Método: el agente leyó el sidebar.tsx real del registry de shadcn (new-york-v4) y el styles.js/index.js de @tailwindcss/typography en crudo — los datos de abajo son de código, no de prosa de docs.

prose — suelo de paridad

  • Lista de elementos de paridad (unión tailwind+GitHub+Mantine): h1–h6 (¡tailwind NO cubre h5/h6; GitHub y Mantine sí — cubrirlos!), p, a (+ a code, a strong), strong/em (con contextos: dentro de blockquote/th/h1–h4), blockquote (+ comillas de apertura/cierre en p:first/last-of-type::before/::after), ul/ol/li + ::marker (counters/bullets tokenizados), correcciones de margen de listas anidadas y p-en-li, dl/dt/dd, table completa (thead/tbody/tfoot/th/td, trim de padding en primera/última celda), code/pre (+ reset pre code, backticks vía code::before/::after), kbd (doble box-shadow), img / picture (+ reset picture > img) / video / figure / figcaption, hr, lead (clase, no :first-of-type), y recorte de bordes > :first-child { margin-top:0 } / > :last-child { margin-bottom:0 } (composición limpia dentro de cards). Tier GFM a decidir explícito: task lists, footnotes, alerts, details/summary, mark, sub/sup.
  • Medida: 65ch embebido por tamaño + escape (max-w-none equivalente). Tamaños: tailwind re-deriva la escala COMPLETA 5 veces (sm 14 → 2xl 24) — nuestra fiche debe declarar qué eje (size/density) mapea esto.
  • Overflow de tablas: la respuesta sin wrapper es la de GitHub — table { display:block; width:max-content; max-width:100%; overflow:auto } (tailwind no tiene ninguna: las tablas desbordan la columna).
  • El mecanismo not-prose (crítico): tailwind emite CADA selector como :where(.prose el):not(:where([class~="not-prose"], [class~="not-prose"] *)) — especificidad CERO (cualquier clase gana) + exclusión "donut" del nodo y descendientes. Limitación admitida: no se puede re-anidar prose dentro del donut. Alternativa moderna: @scope ([data-prose]) to ([data-prose-ignore]) (Baseline newly available desde finales de 2025 — evaluar contra nuestro suelo de soporte).
  • Territorio sin reclamar (superación): comillas de blockquote hardcodeadas en inglés en TODAS las refs (\201C…) → CSS quotes locale-aware vía langs; exclusión automática de componentes embebidos (todo lo que cuelgue de una raíz data-{component} se auto-excluye — las refs no pueden porque no poseen el markup de sus consumidores); dark gratis vía roles (NO copiar el patrón -invert: es un parche por colores horneados); code-in-heading (h2 code con corrección de tamaño — tailwind lo trae, Fumadocs lo presume).
  • Avisos: selectores de elemento = categoría "estructural bajo una parte" del eidos-lint — sancionarlo deliberadamente o el recipe lintará invalid; propiedades lógicas (border-inline-start) desde el día uno; anchors de heading son capa docs-shell (patrón a11y correcto: link DESPUÉS del heading, à la Starlight), no capa prose.

sidebar — suelo de paridad

  • shadcn = 23 partes + hook (Provider · Sidebar · Trigger · Rail · Inset · Input · Header · Footer · Separator · Content · Group · GroupLabel · GroupAction · GroupContent · Menu(ul) · MenuItem(li) · MenuButton · MenuAction · MenuBadge · MenuSkeleton · MenuSub(ul) · MenuSubItem · MenuSubButton(a) · useSidebar). Nuestro boceto tiene 8 — demasiado grueso: item funde MenuItem (li posicionador) + MenuButton (interactivo, data-active, host del tooltip), y sin ese split no hay dónde colgar action/badge/skeleton/sub-nivel. shadcn-svelte lo porta 1:1 con dot-notation y Svelte 5 (bind:open, snippets para asChild) — el mapeo a nuestro idioma está probado.
  • Dos ejes, no uno: estado data-state="expanded|collapsed" + modo collapsible="offcanvas|icon|none" (shadcn estampa data-collapsible SOLO estando colapsado — ojo si espejamos nombres). Nuestro data-rail fusionaba ambos ejes → separar. Rail además es una PARTE física (franja de 16px toggle en el borde, tabIndex -1, cursores direccionales), no un estado.
  • Props/constantes de referencia: side left|right (table stakes), variant sidebar|floating|inset (diferible declarándolo), widths 16rem / 18rem móvil / 3rem icon como TOKENS (no consts TS), cookie sidebar_state 7d con lectura SSR → defaultOpen (evita flash de hidratación), atajo global Cmd/Ctrl+B con preventDefault (¡secuestra la negrita de cualquier editor embebido — el nuestro se scope-a fuera de contextos editables!), tooltips en modo icon montados SIEMPRE y suprimidos con hidden (no mount/unmount), móvil = Sheet <768px (nuestro Drawer con props label/description, no hacks sr-only).
  • Exclusiones v1 legales SOLO con costuras: open/onOpenChange controlado + defaultOpen + toggle() expuesto en el provider — la persistencia y el atajo viven en app-land únicamente si esas costuras existen desde v1; si no, es rediseño posterior.
  • A11y — todas las refs suspenden: shadcn NO tiene landmark <nav>, NI aria-current (solo data-active), atajo sin aria-keyshortcuts, rail inalcanzable por teclado. El patrón correcto es APG Disclosure Navigation: nav landmark + botones aria-expanded/aria-controls + links con aria-current="page" + Esc devuelve el foco al trigger. Superación directa: emitir aria-current del MISMO prop que estampa data-active.
  • Nadie headless lo tiene (Radix/Base/Ark/React-Aria confirmado): el sidebar canónico es invención del tier estilizado — espacio abierto con shadcn como estándar de facto.
  • Pitfalls: animar width = layout por frame (aceptado por la industria; nosotros: offcanvas por transform y width-anim solo en icon, lecturas vía dom.measure); submenús en modo icon shadcn los OCULTA (nuestro DropdownMenu/Popover flotante en rail = superación, es el mejor comportamiento de AntD Menu); overscroll-behavior: contain en Content; RTL lógico desde el día uno (shadcn necesitó un changelog entero de retrofit); jitter de will-change en raíles finos a DPR≠1 (memoria).

P5 — Docs — ✅ RECIBIDA 2026-07-21 (Starlight 0.41 · Fumadocs 16.11 · Docusaurus 3.10 · VitePress 1.6/2α · Nextra 4.6 · Mintlify)

Suelo del docs-shell (convergencia de los 6)

3 regiones con raíles sticky de scroll independiente + header sticky; sidebar con ≥3 niveles, grupos colapsables, profundidad default-open, active trail auto-expandido, badges, drawer móvil; TOC h2–h3 configurable con scrollspy, móvil = popover/dropdown, back-to-top; búsqueda = command palette ⌘K con índice estático (Pagefind/MiniSearch/Orama); breadcrumb del árbol (solo anidado); prev/next del orden del árbol; fila meta (edit-on-GitHub + last-updated); dark light/dark/system sin flash; slots reservados: banner de anuncio, sidebar top/bottom, page-actions, versión/idioma. Fumadocs es el benchmark y el ÚNICO que shippea el shell como componentes reutilizables (DocsLayout/DocsPage con sistema de slots + fumadocs-core headless; anchos TOKENIZADOS --fd-sidebar-col/--fd-toc-width — validación de nuestro enfoque). Diferenciadores adoptables: tabs de sección en sidebar (Fumadocs), TOC estilo "clerk" (raíl de pulgar), auto-colapso de hermanos (Docusaurus), acciones AI (copy-page-as-Markdown, open-in-Claude/ChatGPT, llms.txt, negociación de contenido .md — table stakes 2026 y casi gratis: nuestro corpus YA es Markdown).

Suelo del code-showcase

Preview + código + copy SIEMPRE; barra de filename con icono; números de línea; marcas de línea/palabra; diff (++/--); código largo colapsable (shadcn: 3 líneas + gradiente + expandir); tabs de package manager (npm/pnpm/yarn/bun de un solo bloque); grupos multi-archivo con syncKey site-wide (Starlight); controles de preview: alineación + toggle RTL (el de shadcn lleva disclaimer "AI-translated" — el nuestro iría con langs real). ⚠️ La mayoría pertenece al canon code-block: verificar qué soporta nuestro recipe ANTES de F4.2; cada carencia = gap de canon flaggeado (regla de admisión).

Props-table: generación y suelo de presentación

  • Suelo de presentación = Ark UI: secciones POR PARTE (props + data-attributes + ARIA + keyboard por parte) + tabla de contexto/API. Nuestro <PropsTable> plano queda por debajo — el morfo ya trae el seccionado; renderizarlo.
  • Generación en refs: manual (Radix — puro riesgo de drift) · build-time docgen → JSON (Mantine, Ark generate-type-docs.ts) · TS-Compiler-API en build (Fumadocs AutoTypeTable, solo server).
  • Vía Svelte para props TS (la cuestión abierta de F4.3): sveld DESCALIFICADO (sin resolución semántica — ResponsiveProp<T> quedaría texto opaco); svelte-docgen pre-v1; la ruta = svelte2tsx + TS Compiler API en build-time → JSON por componente (Storybook migró a ella precisamente por runes; PRs #29423/#28492).

Brechas señaladas en NUESTRAS fiches F4/F1 (leyó el plan — 10 puntos)

  1. F4.1 slots insuficientes: faltan topbar, banner, sidebar top/bottom, page-actions, opciones de breadcrumb, fila meta, slots versión/idioma. D-BLK.6 manda el wiring al app — pero el shell debe RESERVAR los puntos de montaje.
  2. ⚠️ COLISIÓN F1.7 vs docs-tree (firmar ANTES de construir F1.7): el sidebar de app v1 (grupos+rail) no cubre árbol profundo, active-trail auto-expand, auto-colapso, default-open depth, scroll-active-into-view; y un árbol de 100 páginas como children choca con B-5 → o el componente canónico sidebar/tree es data-driven (precedente: Menubar ya lo es), o hay pieza canónica nueva (nav-tree). Decisión de usuario.
  3. ⌘K sin decidir: Command existe; el registro global de atajo está en F5. Todas las refs lo dan día uno. Decidir: listener app-land documentado o adelantar el art shortcuts.
  4. TOC móvil sin mecanismo en F1.6/F4.1 (refs: popover o dropdown) + anchor-nav sin config min/max de nivel.
  5. prose sin heading-anchors: Starlight 0.34 los hizo core con el patrón a11y correcto (link DESPUÉS del heading + label generada); sin ellos mueren los deep-links del TOC. + iconos de external-link (VitePress).
  6. F4.2 bajo suelo (lista de arriba) y los chips de tema/density/dir diferidos son EL FOSO, no un nice-to-have — ver superación.
  7. F4.3 por-parte (suelo Ark) + tabla de eventos familia·verbo·intent.
  8. Dirección TS-props: fijar ya la ruta svelte2tsx build-time.
  9. Cero acciones AI en los sketches (llms.txt, copy-as-md — casi gratis).
  10. Falta last-updated/edit-link y la decisión del skip-link (diferida en F2.1) debe aterrizar antes de F4.1.

Superación (la más fuerte de las 6 pistas)

Props tables que no pueden mentir: compileMorfo da partes/attrs/ARIA/ keyboard/eventos EN RUNTIME del mismo objeto que ejecuta el componente — cero drift por construcción, CI puede exigir tabla completa por componente PASS; la tabla de keyboard de nadie más ES el plan de teclado real. Tabla de eventos semántica (familia·verbo·intent·canales) que ninguna ref tiene. Ejes de tema por demo (theme/density/contrast/RTL/motion vivos con tokens reales — imposible para SSG estáticos). Búsqueda contract-aware (Command indexando morfos: "¿quién maneja Escape?", "¿quién estampa data-stuck?" — Pagefind indexa texto, no contratos). Scrollspy con disciplina de reflow demostrable por uix.perf; sema demoable por evento; dogfooding = el shell ES el test de aceptación de F4.

P6 — Svelte — ✅ RECIBIDA 2026-07-21 (inventarios por llms.txt + npm; versiones al día)

El paisaje de blocks en Svelte (los 3 actores reales)

Oferta Qué shippea Modelo
shadcn-svelte (CLI 1.4.2, 82k dl/wk; sobre Bits UI 2 = 821k dl/wk) 58 blocks first-party, SOLO app: 16 sidebars · 15 auth (login/signup/OTP) · 26 calendar · 1 dashboard · 7 familias de charts (sobre LayerChart, 180k dl/wk). CERO marketing sections (igual que upstream) copy-paste vía registry CLI (registry.json), llms.txt, visual builder /create
Flowbite Svelte Blocks v2.1.0 (MIT, Sv5+TW4) El único con marketing (~29 tipos: hero, pricing, CTA, FAQ, testimonials, newsletter, footer, 404/500/maintenance, cookie, onboarding…) + application (~20: CRUD en modals/drawers, advanced tables, faceted search, sidenav) paquete npm; estética datada; theming superficial
sv-blocks (port Tailark) 150+ marketing blocks para shadcn-svelte + 60 "Veil Kit" jsrepo CLI + MCP server (instalables desde Cursor/Windsurf)

Resto: Skeleton v5 (2026-07-17; theming profundo, CERO blocks), Melt original congelada (~16 meses), melt next 0.44 pre-1.0, Ark UI Svelte 5.22 (45+ headless, org Chakra, cadencia semanal — vigilar), HeroUI sigue React-only ("Svelte planeado sin fecha"), plantillas admin = repos, no blocks componibles. Todo el paisaje asume Tailwind v4 + copy-paste.

Huecos objetivos del ecosistema (nadie los tiene)

docs-shell · settings/preferences · billing/checkout · empty/error states como SISTEMA · data-table CRUD componible (Flowbite = snippets sueltos) · blocks con i18n/RTL · a11y auditada a nivel sección · blocks sobre tokens no-Tailwind · capa perceptiva. Nadie combina componentes + theming profundo + blocks: shadcn tiene blocks sin theming profundo; Skeleton theming sin blocks; Flowbite blocks con theming superficial. Esa es la ventana.

Listón de paridad Svelte (para reclamar "la oferta más completa")

  1. App-shell: cubrir la matriz de los 16 sidebars de shadcn con 1 block parametrizado + presets, documentando la equivalencia variante-a-variante (no competir en cardinalidad copy-paste).
  2. Auth: login/signup/OTP/forgot (15+ layouts entre shadcn y Flowbite).
  3. Dashboard completo + stat/chart cards sueltos; galería de charts con variantes día uno (lección LayerChart: shadcn no escribió motor, montó galería).
  4. CRUD: tabla avanzada + create/update en modal Y drawer + delete-confirm (el set Flowbite que shadcn no tiene).
  5. Marketing: la unión Flowbite+sv-blocks ≈ 20 tipos — nuestra F2 (10) debe contrastarse contra esa unión (banners/cookie/team/blog/contact/onboarding no están en F2 → decisión explícita).
  6. Calendar: shadcn 26 blocks; con nuestra riqueza de componentes bastan menos, cubriendo range/presets/time/booked.

Amenazas / lecciones arquitectónicas (para decidir, no resolver en silencio)

  • La cultura copy-paste GANÓ la distribución. Un tier empaquetado necesita historia de personalización estructural (partes/snippets por zona — nuestra API composicional ya lo es) y quizá un camino de "eject" block→código propio.
  • Registry + llms.txt + MCP = table stakes 2026: los blocks deberían ser enumerables/instalables por agentes (encaja con la vía agentiva del proyecto). Candidato a F5/decisión.
  • Zag/Ark = la vara de a11y cross-framework: conviene poder DEMOSTRAR la nuestra (matriz teclado/ARIA por block, generada del morfo — inédito).
  • Tailwind v4 es el sustrato universal: zero-dep es diferenciador (sin lock-in) y fricción a la vez — tensión estratégica del usuario.
  • Los upgrades propagan en nuestro modelo (composición) vs congelación copy-paste — EL argumento; requiere la historia de personalización de arriba para sostenerse.

Síntesis (6/6 pistas — 2026-07-21)

Los suelos de paridad por ítem viven en cada sección de pista (arriba); las fases 0 del plan contrastan contra ellos. Lo transversal:

Cinco conclusiones

  1. La ventana estratégica es real y está abierta: nadie — en ningún ecosistema — combina componentes + theming profundo + blocks con comportamiento. En Svelte el espacio "sistema integrado" está vacío (shadcn-svelte: blocks sin theming profundo; Skeleton: theming sin blocks; Flowbite: blocks con theming superficial). El casi-par global es Untitled UI React (componentes con props de verdad) — React-only, PRO-gated, sin tokens/RTL/density. En los 7 componentes F1, los headless (Radix/Base/Ark/React-Aria) shippean CERO.
  2. El patrón de brechas de nuestro v1 es consistente: los esqueletos son correctos; lo que falta es (a) la SEGUNDA variante convergente del mercado (feature-split, testimonial-spotlight, faq-lista, hero-media, cta-justified), (b) las costuras de estado (open/onOpenChange/toggle en sidebar; error/loading slots en auth), y (c) los ejes que el mercado resuelve con N copias y nosotros con props.
  3. La distribución copy-paste ganó: registry + llms.txt + MCP son table stakes 2026. Nuestro contraataque es estructural (upgrades que propagan, variantes tipadas) pero necesita la historia de personalización (composición por partes = ya la tenemos) y la enumerabilidad por agentes (candidata a iniciativa propia).
  4. El liderazgo a11y es barato y sistémico: las referencias suspenden en TODO el tablero (sin landmarks ni gestión de heading-level en secciones, sin aria-current en 4 de 5 scrollspies, role="alert" estático como bug shipped, atajos globales sin scope). Nuestra doctrina ya obliga a lo correcto; solo hay que no copiarles.
  5. Alinearse con la plataforma donde ya estandarizó: data-stuck/ data-edge espejando scroll-state(stuck:); @scope con donut como mecanismo moderno de prose (con fallback :where()+donut); heading anchors con el patrón Starlight; aria-current="location|true".

Enmiendas al plan

Aplicadas (no cambian alcance): regla de trabajo nueva en el plan §4 — toda fase 0 contrasta contra este dossier ANTES de diseñar; puntero de colisión en la fiche F1.7 (sidebar-app vs árbol-docs / B-5).

A decisión del usuario (cambian alcance — presentadas 2026-07-21):

# Decisión Recomendación
E-1 Colisión F1.7: el árbol de navegación docs (anidación profunda, active-trail, data-driven) no cabe en el sidebar-app v1 y choca con B-5 Componente canónico NUEVO nav-tree data-driven (precedente: Menubar ya es data-driven); sidebar queda app-céntrico; F4.1 compone nav-tree
E-2 Filosofía de alcance v1: ¿subir los v1 al suelo de paridad investigado, o construir fino y pasar una ola v1.1 de paridad? Suelo de paridad = v1 (el encargo fue "a la par y cuanto menos superarlo"); las fases 0 dimensionan cada subida con el dossier
E-3 Categorías de la unión no planeadas: banner · team · contact · content-section (· bento · gallery · cookie-consent…) Añadir a F2 las 4 baratas (banner compone el componente existente; content-section = prose+Section); resto a F5 con disparador
E-4 Distribución registry/llms.txt/MCP de blocks Registrar como iniciativa PROPIA en next-features (no engorda este plan); llms.txt del corpus docs = barato y encaja con F4
E-5 ⌘K global (F4/command): ¿adelantar el art shortcuts o listener app-land? Listener app-land documentado en el README del block; el art shortcuts mantiene su disparador F5 (≥2 consumidores)

Ángulos de superación ratificables (consolidado)

  1. Variantes como props tipadas + upgrades que propagan (vs N dumps).
  2. Landmarks + política de heading-level como API del block (la industria NI LO VENDE).
  3. A11y por encima de toda referencia: aria-current del mismo prop que data-active, role=note+labelledby, APG focus-return, atajos scoped, live-regions en bulk/steps/inbox.
  4. Tokens: dark/brand/density/RTL gratis por sustrato (vs dark como segundo artefacto a la venta).
  5. i18n by construction (cero strings horneados; comillas de blockquote locale-aware — territorio sin reclamar).
  6. data-stuck = polyfill del contrato CSS futuro; prose con auto-exclusión de componentes embebidos (nadie puede: no poseen el markup de sus consumidores).
  7. Props tables runtime desde compileMorfo que no pueden mentir + tabla de eventos semántica + búsqueda contract-aware ("¿quién maneja Escape?").
  8. Ejes de tema por demo (theme/density/contrast/RTL/motion vivos) = el foso del showcase; sema demoable por evento.
  9. Count-up con reduced-motion, submenús flotantes en rail, kanban con roving focus y empty por columna — cada uno literalmente imposible o ausente en las refs.
  10. Rendimiento demostrable: scrollspy/sticky por IO vía adom con uix.perf probando cero forced-reflow (ninguna ref puede afirmarlo).

Powered by TurnKey Linux.