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/CONTINUE-blocks.md

7.7 KiB

CONTINUE — F2 blocks de sitio (handoff 2026-07-23)

Estado al parar: F1 CERRADA (8/8 componentes canon) y F2.1 site-header HECHA — el primer block del tier, que además fijó la superficie de demo para los 13 que quedan. Plan maestro: docs/process/PLAN-blocks.md (§F2 y el registro §7). Todo commiteado y pusheado a gita/alpha-0.1-sec-dom; último commit ae7b4f8c3.

Lo siguiente

F2.6 faq (ficha en PLAN-blocks.md §F2.6). Compone Section + Container (medida estrecha) + Heading + Accordion. .Item = proxy fino de Accordion.Item (LEER el README del Accordion antes — respetar su API real). v1 = una columna; la brecha del dossier es la lista estática 2/3 columnas + la cola «Still have questions?» (scope-approval). Después: stats-band → cta → newsletter → site-footer → banner → team → contact → content-section.

F2.4 pricing + F2.5 testimonials HECHOS. pricing = primer compound CON CONTEXTO (el Switch escribe el periodo, los PlanPrice lo leen; contexto reactivo vía context.ts, getter sobre $bindable, como CardGroup; el block NUNCA formatea moneda). testimonials = compound SIN contexto (.Item repite). Lecciones nuevas para los que vienen:

  • Escalas donor activadas = green/indigo/orange/plum/teal. Una escala NO activada (cyan/ruby/amber/jade) en color cae en SILENCIO a primary. Usa las activadas.
  • Card NO tiene variant surface (solo soft/solid/outline/ghost); soft neutral es casi invisible en claro → usa outline para tarjetas que deben leerse.

F2.1 site-header · F2.2 hero · F2.3 feature-grid · F2.3b feature-split HECHOS, + primitivo canon Mockup ($uix/eidos/components/mockup: chrome browser/ phone/plain + url) — úsalo para toda media enmarcada en los blocks que vienen (pricing screenshots, testimonials, etc.), NO falsees un screenshot por demo. Regla de forma del tier (NO re-decidir): compound solo cuando las partes COORDINAN o SE REPITEN (feature-grid.Item, pricing.Plan, faq.Item — partes que el app itera); slots de snippet para secciones de layout (hero, site-header, cta, stats-band). Lecciones de feature-grid que ahorran sangre en los compound que vienen:

  • Sub-componentes de bloque extienden los props del canon que envuelven (BoxProps, StackProps, HeadingProps…), nunca HTMLAttributes — el style: string|null del atributo HTML crudo choca al hacer spread en el canon (+ "union type too complex").
  • .Items/.List como envoltorio de la rejilla deja la cabecera fuera sin hacks de grid-column.
  • Chips de icono: Surface variant="solid", no soft (el soft en claro es casi blanco, oklch 0.99, invisible).
  • Un slot de snippet cuyo nombre sea un atributo HTML (title, background, media…) colisiona → string & Snippet. Solución: Omit<HTMLAttributes, '…' | 'title'> o nombra el slot distinto (backdrop). Pasó en hero.
  • svelte-check filtrado por ruta con backslashes: escapa bien o filtra por nombre de fichero (rg -i "HeroSite"), no por routes\\blocks\\… — un patrón mal escapado oculta errores propios.

Deuda a decisión tuya (nuevo)

Feature-split / alternante (texto junto a screenshot, lados alternos) — la brecha nº1 de F2 del dossier. Es otra disposición (filas de 2 columnas, no rejilla de iconos): candidato a block hermano feature-split. En los Gaps de feature-grid. Sin decidir.

Cada uno entra por el contrato B (docs/architecture/blocks.md) con fase 0 ligera obligatoria: mirar el equivalente en ≥2 catálogos del dossier (docs/process/RESEARCH-blocks-references.md) y anotar en el README del block qué se adopta y qué se descarta.

La plantilla ya existe — cópiala, no la reinventes

Un block terminado son estos ficheros (ejemplo real: site-header):

src/uix/blocks/{kebab}/
├── README.md            # Función · Mapa de composición · Decisiones · Gaps
├── index.ts             # export del compound + tipos
├── types.ts             # props (todo contenido entra por snippets, B-5/B-7)
└── {kebab}.svelte       # composición: solo componentes del canon, sin CSS

web/routes/blocks/{kebab}/
├── +page.svelte         # BlockDemo + controles vivos + pestañas de doc
├── {Name}Site.svelte    # el block dentro de contenido REAL de producto
└── preview/
    ├── +layout@.svelte  # `@` resetea el layout: la vista previa es su página
    └── +page.svelte     # sirve {Name}Site leyendo la URL

Y luego: marcar shipped: true en web/routes/blocks/_lib/catalog.ts (raíl y galería leen esa única fuente) y npm run blocks:check.

Reglas que ya costaron sangre (no las re-aprendas)

  • El block se enseña A SANGRE en la página. Nada entre el block y el borde: ni marco con relleno, ni caja con scroll, ni cromo pegajoso encima. Medido: un Card desplazaba 21px un header con offset: 0 (su recipe pinta con --card-padding-*, que padding={0} de la capa Box no alcanza), y un position: sticky dentro de un div con scroll es un comportamiento que nadie vive. Si un block se ancla a algo, se mide contra lo que se anclará en producción.
  • Los anchos de dispositivo (375/768) van por la ruta preview en iframe, y es opt-in: en dev, dos documentos sin empaquetar a la vez agotan las conexiones del navegador (ERR_INSUFFICIENT_RESOURCES mata las DOS páginas).
  • Cada prop público, un control vivo en la demo; los ejes de sección (tema, idioma, dirección, densidad) ya los da el shell, no los repitas.
  • Nada de backticks de markdown dentro de <Text>: se ven literales. Lo que es código va en <Code>.
  • Ojo con las variables de layout que heredan. justify de Group se hereda a los clusters anidados (pon justify explícito) y las de Box YA no heredan desde 2026-07-23 (docs/theming/changelog.md §46).
  • Un hueco del canon se registra, no se falsea. Si al componer falta algo, va a los Gaps del block como candidato a canon y la demo usa lo que hay.

Deuda declarada (decisiones tuyas pendientes)

  1. CTA que navega y parece botón — RESUELTO 2026-07-23 por composición, no por prop nueva: el child (asChild) de Button entrega ahora un snippet content, así que <a href {...props}>{@render content()}</a> recibe la pintura sólida COMPLETA (icono · etiqueta · endIcon · spinner) y soma deja de estampar type en un elemento que no es suyo. Button sigue sin href y Link sigue poseyendo la navegación. Doctrina: README de eidos Button §«CTA que navega». Úsalo tal cual en el hero (su CTA primario es exactamente esto).
  2. pricing, feature-grid tienen brechas del dossier §P1 que el plan v1 no cubre (tabla comparativa de precios, split/alternante texto-screenshot). Cada fase 0 las presenta como scope-approval, no se deciden solas. (La de hero —fondo cover— ya se decidió y está hecha: layout background.)
  3. Box/Surface flex/grow no crecen un hijo flex (encontrado en hero): <Surface flex={1}> se quedó a 0-width (flex: 0 1 auto, el --box-flex no surtió efecto); ningún componente shipped usa la prop. La demo usó Grid (tracks 1fr). Revisar el cableado end-to-end de --box-flex/--box-grow.

Estado de gates al parar

  • npm run blocks:check verde (2 blocks).
  • npm run check sin errores propios (la deuda restante es ajena; p.ej. web/routes/demos/heroscrolling es de otra sesión).
  • vitest src/uix/eidos 353/353 · vitest src/uix/morfo 114/114.
  • contracts.test.ts: 3 fallos AJENOS conocidos (menubar DOM-write · radio-group data-ready · claves camelCase de aura), de sesiones paralelas.

Powered by TurnKey Linux.