docs(blocks): registro de F2.1, doctrina de demo del tier y handoff
Documentación al día de lo que se cerró hoy y handoff para retomar mañana.
- `PLAN-blocks.md` §7: **F2.1 `site-header` HECHA** con sus siete commits, la
fase 0 contra el dossier §P1, el landmark que le faltaba a `NavigationMenu`
(arreglado en el canon, no parcheado en el block), el hueco del CTA que
navega y parece botón (registrado, no falseado) y el defecto de framework
que destapó la demo.
- `theming/changelog.md` §46: las 44 variables de cascada de `Box` dejan de
heredarse. Un `Section` regalaba su padding a cada descendiente —la galería
arrastraba ~300px de aire desde F0— y los hijos heredaban anchos y `display`
ajenos. `@property { inherits: false }`, radio verificado sin regresiones.
Lección: una variable que un componente escribe para SÍ MISMO debe declararse
`inherits: false`; si no, deja de ser un prop y se vuelve un contagio.
- `architecture/blocks.md` B-9: la demo de un block se construye sobre el
harness compartido y el block se enseña A SANGRE — nunca dentro de un marco
con relleno ni de una caja con scroll, porque eso cambia lo que el block
hace.
- `src/uix/blocks/README.md`: anatomía de la demo (harness, `{Name}Site`, ruta
`preview`, `DocRow`, catálogo único, ejes en el shell).
- `CONTINUE-blocks.md` (nuevo): handoff — qué toca (F2.2 `hero`), la plantilla
de ficheros para copiar, las reglas que ya costaron sangre (a sangre, iframe
solo para anchos de dispositivo, cada prop un control, nada de backticks en
`<Text>`, ojo con las variables que heredan), la deuda declarada que es
decisión del usuario y el estado exacto de los gates.
Gates al parar: `blocks:check` verde · `svelte-check` 73 errores, todos deuda
ajena (0 propios) · `vitest src/uix/eidos` 353/353 · `contracts.test` con los
3 fallos ajenos conocidos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
# 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.
|
feat(blocks): F2.4 `pricing` — el primer compound CON CONTEXTO del tier
La sección de planes: un toggle de periodo sobre una fila de planes, uno
destacado. Es el primer block cuyas partes se COORDINAN de verdad (no solo se
repiten como en feature-grid/split): el `Switch` escribe el periodo de
facturación y cada `PlanPrice` lo lee. Esa coordinación es lo que gana un
contexto compartido — la forma más fuerte de compound.
`<Pricing bind:period>` + `.Header` + `.Switch` + `.Plans` + `.Plan`(featured,
badge) + `.PlanName`/`.PlanDescription`/`.PlanPrice`/`.PlanFeatures`/
`.PlanFeature`/`.PlanAction`.
- **Contexto reactivo** (`context.ts`): la raíz provee el periodo como getter
sobre un `$bindable`; el `Switch` (un `ToggleGroup`) lo escribe, el
`PlanPrice` lo lee y muestra el snippet `monthly` o `annual`. Mismo patrón que
`CardGroup`. `period` es bindable por si la app quiere observarlo.
- **El block NUNCA formatea moneda**: la app compone `FormatNumber` dentro de
los snippets de precio (B-7). El block posee el switch, no el dinero.
- `.PlanAction` fija el CTA al borde inferior de la tarjeta
(`margin-block-start: auto`) para que una fila de planes alinee sus botones
aunque tengan distinto nº de features; `.Plan` con `align="start"` deja los
checks en columna limpia; `featured` da acento (borde primary) + elevación.
Demo (`web/routes/blocks/pricing/`): full-bleed + ruta `preview`, tres planes
(Pro destacado en el centro) con el toggle mensual/anual vivo.
Hueco a decisión del usuario (Gaps del block): la **tabla de comparación**
(features × planes) — la brecha recurrente del dossier en pricing. Es una tabla,
no una fila de tarjetas: candidato a hermano `pricing-table`. Presentado, no
resuelto.
Verificado en navegador: el toggle cambia los TRES precios a la vez (0/29/99 →
0/23/79), tarjetas de igual alto con CTAs alineados, featured con acento, en
claro/oscuro × LTR/RTL. `blocks:check` verde (5 blocks) · `svelte-check` sin
errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
|
|
|
|
|
**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.
|
docs(blocks): registro de F2.1, doctrina de demo del tier y handoff
Documentación al día de lo que se cerró hoy y handoff para retomar mañana.
- `PLAN-blocks.md` §7: **F2.1 `site-header` HECHA** con sus siete commits, la
fase 0 contra el dossier §P1, el landmark que le faltaba a `NavigationMenu`
(arreglado en el canon, no parcheado en el block), el hueco del CTA que
navega y parece botón (registrado, no falseado) y el defecto de framework
que destapó la demo.
- `theming/changelog.md` §46: las 44 variables de cascada de `Box` dejan de
heredarse. Un `Section` regalaba su padding a cada descendiente —la galería
arrastraba ~300px de aire desde F0— y los hijos heredaban anchos y `display`
ajenos. `@property { inherits: false }`, radio verificado sin regresiones.
Lección: una variable que un componente escribe para SÍ MISMO debe declararse
`inherits: false`; si no, deja de ser un prop y se vuelve un contagio.
- `architecture/blocks.md` B-9: la demo de un block se construye sobre el
harness compartido y el block se enseña A SANGRE — nunca dentro de un marco
con relleno ni de una caja con scroll, porque eso cambia lo que el block
hace.
- `src/uix/blocks/README.md`: anatomía de la demo (harness, `{Name}Site`, ruta
`preview`, `DocRow`, catálogo único, ejes en el shell).
- `CONTINUE-blocks.md` (nuevo): handoff — qué toca (F2.2 `hero`), la plantilla
de ficheros para copiar, las reglas que ya costaron sangre (a sangre, iframe
solo para anchos de dispositivo, cada prop un control, nada de backticks en
`<Text>`, ojo con las variables que heredan), la deuda declarada que es
decisión del usuario y el estado exacto de los gates.
Gates al parar: `blocks:check` verde · `svelte-check` 73 errores, todos deuda
ajena (0 propios) · `vitest src/uix/eidos` 353/353 · `contracts.test` con los
3 fallos ajenos conocidos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
|
feat(blocks): F2.3b `feature-split` — la brecha nº1 del dossier, con Mockup
La sección que las 5 refs shippean y que va justo tras el hero: una afirmación
de producto junto a un screenshot, alternando lados fila a fila. Otra
disposición que la rejilla de iconos de `feature-grid`, así que block hermano
(decisión del usuario), no una variante turbia dentro de aquél.
Compound —la `.Row` se repite—: `<FeatureSplit>` + `.Row` (`reversed`, slot
`media`) + `.Eyebrow` + `.Title` + `.Text` + `.Features`/`.Feature` (checklist)
+ `.Actions`. El block coloca; la app pone la copy y la media.
- `reversed` mueve la media al lado de inicio vía `grid-column` (Box expone
`gridColumn`/`order`), dejando la copy SIEMPRE primera en el DOM — el orden de
lectura y el foco no cambian aunque el screenshot salte de lado.
- El check de cada `.Feature` es decorativo (`aria-hidden`): la palabra lleva el
significado.
- La media se COMPONE con el primitivo `Mockup`: la demo enseña cromo de
navegador (dashboard) y de teléfono (app), cerrando el hueco de «tratamiento
de media» del dossier de raíz en vez de falsearlo.
`.Row` usa un tipo limpio (no `HTMLAttributes`) porque su slot `media` colisiona
con el atributo HTML homónimo; el resto de sub-partes extienden los props del
componente canon que envuelven (lección de feature-grid).
Demo (`web/routes/blocks/feature-split/`): full-bleed + ruta `preview`, con
control del nº de filas y del lado inicial; 3 filas con Mockup navegador/teléfono.
Verificado en navegador (Playwright, módulos frescos): filas alternas en
claro/oscuro × LTR/RTL, `reversed`, el orden de lectura copy-primero, y los dos
cromos de Mockup. `blocks:check` verde (4 blocks) · `svelte-check` sin errores
propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
**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
|
feat(blocks): F2.3 `feature-grid` — el primer block compound del tier
`<FeatureGrid>` + `.Header` + `.Items` + `.Item` + `.ItemIcon`/`.ItemTitle`/
`.ItemText`: una cabecera sobre una rejilla responsive de features
(icono · título · texto). Es la sección que responde «qué hace», la nº1 tras el
hero.
Primer block COMPOUND del tier, y aplica la regla de forma que fijamos: el
`.Item` se REPITE (el app mapea sobre N features) → gana sub-componentes, donde
`hero`/`site-header` usan slots de snippet (partes fijas de layout). Las partes
no coordinan —sin contexto ni estado entre ellas—: la rejilla es del padre, las
celdas del app. `.Items` es el envoltorio honesto de la rejilla (`AutoGrid`), que
deja la cabecera fuera sin un `grid-column: 1/-1` a pelo.
- El block coloca (Section · Container · AutoGrid · Surface · Heading · Text); el
app pone todo el contenido por children (B-7).
- `.Items` fluido por `minChildWidth` (tantas columnas como quepan) o `columns`
fijas; `.Item` `align` start/center; `.ItemIcon` chip `Surface`; `.ItemTitle`
`Heading` h3; `.ItemText` `Text` apagado.
- `align` de sección (center/start) coloca la cabecera coherente con las columnas.
Dos cosas encontradas al construir, resueltas:
- **Los sub-componentes de bloque extienden los props del componente canon que
envuelven** (`BoxProps`, `StackProps`, `HeadingProps`…), **no
`HTMLAttributes`**: el `style: string|null` del atributo HTML crudo choca con
el `style: string` del canon al hacer spread (+ "union type too complex").
- **`.ItemIcon` por defecto `solid`, no `soft`**: el soft-primary en claro es
casi blanco (oklch 0.99) → el chip era invisible; solid da el chip con glifo
on-solid (la tinta de contraste la pone `Surface`).
Demo (`web/routes/blocks/feature-grid/`): full-bleed + ruta `preview`, con
control de columnas (fluido/2/3/4), align, nº de items y dir; 6 features con
iconos del canon.
Hueco a decisión del usuario (en los Gaps del block): el **feature-split/
alternante** (texto junto a un screenshot, lados alternos) — la brecha nº1 del
dossier — es otra disposición (filas de 2 columnas, no rejilla de iconos):
probablemente un block hermano `feature-split`. Presentado, no resuelto.
Verificado en navegador (Playwright, módulos frescos): center/start × claro/
oscuro × LTR/RTL, columnas fluidas y fijas, 3/4/6 items, chips visibles.
`blocks:check` verde (3 blocks) · `svelte-check` sin errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
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).
|
feat(blocks): F2.3b `feature-split` — la brecha nº1 del dossier, con Mockup
La sección que las 5 refs shippean y que va justo tras el hero: una afirmación
de producto junto a un screenshot, alternando lados fila a fila. Otra
disposición que la rejilla de iconos de `feature-grid`, así que block hermano
(decisión del usuario), no una variante turbia dentro de aquél.
Compound —la `.Row` se repite—: `<FeatureSplit>` + `.Row` (`reversed`, slot
`media`) + `.Eyebrow` + `.Title` + `.Text` + `.Features`/`.Feature` (checklist)
+ `.Actions`. El block coloca; la app pone la copy y la media.
- `reversed` mueve la media al lado de inicio vía `grid-column` (Box expone
`gridColumn`/`order`), dejando la copy SIEMPRE primera en el DOM — el orden de
lectura y el foco no cambian aunque el screenshot salte de lado.
- El check de cada `.Feature` es decorativo (`aria-hidden`): la palabra lleva el
significado.
- La media se COMPONE con el primitivo `Mockup`: la demo enseña cromo de
navegador (dashboard) y de teléfono (app), cerrando el hueco de «tratamiento
de media» del dossier de raíz en vez de falsearlo.
`.Row` usa un tipo limpio (no `HTMLAttributes`) porque su slot `media` colisiona
con el atributo HTML homónimo; el resto de sub-partes extienden los props del
componente canon que envuelven (lección de feature-grid).
Demo (`web/routes/blocks/feature-split/`): full-bleed + ruta `preview`, con
control del nº de filas y del lado inicial; 3 filas con Mockup navegador/teléfono.
Verificado en navegador (Playwright, módulos frescos): filas alternas en
claro/oscuro × LTR/RTL, `reversed`, el orden de lectura copy-primero, y los dos
cromos de Mockup. `blocks:check` verde (4 blocks) · `svelte-check` sin errores
propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
- **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.
|
feat(blocks): F2.3 `feature-grid` — el primer block compound del tier
`<FeatureGrid>` + `.Header` + `.Items` + `.Item` + `.ItemIcon`/`.ItemTitle`/
`.ItemText`: una cabecera sobre una rejilla responsive de features
(icono · título · texto). Es la sección que responde «qué hace», la nº1 tras el
hero.
Primer block COMPOUND del tier, y aplica la regla de forma que fijamos: el
`.Item` se REPITE (el app mapea sobre N features) → gana sub-componentes, donde
`hero`/`site-header` usan slots de snippet (partes fijas de layout). Las partes
no coordinan —sin contexto ni estado entre ellas—: la rejilla es del padre, las
celdas del app. `.Items` es el envoltorio honesto de la rejilla (`AutoGrid`), que
deja la cabecera fuera sin un `grid-column: 1/-1` a pelo.
- El block coloca (Section · Container · AutoGrid · Surface · Heading · Text); el
app pone todo el contenido por children (B-7).
- `.Items` fluido por `minChildWidth` (tantas columnas como quepan) o `columns`
fijas; `.Item` `align` start/center; `.ItemIcon` chip `Surface`; `.ItemTitle`
`Heading` h3; `.ItemText` `Text` apagado.
- `align` de sección (center/start) coloca la cabecera coherente con las columnas.
Dos cosas encontradas al construir, resueltas:
- **Los sub-componentes de bloque extienden los props del componente canon que
envuelven** (`BoxProps`, `StackProps`, `HeadingProps`…), **no
`HTMLAttributes`**: el `style: string|null` del atributo HTML crudo choca con
el `style: string` del canon al hacer spread (+ "union type too complex").
- **`.ItemIcon` por defecto `solid`, no `soft`**: el soft-primary en claro es
casi blanco (oklch 0.99) → el chip era invisible; solid da el chip con glifo
on-solid (la tinta de contraste la pone `Surface`).
Demo (`web/routes/blocks/feature-grid/`): full-bleed + ruta `preview`, con
control de columnas (fluido/2/3/4), align, nº de items y dir; 6 features con
iconos del canon.
Hueco a decisión del usuario (en los Gaps del block): el **feature-split/
alternante** (texto junto a un screenshot, lados alternos) — la brecha nº1 del
dossier — es otra disposición (filas de 2 columnas, no rejilla de iconos):
probablemente un block hermano `feature-split`. Presentado, no resuelto.
Verificado en navegador (Playwright, módulos frescos): center/start × claro/
oscuro × LTR/RTL, columnas fluidas y fijas, 3/4/6 items, chips visibles.
`blocks:check` verde (3 blocks) · `svelte-check` sin errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
|
|
|
|
|
## 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.
|
feat(blocks): F2.2 `hero` — center · split · background, por slots
Segundo block del tier. API por SLOTS DE SNIPPET, no compound: la forma se
razonó con el usuario y con el paisaje de referencia. Compound se reserva para
partes que COORDINAN (estado/contexto/ARIA entre ellas — Accordion, Dialog); un
hero son cinco slots de layout que no se hablan entre sí y que el root arregla,
así que snippets. Además el campo entero shippea marketing como copy-paste
plano —nadie aplica compound a una sección—, y los slots por zona son la
historia de personalización que distingue al tier del copy-paste.
`<Hero layout="center|split|background" level container size>` +
`eyebrow/title/description/actions/media/background/children`.
- El block **envuelve** título y subtítulo en `Heading`/`Text`: así posee el
`id` que nombra el `<section aria-labelledby>` y el nivel del encabezado,
mientras la app pone las palabras (B-7). `eyebrow`/`actions`/`media` son
contenido libre (ahí los componentes del canon SON la API).
- `center` = `Stack` centrado, media debajo (ancho-capado); `split` = `Grid` de
dos columnas (una sola sin media), apila en estrecho.
- **`background` (cover)** — añadido por scope-approval del usuario: la media a
sangre detrás de la copy, con velo de contraste (`--color-overlay` a
`--opacity-scrim`), texto `on-solid` y `object-fit: cover` vía un `<style>`
justificado (D-BLK.2). Son las ÚNICAS reglas que el block posee, todas sobre
tokens del ecosistema — cero color a mano. Capas por orden de fuente, sin
`z-index`.
Demo (`web/routes/blocks/hero/`): full-bleed en la página + ruta `preview` para
anchos de dispositivo, cada prop un control vivo, y el backdrop del layout cover
dogfooda el sistema de color — es un `Surface color="primary" gradient` (finish
aurora = `--gradient-aurora`, derivado de los roles del tema; cambia con la
paleta). Mini-site compartido por las dos superficies (`HeroSite.svelte`).
Encontrado al componer, registrado no resuelto: `Box`/`Surface` `flex`/`grow`
no hicieron crecer un hijo flex (bars a 0-width, `flex: 0 1 auto`; la prop no la
usa ningún componente shipped). La demo usó `Grid` (tracks `1fr`). Flag en el
README del block y en el handoff para revisar el cableado de `--box-flex`.
Verificado en navegador (Playwright headless, módulos frescos): center/split/
background × claro/oscuro × LTR/RTL, media on/off, y el landmark nombrado
(región con `aria-labelledby` que resuelve al título). `blocks:check` verde
(2 blocks) · `svelte-check` sin errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
|
docs(blocks): registro de F2.1, doctrina de demo del tier y handoff
Documentación al día de lo que se cerró hoy y handoff para retomar mañana.
- `PLAN-blocks.md` §7: **F2.1 `site-header` HECHA** con sus siete commits, la
fase 0 contra el dossier §P1, el landmark que le faltaba a `NavigationMenu`
(arreglado en el canon, no parcheado en el block), el hueco del CTA que
navega y parece botón (registrado, no falseado) y el defecto de framework
que destapó la demo.
- `theming/changelog.md` §46: las 44 variables de cascada de `Box` dejan de
heredarse. Un `Section` regalaba su padding a cada descendiente —la galería
arrastraba ~300px de aire desde F0— y los hijos heredaban anchos y `display`
ajenos. `@property { inherits: false }`, radio verificado sin regresiones.
Lección: una variable que un componente escribe para SÍ MISMO debe declararse
`inherits: false`; si no, deja de ser un prop y se vuelve un contagio.
- `architecture/blocks.md` B-9: la demo de un block se construye sobre el
harness compartido y el block se enseña A SANGRE — nunca dentro de un marco
con relleno ni de una caja con scroll, porque eso cambia lo que el block
hace.
- `src/uix/blocks/README.md`: anatomía de la demo (harness, `{Name}Site`, ruta
`preview`, `DocRow`, catálogo único, ejes en el shell).
- `CONTINUE-blocks.md` (nuevo): handoff — qué toca (F2.2 `hero`), la plantilla
de ficheros para copiar, las reglas que ya costaron sangre (a sangre, iframe
solo para anchos de dispositivo, cada prop un control, nada de backticks en
`<Text>`, ojo con las variables que heredan), la deuda declarada que es
decisión del usuario y el estado exacto de los gates.
Gates al parar: `blocks:check` verde · `svelte-check` 73 errores, todos deuda
ajena (0 propios) · `vitest src/uix/eidos` 353/353 · `contracts.test` con los
3 fallos ajenos conocidos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
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`):
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
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)
|
|
|
|
|
|
feat(button): el CTA que navega y parece botón, por composición (opción D)
El hueco que registró `site-header`: un «Empezar gratis» de cabecera tiene que
NAVEGAR y parecer botón. `Button` no crece un `href` —`Link` posee la
navegación, y un ancla se activa con Enter, no con espacio, lo cual es
correcto—: presta la pintura por composición. Lo que hacía de esa forma un
downgrade era que el `child` (asChild) descartaba la decoración; se completa el
slot.
- **eidos `<Button>`**: el `child` recibe ahora `content`, el cuerpo YA
decorado (icono · etiqueta · endIcon · spinner) en su propio snippet que
comparten las dos ramas de render. Así
`<a href {...props}>{@render content()}</a>` conserva TODOS los slots en vez
de sustituirlos (antes la flecha del sitio alpha estaba escrita a mano).
Nuevo tipo exportado `ButtonChildProps`.
- **soma / morfo**: en la forma `child` el elemento es del consumidor, así que
soma deja de estampar `type` (un `<a type="button">` es una pista de MIME
falsa). El componente pasa `type: undefined` cuando hay `child`; el provider
lo REENVÍA verbatim (antes lo re-defaulteaba a `'button'` y pisaba el drop —
el default vive en el destructure del componente); el morfo declara el attr
`type` condicional (`prop-truthy`).
- **docs**: ejemplo rancio de `index.ts` corregido (anunciaba un `asChild`/
`variant="link"` que no existen); sección «CTA que navega» en el README de
eidos con el patrón y el footgun documentado (un `<button>` en un `<form>` vía
`child` se pone su propio `type`); nota en el README de soma.
- **site-header**: el CTA de la demo usa ya la forma real (`<a>` sólido con
flecha), y el hueco pasa de «candidato a canon» a CERRADO por composición —
`Button` sigue sin `href` y `Link` sigue poseyendo la navegación, las dos
decisiones firmadas se mantienen. Actualizados PLAN/CONTINUE-blocks.
- **demo de Button**: control `child (asChild → <a>)` vivo, snippet del código
y fila de a11y explicando por qué el ancla activa solo con Enter.
Verificado en navegador (dev, restart para módulos frescos): asChild ON →
`<a href="#pricing">` sin `type`, pintura sólida completa (bg primary, tinta
blanca, 36px, padding 16px), y el slot de icono SOBREVIVE dentro del ancla
(`[data-button-icon]` + svg + body); asChild OFF → `<button type="button">`
intacto (sin regresión de submit implícito); el CTA real de `site-header` sale
`<a>` con la flecha final y 0 errores de consola. `blocks:check` verde ·
`vitest src/uix/morfo` 114/114 · `svelte-check` sin errores propios nuevos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
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).
|
feat(blocks): F2.2 `hero` — center · split · background, por slots
Segundo block del tier. API por SLOTS DE SNIPPET, no compound: la forma se
razonó con el usuario y con el paisaje de referencia. Compound se reserva para
partes que COORDINAN (estado/contexto/ARIA entre ellas — Accordion, Dialog); un
hero son cinco slots de layout que no se hablan entre sí y que el root arregla,
así que snippets. Además el campo entero shippea marketing como copy-paste
plano —nadie aplica compound a una sección—, y los slots por zona son la
historia de personalización que distingue al tier del copy-paste.
`<Hero layout="center|split|background" level container size>` +
`eyebrow/title/description/actions/media/background/children`.
- El block **envuelve** título y subtítulo en `Heading`/`Text`: así posee el
`id` que nombra el `<section aria-labelledby>` y el nivel del encabezado,
mientras la app pone las palabras (B-7). `eyebrow`/`actions`/`media` son
contenido libre (ahí los componentes del canon SON la API).
- `center` = `Stack` centrado, media debajo (ancho-capado); `split` = `Grid` de
dos columnas (una sola sin media), apila en estrecho.
- **`background` (cover)** — añadido por scope-approval del usuario: la media a
sangre detrás de la copy, con velo de contraste (`--color-overlay` a
`--opacity-scrim`), texto `on-solid` y `object-fit: cover` vía un `<style>`
justificado (D-BLK.2). Son las ÚNICAS reglas que el block posee, todas sobre
tokens del ecosistema — cero color a mano. Capas por orden de fuente, sin
`z-index`.
Demo (`web/routes/blocks/hero/`): full-bleed en la página + ruta `preview` para
anchos de dispositivo, cada prop un control vivo, y el backdrop del layout cover
dogfooda el sistema de color — es un `Surface color="primary" gradient` (finish
aurora = `--gradient-aurora`, derivado de los roles del tema; cambia con la
paleta). Mini-site compartido por las dos superficies (`HeroSite.svelte`).
Encontrado al componer, registrado no resuelto: `Box`/`Surface` `flex`/`grow`
no hicieron crecer un hijo flex (bars a 0-width, `flex: 0 1 auto`; la prop no la
usa ningún componente shipped). La demo usó `Grid` (tracks `1fr`). Flag en el
README del block y en el handoff para revisar el cableado de `--box-flex`.
Verificado en navegador (Playwright headless, módulos frescos): center/split/
background × claro/oscuro × LTR/RTL, media on/off, y el landmark nombrado
(región con `aria-labelledby` que resuelve al título). `blocks:check` verde
(2 blocks) · `svelte-check` sin errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
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`.
|
docs(blocks): registro de F2.1, doctrina de demo del tier y handoff
Documentación al día de lo que se cerró hoy y handoff para retomar mañana.
- `PLAN-blocks.md` §7: **F2.1 `site-header` HECHA** con sus siete commits, la
fase 0 contra el dossier §P1, el landmark que le faltaba a `NavigationMenu`
(arreglado en el canon, no parcheado en el block), el hueco del CTA que
navega y parece botón (registrado, no falseado) y el defecto de framework
que destapó la demo.
- `theming/changelog.md` §46: las 44 variables de cascada de `Box` dejan de
heredarse. Un `Section` regalaba su padding a cada descendiente —la galería
arrastraba ~300px de aire desde F0— y los hijos heredaban anchos y `display`
ajenos. `@property { inherits: false }`, radio verificado sin regresiones.
Lección: una variable que un componente escribe para SÍ MISMO debe declararse
`inherits: false`; si no, deja de ser un prop y se vuelve un contagio.
- `architecture/blocks.md` B-9: la demo de un block se construye sobre el
harness compartido y el block se enseña A SANGRE — nunca dentro de un marco
con relleno ni de una caja con scroll, porque eso cambia lo que el block
hace.
- `src/uix/blocks/README.md`: anatomía de la demo (harness, `{Name}Site`, ruta
`preview`, `DocRow`, catálogo único, ejes en el shell).
- `CONTINUE-blocks.md` (nuevo): handoff — qué toca (F2.2 `hero`), la plantilla
de ficheros para copiar, las reglas que ya costaron sangre (a sangre, iframe
solo para anchos de dispositivo, cada prop un control, nada de backticks en
`<Text>`, ojo con las variables que heredan), la deuda declarada que es
decisión del usuario y el estado exacto de los gates.
Gates al parar: `blocks:check` verde · `svelte-check` 73 errores, todos deuda
ajena (0 propios) · `vitest src/uix/eidos` 353/353 · `contracts.test` con los
3 fallos ajenos conocidos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
|
|
|
|
|
## Estado de gates al parar
|
|
|
|
|
|
feat(blocks): F2.2 `hero` — center · split · background, por slots
Segundo block del tier. API por SLOTS DE SNIPPET, no compound: la forma se
razonó con el usuario y con el paisaje de referencia. Compound se reserva para
partes que COORDINAN (estado/contexto/ARIA entre ellas — Accordion, Dialog); un
hero son cinco slots de layout que no se hablan entre sí y que el root arregla,
así que snippets. Además el campo entero shippea marketing como copy-paste
plano —nadie aplica compound a una sección—, y los slots por zona son la
historia de personalización que distingue al tier del copy-paste.
`<Hero layout="center|split|background" level container size>` +
`eyebrow/title/description/actions/media/background/children`.
- El block **envuelve** título y subtítulo en `Heading`/`Text`: así posee el
`id` que nombra el `<section aria-labelledby>` y el nivel del encabezado,
mientras la app pone las palabras (B-7). `eyebrow`/`actions`/`media` son
contenido libre (ahí los componentes del canon SON la API).
- `center` = `Stack` centrado, media debajo (ancho-capado); `split` = `Grid` de
dos columnas (una sola sin media), apila en estrecho.
- **`background` (cover)** — añadido por scope-approval del usuario: la media a
sangre detrás de la copy, con velo de contraste (`--color-overlay` a
`--opacity-scrim`), texto `on-solid` y `object-fit: cover` vía un `<style>`
justificado (D-BLK.2). Son las ÚNICAS reglas que el block posee, todas sobre
tokens del ecosistema — cero color a mano. Capas por orden de fuente, sin
`z-index`.
Demo (`web/routes/blocks/hero/`): full-bleed en la página + ruta `preview` para
anchos de dispositivo, cada prop un control vivo, y el backdrop del layout cover
dogfooda el sistema de color — es un `Surface color="primary" gradient` (finish
aurora = `--gradient-aurora`, derivado de los roles del tema; cambia con la
paleta). Mini-site compartido por las dos superficies (`HeroSite.svelte`).
Encontrado al componer, registrado no resuelto: `Box`/`Surface` `flex`/`grow`
no hicieron crecer un hijo flex (bars a 0-width, `flex: 0 1 auto`; la prop no la
usa ningún componente shipped). La demo usó `Grid` (tracks `1fr`). Flag en el
README del block y en el handoff para revisar el cableado de `--box-flex`.
Verificado en navegador (Playwright headless, módulos frescos): center/split/
background × claro/oscuro × LTR/RTL, media on/off, y el landmark nombrado
(región con `aria-labelledby` que resuelve al título). `blocks:check` verde
(2 blocks) · `svelte-check` sin errores propios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
- `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.
|
docs(blocks): registro de F2.1, doctrina de demo del tier y handoff
Documentación al día de lo que se cerró hoy y handoff para retomar mañana.
- `PLAN-blocks.md` §7: **F2.1 `site-header` HECHA** con sus siete commits, la
fase 0 contra el dossier §P1, el landmark que le faltaba a `NavigationMenu`
(arreglado en el canon, no parcheado en el block), el hueco del CTA que
navega y parece botón (registrado, no falseado) y el defecto de framework
que destapó la demo.
- `theming/changelog.md` §46: las 44 variables de cascada de `Box` dejan de
heredarse. Un `Section` regalaba su padding a cada descendiente —la galería
arrastraba ~300px de aire desde F0— y los hijos heredaban anchos y `display`
ajenos. `@property { inherits: false }`, radio verificado sin regresiones.
Lección: una variable que un componente escribe para SÍ MISMO debe declararse
`inherits: false`; si no, deja de ser un prop y se vuelve un contagio.
- `architecture/blocks.md` B-9: la demo de un block se construye sobre el
harness compartido y el block se enseña A SANGRE — nunca dentro de un marco
con relleno ni de una caja con scroll, porque eso cambia lo que el block
hace.
- `src/uix/blocks/README.md`: anatomía de la demo (harness, `{Name}Site`, ruta
`preview`, `DocRow`, catálogo único, ejes en el shell).
- `CONTINUE-blocks.md` (nuevo): handoff — qué toca (F2.2 `hero`), la plantilla
de ficheros para copiar, las reglas que ya costaron sangre (a sangre, iframe
solo para anchos de dispositivo, cada prop un control, nada de backticks en
`<Text>`, ojo con las variables que heredan), la deuda declarada que es
decisión del usuario y el estado exacto de los gates.
Gates al parar: `blocks:check` verde · `svelte-check` 73 errores, todos deuda
ajena (0 propios) · `vitest src/uix/eidos` 353/353 · `contracts.test` con los
3 fallos ajenos conocidos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
|
|
|
- `contracts.test.ts`: 3 fallos AJENOS conocidos (menubar DOM-write ·
|
|
|
|
|
radio-group `data-ready` · claves camelCase de `aura`), de sesiones paralelas.
|