9.7 KiB
CONTINUE — visibilidad por breakpoint (visibleFrom / hiddenFrom) (handoff, act. 2026-08-19)
CONGELADO 2026-09-17 — el cierre del framework congela este handoff: no se actualiza. Lo que sigue abierto vive en
LEDGER-cierre-2026-09.md, por id.
Estado: F1–F3 HECHAS, AUDITADAS, VERIFICADAS en Chrome real y COMMITEADAS
(2026-08-19, uix(box): ocultar por CSS descarga el vídeo igual…). La auditoría
de cierre encontró tres desviaciones menores, las tres corregidas antes del
commit (ver §Auditoría). Nada bloquea el uso.
Por dónde entrar: §Qué queda, por orden. Lo único pendiente es F4 (rollout al hero), y sólo si el autor lo pide.
Qué es
Dos props en Box que NO RENDERIZAN el elemento fuera de su rango de
breakpoints — el subárbol no está en el DOM, sus efectos no corren y su media
no se pide. Es la mitad que display={{ base: 'none' }} no puede dar (oculta,
pero monta). Por herencia la ganan los once contenedores que componen Box
(Section, Container, Flex, Grid, Stack, Group, Wrap, AutoGrid, Surface,
AspectRatio, Float) sin tocar sus ficheros.
visibleFrom="md"→ no existe por debajo demd(desktop-only).hiddenFrom="md"→ no existe desdemd(mobile-only).- Ambos → rango contiguo.
baseexcluido del tipo a propósito.
La puerta es eidos.dom.isAtLeast(bp) —el predicado que ActiveDom ya tenía,
sobre los breakpoints que configura el app— en un $derived y un {#if}
alrededor de la raíz de box.svelte. Sin atributos nuevos, sin generador.
Fuente viva de las decisiones: C:\Users\dev\.claude\plans\elegant-weaving-lark.md
(D-V.1…4 firmadas 2026-08-18, con el estudio de cómo lo hacen Mantine, Chakra,
MUI, Vuetify, Framer y Webflow — todos por CSS o pagando flash/adivinando el
ancho). Su contenido de decisiones debería moverse a un lugar del repo si el eje
sigue creciendo (hoy vive en el README de Box y en docs/architecture/eidos.md).
Auditoría de cierre (2026-08-19) — hallazgos y correcciones
| # | Hallazgo | Corrección |
|---|---|---|
| 1 | El tipo aceptaba base: visibleFrom="base" = «siempre», hiddenFrom="base" = «nunca renderiza» — y la demo (correctamente) no lo ofrecía en los chips: paridad rota entre tipo y demo |
Exclude<Breakpoint, 'base'> en ambas props, con el porqué en el JSDoc. El mismo Exclude bajó a la demo ($state + chips) el 2026-08-19: sin él npm run check daba 2 errores en box/. HECHO |
| 2 | README decía «los doce contenedores que componen Box» y listaba once (el doceavo es Box) | «once… — doce con Box». HECHO |
| 3 | El plan pedía en Gaps la exclusión de Card / Banner / ScrollArea / Sticky (raíz propia, no heredan) y faltaba | Fila añadida con la regla del as (≥2 casos reales). HECHO |
| 4 | Dos afirmaciones del informe no se habían LEÍDO en consola: «Svelte repara el {#if} sin aviso» y «sin effect_update_depth_exceeded al cruzar con capas que se registran» |
Medido en Chrome con consola capturada desde la carga: cero avisos de hidratación, cero bucles en 3 ciclos con un Background.Gradient animate dentro; Stack → Flex → Box hereda. CONFIRMADO |
| 5 | La nota documental fue a docs/architecture/eidos.md y no a theming/reference.md como decía el plan |
theming/reference.md no tiene sección responsive; el párrafo del «puente responsive» vive en eidos.md §tokens. Desvío justificado, no error |
Verificado (Chrome real, 2026-08-18/19): a 2133px conviven visibleFrom="md"
presente, hiddenFrom="md" ausente y rango sm–lg ausente · al cerrar la puerta
en vivo desaparecen sección, <video> e <input> del DOM; al reabrir el input
vuelve vacío (la renuncia D-V.4, medida) · el par cambia con un resize ·
npm run build → 200.html de 1.815 bytes, shell puro: en producción no hay
SSR que pueda pintar mal · en DEV sí: el dev server sirve la variante base y
pide su media antes de que la hidratación la pode (documentado en el README de
Box como caveat de desarrollo).
Qué queda, por orden
Commit hecho el 2026-08-19 con las seis rutas del eje (
box/{box.svelte,types.ts,README.md}, la demo,eidos.md, este handoff) ygit addpor ruta, nunca-A: otra sesión editabaapp-shellen paralelo. Gates en verde ese día:checksin nada enbox/,blocks:check0,morfo:checkPASS box,docs:check0,npx vitest run src/uix/eidos434/435 (el fallo esskin-media-player, ajeno), prettier OK — salvoeidos.md, que ya fallaba en HEAD en tablas ajenas al eje y por eso no se reformatea.
F4 HECHA el 2026-08-19. La receta vive donde se usa —
hero/README.md§«The responsive backdrop» — y el vehículo es el backdrop deHeroSite. La puerta va DENTRO del snippet, nunca alrededor del<Hero>: envolver el block duplicaría título, copy, formulario y acciones por breakpoint (lo que hace Framer).display="contents"en las dos Box: una puerta decide presencia, no añade geometría. Medido sobre build de PRODUCCIón (npm run build+vite preview, Chrome): a 375 → 0<video>en el DOM y ninguna petición devideo.mp4; a 1280 → 1<video>y una peticion (206 Partial Content). La afirmación central del eje deja de estar medida sólo en dev, donde es falsa.⚠️ Hallazgo ajeno, medido de paso: la media dentro de un
Background.LayerDESBORDA la capa — el mínimo automático del ítem de rejilla gana ablock-size: 100%. Hero a 1280: capa 567px,<video>714px; y en la demo del propio canon con<Background.Video>: capa 288px, vídeo 435px.min-block-size: 0lo colapsa exacto en ambos.overflow: cliplo esconde, y por eso nunca se vio. Es del ejebackground(cerrado el 2026-08-18), escrito enhero/README.md§Found while composing — marcado, no arreglado.
- Si algún día hay SSR/prerender — el puente C está escrito en el README de
Box §Gaps con su disparador:
data-visible-from/data-hidden-from, dos reglas@mediapor breakpoint enrender-css.ts(junto a las de tipografía), y la puertahidratado ? resuelto : true. Hoy sería un atributo que nadie lee — no construir sin el disparador. - Card, Banner, ScrollArea, Sticky — no heredan (raíz propia). Regla del
as: a mano cuando aparezcan ≥2 casos reales; mientras, envolver en<Box>.
Lo que este eje enseñó
- Pregunta «¿y si no tenemos SSR?» antes de diseñar el puente. Iba a
construir la híbrida (CSS hasta hidratar + desmontar después) por «framework de
referencia»; el repo respondió:
adapter-static+fallbacksin ninguna rutaprerender = true= SPA puro. La mitad cara del diseño era para un despliegue que no existe. - El panel oculto miente para esto también:
innerWidth0 ⇒ todo resuelve abase. La verificación exige Chrome visible (claude-in-chrome), y aun ahí una ventana maximizada no admiteresize— cruza el umbral por el breakpoint (hiddenFromcon un botón), que recorre el mismo$derived. - Una sonda que no puede cerrar la puerta no prueba nada: a 2133px
visibleFrom="xxl"sigue abierta (1536 < 2133). Elegir el eje que sí cruza.
Mapa de ficheros
| Qué | Dónde |
|---|---|
| La puerta | src/uix/eidos/components/box/box.svelte (visible + {#if}) |
| El tipo y su JSDoc | src/uix/eidos/components/box/types.ts |
| Decisiones, medidas, caveat de dev, gaps | src/uix/eidos/components/box/README.md |
| La demo (chips + snippet en paridad) | web/routes/uix/components/box/+page.svelte |
| La receta (caso real, con cifras) | src/uix/blocks/hero/README.md §«The responsive backdrop» |
| El caso real | web/routes/blocks/hero/HeroSite.svelte (snippet backdrop) |
| El párrafo de arquitectura | docs/architecture/eidos.md §«responsive bridge» |
| El predicado que reutiliza | src/arts/adom/active-dom.svelte.ts isAtLeast |