kmcom-nuxt-layers 6.4.0 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/MIGRATION-v6.5.0.md +87 -0
- package/docs/MIGRATION.md +2 -1
- package/docs/USAGE.md +35 -10
- package/layers/content/app/components/content/Figure.vue +1 -1
- package/layers/content/app/composables/useContentSection.ts +1 -1
- package/layers/core/app/app.config.ts +7 -3
- package/layers/core/app/components/LoadingScreen.vue +35 -21
- package/layers/core/app/composables/useCache.ts +2 -2
- package/layers/core/app/composables/useErrorLog.ts +5 -5
- package/layers/core/app/composables/useLoading.ts +19 -10
- package/layers/core/app/plugins/loading.client.ts +11 -3
- package/layers/core/app/types/loading.ts +10 -3
- package/layers/core/app/utils/loading.ts +6 -15
- package/layers/core/nuxt.config.ts +14 -14
- package/layers/core/server/utils/app-config.ts +17 -0
- package/layers/data/auth/app/middleware/auth.ts +1 -1
- package/layers/data/forms/app/components/Form/Contact.vue +1 -1
- package/layers/data/forms/server/api/contact.post.ts +16 -8
- package/layers/data/forms/server/api/forms/status.get.ts +3 -0
- package/layers/data/forms/{app → shared}/utils/contact-schema.ts +2 -1
- package/layers/data/metadata/server/api/metadata/search.get.ts +27 -7
- package/layers/data/metadata/server/api/metadata/status.get.ts +4 -1
- package/layers/data/metadata/server/api/metadata/sync.post.ts +13 -3
- package/layers/data/metadata/server/utils/metadata/resolve-record.ts +3 -3
- package/layers/delivery/feeds/nuxt.config.ts +6 -1
- package/layers/delivery/feeds/package.json +2 -2
- package/layers/delivery/feeds/server/routes/feed/demo.get.ts +2 -2
- package/layers/delivery/feeds/server/utils/content-adapter.ts +1 -1
- package/layers/delivery/feeds/server/utils/feed-service.ts +2 -2
- package/layers/design-system/theming/app/plugins/theme.client.ts +7 -0
- package/layers/design-system/theming/nuxt.config.ts +0 -2
- package/layers/motion/scroll/app/plugins/locomotive-scroll.client.ts +3 -2
- package/layers/render/canvas/nuxt.config.ts +0 -4
- package/layers/render/shader/nuxt.config.ts +0 -4
- package/layers/structure/routing/app/middleware/01.maintenance.global.ts +4 -1
- package/layers/structure/routing/app/middleware/02.governance.global.ts +1 -1
- package/layers/structure/routing/nuxt.config.ts +19 -12
- package/layers/structure/routing/server/api/feature-flags.get.ts +4 -2
- package/package.json +35 -5
- package/docs/FALLOW-COMPLEXITY-DUPLICATION-AUDIT.md +0 -64
- package/docs/IMPROVE-AUDIT-README.md +0 -29
- package/docs/IMPROVE-AUDIT-RESULTS.md +0 -51
- package/docs/IMPROVE-DEEP-AUDIT-RESULTS.md +0 -81
- package/docs/fallow-refactor/apps-debug.md +0 -27
- package/docs/fallow-refactor/apps-playground.md +0 -46
- package/docs/fallow-refactor/apps-visual-identity.md +0 -41
- package/docs/fallow-refactor/layers-animations.md +0 -34
- package/docs/fallow-refactor/layers-canvas.md +0 -32
- package/docs/fallow-refactor/layers-content.md +0 -33
- package/docs/fallow-refactor/layers-core.md +0 -39
- package/docs/fallow-refactor/layers-feeds.md +0 -39
- package/docs/fallow-refactor/layers-forms.md +0 -30
- package/docs/fallow-refactor/layers-layout.md +0 -42
- package/docs/fallow-refactor/layers-mailer.md +0 -32
- package/docs/fallow-refactor/layers-motion.md +0 -27
- package/docs/fallow-refactor/layers-navigation.md +0 -31
- package/docs/fallow-refactor/layers-page-transitions.md +0 -30
- package/docs/fallow-refactor/layers-routing.md +0 -33
- package/docs/fallow-refactor/layers-scripts.md +0 -35
- package/docs/fallow-refactor/layers-scroll.md +0 -38
- package/docs/fallow-refactor/layers-seo.md +0 -32
- package/docs/fallow-refactor/layers-shader.md +0 -53
- package/docs/fallow-refactor/layers-theme.md +0 -33
- package/docs/fallow-refactor/layers-transitions.md +0 -27
- package/docs/fallow-refactor/layers-typography.md +0 -29
- package/docs/fallow-refactor/layers-visual.md +0 -34
- package/docs/superpowers/plans/2026-09-03-layout-layer-fluid-rebuild.md +0 -1850
- package/docs/superpowers/plans/2026-09-03-vue-element-system.md +0 -1019
- package/docs/superpowers/plans/2026-09-04-grid-layer.md +0 -977
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-0-1-design.md +0 -533
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-2-design.md +0 -154
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-3-design.md +0 -109
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-4-design.md +0 -124
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-5-design.md +0 -121
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-6-design.md +0 -77
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-7-design.md +0 -73
- package/docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md +0 -190
- package/docs/superpowers/specs/2026-09-03-layout-layer-fluid-rebuild-design.md +0 -312
- package/docs/superpowers/specs/2026-09-03-vue-element-system-design.md +0 -342
- package/docs/superpowers/specs/2026-09-04-grid-layer-design.md +0 -236
- package/layers/content/app/utils/galleryImageMeta.test.ts +0 -30
- package/layers/core/app/components/Element.test.ts +0 -90
- package/layers/core/app/components/ElementTw.test.ts +0 -64
- package/layers/core/app/composables/useLayoutAttrs.test.ts +0 -77
- package/layers/core/app/utils/browserInfo.test.ts +0 -81
- package/layers/core/app/utils/featureClasses.test.ts +0 -101
- package/layers/core/app/utils/loading.test.ts +0 -48
- package/layers/core/app/utils/resolveElementStyle.test.ts +0 -99
- package/layers/core/app/utils/scrollGuardClamp.test.ts +0 -36
- package/layers/core/app/utils/styleToTailwindClasses.test.ts +0 -31
- package/layers/data/forms/app/utils/contact-schema.test.ts +0 -75
- package/layers/data/forms/app/utils/fieldProps.test.ts +0 -141
- package/layers/data/metadata/providers/comicvine/server/utils/metadata-comicvine/normalise.test.ts +0 -201
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/client.test.ts +0 -76
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/normalise.test.ts +0 -144
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/client.test.ts +0 -25
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +0 -144
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +0 -29
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/normalise.test.ts +0 -162
- package/layers/data/metadata/server/utils/metadata/cache.test.ts +0 -39
- package/layers/data/metadata/server/utils/metadata/provider-fetch.test.ts +0 -27
- package/layers/data/metadata/server/utils/metadata/provider-registry.test.ts +0 -54
- package/layers/data/metadata/server/utils/metadata/resolve-record.test.ts +0 -87
- package/layers/data/metadata/server/utils/metadata/search.test.ts +0 -204
- package/layers/delivery/feeds/server/utils/content-adapter.test.ts +0 -67
- package/layers/delivery/feeds/server/utils/feed-author.test.ts +0 -71
- package/layers/delivery/feeds/server/utils/feed-config.test.ts +0 -184
- package/layers/delivery/feeds/server/utils/formats.test.ts +0 -71
- package/layers/delivery/seo/app/utils/seoConfig.test.ts +0 -58
- package/layers/design-system/theming/server/utils/accent-css.test.ts +0 -71
- package/layers/design-system/theming/server/utils/fouc-config.test.ts +0 -78
- package/layers/design-system/typography/app/components/Typography/Headline.test.ts +0 -36
- package/layers/design-system/typography/app/components/Typography/index.test.ts +0 -31
- package/layers/design-system/typography/app/composables/color.test.ts +0 -30
- package/layers/design-system/typography/app/composables/typography.test.ts +0 -53
- package/layers/design-system/visual/app/components/HoverDimGroup.test.ts +0 -38
- package/layers/design-system/visual/app/composables/tint.test.ts +0 -22
- package/layers/design-system/visual/app/utils/colorTokens.test.ts +0 -51
- package/layers/design-system/visual/app/utils/gradientStyle.test.ts +0 -75
- package/layers/design-system/visual/app/utils/responsiveSizes.test.ts +0 -71
- package/layers/motion/animations/app/components/Motion/Staggered.test.ts +0 -40
- package/layers/motion/scroll/app/composables/useReducedMotion.test.ts +0 -23
- package/layers/motion/scroll/app/utils/parallax.test.ts +0 -24
- package/layers/structure/grid/app/composables/useGridTracks.test.ts +0 -94
- package/layers/structure/grid/app/types/tracks.test.ts +0 -32
- package/layers/structure/grid/app/utils/placement.test.ts +0 -19
- package/layers/structure/layout/app/utils/gridPlacementStyle.test.ts +0 -269
- package/layers/structure/navigation/app/utils/site.test.ts +0 -39
- package/layers/structure/routing/app/utils/resolveRoute.test.ts +0 -47
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Layer Taxonomy Redesign — Part 7: Tier 7 (Delivery)
|
|
2
|
-
|
|
3
|
-
## Scope
|
|
4
|
-
|
|
5
|
-
Forensic audit of `seo`, `scripts`, `feeds`, plus the `baseline` → `scripts` merge carried over
|
|
6
|
-
as an open decision from Tier 0-1. Cleanup-only pass, per user direction from Tier 6.
|
|
7
|
-
|
|
8
|
-
## Findings and resolution
|
|
9
|
-
|
|
10
|
-
### `seo`: stale `OgImageBasic` fallback — fixed (real bug, low severity)
|
|
11
|
-
|
|
12
|
-
`resolveOgImageConfig()`'s fallback (used only when `seoLayer` config is entirely absent) still
|
|
13
|
-
returned `'OgImageBasic'` — the old default, already fixed at the `app.config.ts` level to
|
|
14
|
-
`'OgImageNuxtSeo'` in an earlier session (`OgImageBasic` doesn't exist in `nuxt-og-image@6`). The
|
|
15
|
-
fallback path is effectively dead in practice (app.config always provides `seoLayer`), but the
|
|
16
|
-
stale value was still wrong and the test asserted the same stale value. **Fixed**: fallback and
|
|
17
|
-
test both updated to `'OgImageNuxtSeo'`.
|
|
18
|
-
|
|
19
|
-
### `scripts/app/types/` — dead duplicate types — deleted
|
|
20
|
-
|
|
21
|
-
`types/scripts.ts` exported `LoadStrategy`, `ScriptLoaderOptions`, and `AnalyticsProxy` — zero
|
|
22
|
-
consumers anywhere. `useScriptLoader.ts` declares its own local `LoadStrategy`/
|
|
23
|
-
`ScriptLoaderOptions` instead of importing the "shared" ones, and `AnalyticsProxy` was unused even
|
|
24
|
-
internally (the real type in use is `AnalyticsClient` in `scriptClients.ts`). **Fixed**: deleted
|
|
25
|
-
`types/scripts.ts` and `types/index.ts`, removed the now-pointless `#layers/scripts/types` alias.
|
|
26
|
-
|
|
27
|
-
### `baseline` merged into `scripts` — done (user decision, carried over from Tier 0-1)
|
|
28
|
-
|
|
29
|
-
`baseline` was 3 files (`BaselineStatus.vue`, a client plugin registering the `baseline-status`
|
|
30
|
-
web component, an `isCustomElement` compiler config) — a third-party embed integration, the same
|
|
31
|
-
shape as `scripts`' existing analytics/GTM facades, not a standalone tier member. **Done**: moved
|
|
32
|
-
`BaselineStatus.vue` and `baseline-status.client.ts` into `layers/scripts/app/`, added the
|
|
33
|
-
`isCustomElement` compiler option and the `baseline-status` dependency to `scripts`, deleted
|
|
34
|
-
`layers/baseline`, removed `baseline` from the playground's `AVAILABLE_LAYERS`/`LAYER_PATHS`/
|
|
35
|
-
`LAYER_DEPENDENCIES`. Component name is unchanged (`BaselineStatus`, auto-imported by filename
|
|
36
|
-
regardless of layer), so `apps/playground/app/pages/baseline.vue` and `index.vue` needed no edits.
|
|
37
|
-
|
|
38
|
-
## Confirmed correct, no action
|
|
39
|
-
|
|
40
|
-
- `seo`: `nuxt.config.ts` (`@nuxtjs/seo` module + `site` config), `app.config.ts` (correct
|
|
41
|
-
`defineAppConfig()` + colocated `declare module`), `useSeoConfig`/`resolveSeoConfig` — real,
|
|
42
|
-
consumed by `apps/playground/app/pages/seo.vue`, well-tested (`seoConfig.test.ts`, now updated).
|
|
43
|
-
- `scripts`: `app.config.ts` (correct structure), `useAnalytics`/`useGtm`/`useScriptsConsent`/
|
|
44
|
-
`useScriptLoader`/`useYoutubeEmbed`, `scriptClients.ts` (provider factories: ga4/plausible/
|
|
45
|
-
fathom/GTM, consent-gated triggers, noop fallbacks) — all real, consumed by
|
|
46
|
-
`apps/playground/app/pages/scripts.vue`.
|
|
47
|
-
- `feeds`: `nuxt.config.ts`'s conditional `extends` (empty unless `FEEDS_STANDALONE` env var is
|
|
48
|
-
set) looks like the "don't rely on load order" anti-pattern at first glance, but it isn't — the
|
|
49
|
-
playground's own `LAYER_DEPENDENCIES` mechanism (`feeds: ['core', 'content']`) is the actual
|
|
50
|
-
dependency-injection path for this repo's layer resolver, and the env-conditional `extends`
|
|
51
|
-
exists specifically to let `feeds` also be consumed as a truly standalone layer outside this
|
|
52
|
-
playground. `app.config.ts`, `feed-catalog.ts` (collection resolution, missing-collection
|
|
53
|
-
warnings), `feed-head.ts` plugin (auto-discovery `<link rel="alternate">` tags), `feed-service.ts`,
|
|
54
|
-
all `server/routes/feed/**` handlers (sampled `rss.get.ts`, `index.get.ts` — consistent), `Feeds/
|
|
55
|
-
Index.vue`, `Feeds/RouteCard.vue` — real, thorough, already well-tested
|
|
56
|
-
(`content-adapter.test.ts`, `feed-author.test.ts`, `feed-config.test.ts`, `formats.test.ts`),
|
|
57
|
-
consumed by `apps/playground/app/pages/feeds.vue`.
|
|
58
|
-
|
|
59
|
-
## Consolidated action list (Tier 7)
|
|
60
|
-
|
|
61
|
-
- [x] Fix stale `OgImageBasic` fallback + test in `seo`
|
|
62
|
-
- [x] Delete dead `scripts/app/types/` (unused duplicate types)
|
|
63
|
-
- [x] Merge `baseline` into `scripts`, delete the `baseline` layer, update playground registration
|
|
64
|
-
|
|
65
|
-
## Not yet covered
|
|
66
|
-
|
|
67
|
-
That closes the 8-tier sweep (Foundation → Design System → Structure → Content → Data → Motion →
|
|
68
|
-
Render → Delivery). Still pending from earlier tiers, none touched this pass: `theme`'s
|
|
69
|
-
`app.config.ts` structural defect and the `theme`→`theming` rename, `typography`'s font-prop
|
|
70
|
-
infrastructure, breakpoint token consolidation, `AppContainer` clamp() conversion,
|
|
71
|
-
`compatibilityVersion: 5` flip, `error.vue` real implementation, `starter` layer relocation into
|
|
72
|
-
`apps/`, `useMetadataItem`'s fate, the openlibrary/google-books provider error-handling
|
|
73
|
-
divergence, and the 8 zero-consumer `shader` composables left open in Tier 6.
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# Swiss Grid Layer — Design Spec
|
|
2
|
-
|
|
3
|
-
Source: "Swiss Grid Spatial System for Web Interfaces" artifact (functional
|
|
4
|
-
spec, rev. 2026-08-31), condensed from design discussion. This document
|
|
5
|
-
translates that spec into a concrete new layer for this monorepo.
|
|
6
|
-
|
|
7
|
-
## §0 Scope and relationship to `layers/structure/layout`
|
|
8
|
-
|
|
9
|
-
New layer: `layers/structure/swiss-grid` — tier 2, sibling to `layout`.
|
|
10
|
-
Depends only on `core`.
|
|
11
|
-
|
|
12
|
-
`layers/structure/layout` (Swiss Grid _subgrid_ system: `LayoutMain` /
|
|
13
|
-
`LayoutSection` / `LayoutGridItem`, hero/centered presets, `HStack` /
|
|
14
|
-
`VStack` / `ZStack` / `Spacer`, `useGridConfig()`) is **untouched** by this
|
|
15
|
-
work. It stays the system in use by `layers/content` (Gallery/Blog/Portfolio
|
|
16
|
-
Page + Item/Slug/Image variants) and `layers/structure/navigation`
|
|
17
|
-
(`Nav`/`NavModal`, which call `useGridConfig()` directly). Migrating those
|
|
18
|
-
consumers to the new layer is explicitly a later, separate pass — not part
|
|
19
|
-
of this spec.
|
|
20
|
-
|
|
21
|
-
The two layers may run in the same app simultaneously. They do not share
|
|
22
|
-
components, CSS custom properties, or config namespaces (`layoutLayer.*` vs
|
|
23
|
-
a new `swissGridLayer.*` app.config key), so there is no collision risk.
|
|
24
|
-
|
|
25
|
-
## §1 Primitives
|
|
26
|
-
|
|
27
|
-
Two components, matching the artifact's §3 API surface exactly:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
// SwissGrid — grid root
|
|
31
|
-
interface SwissGridProps {
|
|
32
|
-
columns?: ResponsiveValue<number> // default: xs:4 sm:4 md:8 lg:12 xl:12
|
|
33
|
-
gap?: ResponsiveValue<Spacing> // Spacing token from core, e.g. 'md'
|
|
34
|
-
tag?: string // default: 'div'
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// SwissGridItem — positioned child
|
|
38
|
-
type SpanAlias = 'full' | 'half' | 'third' | 'quarter'
|
|
39
|
-
interface SwissGridItemProps {
|
|
40
|
-
start?: number
|
|
41
|
-
span?: number | SpanAlias // default: 'full'
|
|
42
|
-
order?: number
|
|
43
|
-
tag?: string // default: 'div'
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
`SwissGrid` sets `display: grid`, a responsive `grid-template-columns:
|
|
48
|
-
repeat(N, minmax(0, 1fr))` (N from `columns`, resolved per breakpoint via
|
|
49
|
-
`core`'s `ResponsiveValue<T>` — 5 tiers: `default/sm/md/lg/xl`, media
|
|
50
|
-
queries built from `core`'s existing `--breakpoint-sm/md/lg/xl` tokens), a
|
|
51
|
-
responsive `gap` from `core`'s `Spacing` scale, and `container-type:
|
|
52
|
-
inline-size` (§7 — makes it a container-query boundary by default; every
|
|
53
|
-
`SwissGrid` is a potential nesting point, not just the page root).
|
|
54
|
-
|
|
55
|
-
`SwissGridItem` sets `grid-column: <start> / span <n>` (or `span <n>` alone
|
|
56
|
-
when `start` is omitted) and `order` via an inline style object, built by a
|
|
57
|
-
pure function — same shape as the old layer's `gridPlacementStyle.ts`, but a
|
|
58
|
-
new implementation in this layer, not shared code. Old and new stay
|
|
59
|
-
decoupled so `layout`'s cleanup/behavior can't leak into this layer or vice
|
|
60
|
-
versa.
|
|
61
|
-
|
|
62
|
-
## §2 Span aliases — resolving the artifact's open item
|
|
63
|
-
|
|
64
|
-
The artifact leaves the exact alias set open (§13). Resolved here:
|
|
65
|
-
|
|
66
|
-
- Aliases are expressed in a fixed **12-unit vocabulary**: `full=12,
|
|
67
|
-
half=6, third=4, quarter=3` — independent of the grid's live column
|
|
68
|
-
count, the same mental model as Bootstrap-style 12-col systems.
|
|
69
|
-
- Because `columns` can be less than 12 at smaller breakpoints (4 at `xs`,
|
|
70
|
-
8 at `sm`/`md` per §1's default), an alias's rendered span is `min(alias
|
|
71
|
-
value, current column count)` — computed in the component, not CSS
|
|
72
|
-
`calc()` (integer `grid-column: span N` can't come from a fractional
|
|
73
|
-
division). This keeps `half` always rendering as "half of whatever this
|
|
74
|
-
breakpoint's grid actually has," clamped so it never overflows a
|
|
75
|
-
narrower grid.
|
|
76
|
-
- The 12-unit table lives in `app.config.ts` under `swissGridLayer.ui.spanAliases`,
|
|
77
|
-
editable like the old layer's presets, not hardcoded in the component.
|
|
78
|
-
|
|
79
|
-
## §3 Composition tier — Cluster and Flow
|
|
80
|
-
|
|
81
|
-
New components, this layer, alongside `SwissGrid`/`SwissGridItem`:
|
|
82
|
-
|
|
83
|
-
- **`Cluster`** — horizontal grouping: `display: flex; flex-wrap: wrap`,
|
|
84
|
-
`gap` from `core`'s `Spacing` scale, optional `align`/`justify` props.
|
|
85
|
-
For groups of items that wrap as a unit (tag lists, button rows,
|
|
86
|
-
metadata chips) — distinct from `SwissGrid`, which is column-track-based.
|
|
87
|
-
- **`Flow`** — vertical stack with automatic rhythm: renders `> * + *
|
|
88
|
-
{ margin-block-start: var(--fluid-space-<size>) }` scoped via a CSS
|
|
89
|
-
class, `size` prop selecting the `core` fluid-space token. For prose-like
|
|
90
|
-
vertical sequences where every child needs the same gap, without each
|
|
91
|
-
child managing its own margin.
|
|
92
|
-
|
|
93
|
-
`HStack`/`VStack`/`Split` (old layer) are not duplicated here — `Cluster`
|
|
94
|
-
and `Flow` cover shapes those don't (wrap-as-a-unit and auto-rhythm
|
|
95
|
-
respectively), not full stack semantics.
|
|
96
|
-
|
|
97
|
-
## §4 Vertical rhythm and fluid tokens — reusing `core`
|
|
98
|
-
|
|
99
|
-
`core` already ships `layers/core/app/assets/css/tokens/spacing-fluid.css`:
|
|
100
|
-
`--fluid-space-xs` through `--fluid-space-3xl`, `clamp()`-based, **plus**
|
|
101
|
-
`-cq` container-relative variants (`--fluid-space-md-cq`, etc.) already
|
|
102
|
-
built on `cqi` units. This is exactly what the artifact's §5 (baseline
|
|
103
|
-
scale) and §6 (fluid `clamp()` tokens) ask for.
|
|
104
|
-
|
|
105
|
-
**Decision: swiss-grid does not define its own spacing scale.** `gap` on
|
|
106
|
-
`SwissGrid`, `Cluster`, and `Flow` all take `core`'s `Spacing` token type
|
|
107
|
-
and resolve to `core`'s existing `--fluid-space-*` custom properties (the
|
|
108
|
-
`-cq` variant when the component sits inside a `container-type` ancestor,
|
|
109
|
-
plain variant otherwise). No new token set, no duplication, no future
|
|
110
|
-
convergence work needed — building a parallel scale here would be
|
|
111
|
-
first-rung ladder work nobody asked for.
|
|
112
|
-
|
|
113
|
-
## §5 Container queries (§7)
|
|
114
|
-
|
|
115
|
-
`container-type: inline-size` ships on `SwissGrid` by default (not opt-in)
|
|
116
|
-
— every grid is nestable. Column-count and gap responsiveness _can_ be
|
|
117
|
-
expressed via `@container` queries scoped to a `SwissGrid`'s own inline
|
|
118
|
-
size (for a grid inside a sidebar vs. full page) as well as via the
|
|
119
|
-
viewport-keyed `ResponsiveValue` breakpoints in §1 — both are supported,
|
|
120
|
-
picked per-usage by which query type the CSS in question actually needs.
|
|
121
|
-
|
|
122
|
-
## §6 Dev overlay (§10)
|
|
123
|
-
|
|
124
|
-
`SwissGridDebug` component, same `⌘⇧G` shortcut and visual language as the
|
|
125
|
-
old layer's `LayoutGridDebug`, reimplemented against the new grid's column
|
|
126
|
-
custom properties. Toggles a column-boundary overlay for whichever
|
|
127
|
-
`SwissGrid` instances are on screen.
|
|
128
|
-
|
|
129
|
-
## §7 CSS conventions
|
|
130
|
-
|
|
131
|
-
All new CSS in this layer uses **logical properties**: `inline-size` /
|
|
132
|
-
`block-size` over `width`/`height`, `margin-inline`/`padding-block` over
|
|
133
|
-
directional variants, etc. This is a deliberate departure from some
|
|
134
|
-
existing CSS in the repo (which uses physical properties) — noted as a
|
|
135
|
-
forward-looking convention for this layer only; not a retrofit of `layout`
|
|
136
|
-
or other layers.
|
|
137
|
-
|
|
138
|
-
## §8 Not building
|
|
139
|
-
|
|
140
|
-
- **No "Section" concept.** The artifact never mentions viewport-height
|
|
141
|
-
sections — that's `layout`-specific (12-row/100vh `LayoutSection`). Out
|
|
142
|
-
of scope.
|
|
143
|
-
- **No migration of `content`/`navigation` consumers.** Explicitly deferred
|
|
144
|
-
to a later pass per user decision.
|
|
145
|
-
- **No shared code with `layout`'s `gridPlacementStyle.ts`.** Pattern
|
|
146
|
-
reused, implementation is new and independent.
|
|
147
|
-
|
|
148
|
-
## §9 File layout
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
layers/structure/swiss-grid/
|
|
152
|
-
├── app/
|
|
153
|
-
│ ├── assets/css/
|
|
154
|
-
│ │ └── swiss-grid.css # entry point, imports below
|
|
155
|
-
│ ├── components/
|
|
156
|
-
│ │ ├── SwissGrid.vue
|
|
157
|
-
│ │ ├── SwissGridItem.vue
|
|
158
|
-
│ │ ├── SwissGridDebug.vue
|
|
159
|
-
│ │ ├── Cluster.vue
|
|
160
|
-
│ │ └── Flow.vue
|
|
161
|
-
│ ├── composables/
|
|
162
|
-
│ │ └── useSwissGrid.ts # config resolution, span-alias lookup
|
|
163
|
-
│ ├── utils/
|
|
164
|
-
│ │ └── gridItemStyle.ts # pure style-building fns (start/span/order)
|
|
165
|
-
│ ├── types/
|
|
166
|
-
│ │ └── swissGrid.ts # SwissGridProps, SwissGridItemProps, SpanAlias
|
|
167
|
-
│ └── app.config.ts # swissGridLayer.ui.{columns,spanAliases}
|
|
168
|
-
├── nuxt.config.ts # extends: ['../../core'], alias #layers/swiss-grid
|
|
169
|
-
└── CLAUDE.md
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## §10 Testing
|
|
173
|
-
|
|
174
|
-
- `gridItemStyle.test.ts` — unit tests for the start/span/order → inline
|
|
175
|
-
style function, and the alias→span clamped-lookup function (mirrors old
|
|
176
|
-
layer's `gridPlacementStyle.test.ts` shape).
|
|
177
|
-
- `tests/nuxt/use-swiss-grid.test.ts` — composable resolution test (config
|
|
178
|
-
defaults, override via app.config), same pattern as
|
|
179
|
-
`use-grid-config.test.ts`.
|
|
180
|
-
- Component mount tests for `SwissGrid`/`SwissGridItem` (renders expected
|
|
181
|
-
`grid-template-columns`/`grid-column` given props).
|
|
182
|
-
- New playground demo page (not `layout.vue` — a separate page, e.g.
|
|
183
|
-
`apps/playground/app/pages/swiss-grid.vue`) to visually verify: column
|
|
184
|
-
grid at each breakpoint, span aliases, `Cluster`/`Flow`, container-query
|
|
185
|
-
nesting, dev overlay.
|
|
186
|
-
|
|
187
|
-
## §11 Open items carried forward
|
|
188
|
-
|
|
189
|
-
None from the artifact remain open — §2 above resolves the span-alias set,
|
|
190
|
-
§6 resolves the dev-overlay mechanism (reuse of the old layer's shortcut).
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
# Layout Layer — Fluid Rebuild Design Spec
|
|
2
|
-
|
|
3
|
-
Source: `LAYOUT-SYSTEM.md` (forensic reference for the `swiss-test/`
|
|
4
|
-
prototype — `src/layout.css`, vanilla Vite/TS, no framework), validated
|
|
5
|
-
against the working prototype at `/Users/kieranmansfield/Developer/layers/swiss-test`.
|
|
6
|
-
This document adapts that CSS-only derivation into a full rebuild of
|
|
7
|
-
`layers/structure/layout`, replacing its current breakpoint-based
|
|
8
|
-
6/12/18-column subgrid system.
|
|
9
|
-
|
|
10
|
-
## §0 Relationship to the Swiss Grid tier-2 spec
|
|
11
|
-
|
|
12
|
-
`docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md` proposes a
|
|
13
|
-
**separate sibling layer** (`layers/structure/swiss-grid`) that leaves
|
|
14
|
-
`layers/structure/layout` untouched. This spec is a **different track**: it
|
|
15
|
-
replaces `layout` itself, in place, rather than adding a new layer beside
|
|
16
|
-
it. The two specs are not both implementable as originally scoped — before
|
|
17
|
-
implementation starts on this one, reconcile with the user whether the
|
|
18
|
-
tier-2 sibling-layer spec is superseded, deferred, or still wanted
|
|
19
|
-
alongside this rebuild.
|
|
20
|
-
|
|
21
|
-
## §1 Governing idea
|
|
22
|
-
|
|
23
|
-
One root unit derives everything else. No breakpoints, no orientation
|
|
24
|
-
query, no hand-picked column counts.
|
|
25
|
-
|
|
26
|
-
```text
|
|
27
|
-
--fs (fluid font-size)
|
|
28
|
-
→ line-height (rounded to px)
|
|
29
|
-
→ --unit: 1rlh
|
|
30
|
-
→ --edge-min, --lpf, --measure-min
|
|
31
|
-
→ --lines, --fields, --type-b, --slack
|
|
32
|
-
→ padding-block, grid tracks, gap
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Change `--fs`'s clamp and the whole grid — margins, field height, column
|
|
36
|
-
count threshold — rescales in step. The grid has no size values of its
|
|
37
|
-
own, only ratios against `--unit`. This is CSS-only: no JS computes grid
|
|
38
|
-
math at runtime.
|
|
39
|
-
|
|
40
|
-
## §2 Scope decisions (from brainstorming)
|
|
41
|
-
|
|
42
|
-
- **Clean break.** No `colStart`/`colSpan`/`rowStart`/`rowSpan` numbered
|
|
43
|
-
placement API. Auto-fill's native column resolution
|
|
44
|
-
(`floor((available + gutter) / (measure-min + gutter))`) is the only
|
|
45
|
-
column-count mechanism — no mathematically-generated `--cols` ladder,
|
|
46
|
-
since a `calc()`/`round()`-derived integer fed into `repeat()`'s
|
|
47
|
-
track-count position is the exact failure mode Pitfall 1 (§7) already
|
|
48
|
-
proved broken in this codebase.
|
|
49
|
-
- **Layout owns `--fs`/`line-height`.** Matches the repo's existing
|
|
50
|
-
convention (CLAUDE.md's open item, option 1) — layout owns the one
|
|
51
|
-
clamp that feeds the grid; typography layer owns everything else
|
|
52
|
-
(font-family, weight scale, prose styles, headings outside grid cells).
|
|
53
|
-
- **Per-section row derivation, restored.** Not a flat, purely continuous
|
|
54
|
-
page (see §4) — the field/line math runs per `LayoutSection`, not once
|
|
55
|
-
globally per page.
|
|
56
|
-
- **CSS `@property` typing, not TS.** Every derived custom property gets a
|
|
57
|
-
real `syntax` descriptor. No TypeScript interface for the JS→CSS var
|
|
58
|
-
bridge (config tunables → `:style`) — out of scope.
|
|
59
|
-
- **Unrelated components untouched.** `HStack`/`VStack`/`ZStack`/`Spacer`,
|
|
60
|
-
`LayoutPage`/`LayoutPageHeader`, the z-index layer system
|
|
61
|
-
(`useZIndex`/`GridLayers`), and the `⌘G` debug overlay carry forward —
|
|
62
|
-
rebuilt only where they touch grid mechanics.
|
|
63
|
-
- **No consumer migration in this task.** `layers/content`,
|
|
64
|
-
`layers/structure/navigation`, and the playground/starter apps keep
|
|
65
|
-
calling the old API until a separate pass updates them. This task's
|
|
66
|
-
deliverable includes a migration guide document, not the migrations
|
|
67
|
-
themselves.
|
|
68
|
-
|
|
69
|
-
## §3 Derivation, step by step
|
|
70
|
-
|
|
71
|
-
Ported from the validated prototype (`swiss-test/src/layout.css`):
|
|
72
|
-
|
|
73
|
-
1. **Type.** `--fs: clamp(1rem, 0.95rem + 0.25svi, 1.125rem)`, registered
|
|
74
|
-
via `@property` as `<length>` so downstream `calc()` gets a resolved
|
|
75
|
-
length, not an unresolved token stream. `line-height` is
|
|
76
|
-
`round(nearest, fs * 1.5, 1px)` — rounded, not raw, so grid boundaries
|
|
77
|
-
land on-pixel.
|
|
78
|
-
2. **Unit.** `--unit: 1rlh`. `rlh` not `lh`: `lh` resolves against the
|
|
79
|
-
_current_ element, so a heading with a different line-height would
|
|
80
|
-
silently produce a different unit for anything nested in it. `rlh`
|
|
81
|
-
always resolves against root.
|
|
82
|
-
3. **Minimums.**
|
|
83
|
-
- `--measure-min: 22rem` — narrowest column, also the
|
|
84
|
-
`repeat(auto-fill, minmax(...))` floor and the `@container cell`
|
|
85
|
-
padding-step threshold.
|
|
86
|
-
- `--edge-min: clamp(1unit, 8svi, 3unit)` — margin floor > 0, steep
|
|
87
|
-
`svi` slope so it shrinks fast on narrow screens. Feeds `--avail-b`,
|
|
88
|
-
so it also trims top/bottom slack, not just inline edges.
|
|
89
|
-
4. **Lines** (per-section, see §4). `--avail-b: 100svh - 2*edge-min`.
|
|
90
|
-
`--lines: round(down, avail-b, unit) / unit` — the only way to get an
|
|
91
|
-
integer line-count out of a length in CSS.
|
|
92
|
-
5. **Fields** (per-section). `--lpf` (lines-per-field) clamped 4–8, scaled
|
|
93
|
-
by viewport height (`round(down, 100svh/unit/4.5, 1)`) so a fixed
|
|
94
|
-
`lpf=8` can't strand up to 8 line-heights as dead padding on a short
|
|
95
|
-
viewport. `--fields: max(1, round(down, (lines+1)/(lpf+1), 1))`.
|
|
96
|
-
6. **Margins** (per-section). Whatever's left over, split by the
|
|
97
|
-
section's `align` prop (§4) — computed last because it can't be
|
|
98
|
-
chosen, only what remains after the whole-line constraint.
|
|
99
|
-
`--slack: 100svh - type-b`, clamped `max(0px, …)` on both sides so a
|
|
100
|
-
short/landscape viewport degrades to scroll instead of negative
|
|
101
|
-
padding.
|
|
102
|
-
7. **Columns.** `repeat(auto-fill, minmax(measure-min, 1fr))` on the root
|
|
103
|
-
grid only. Native `auto-fill` computes column count from available
|
|
104
|
-
space directly, without needing an integer derived via `calc()`.
|
|
105
|
-
|
|
106
|
-
## §4 Section model
|
|
107
|
-
|
|
108
|
-
The root (`LayoutMain`) is a continuous auto-fill grid — content not
|
|
109
|
-
wrapped in a `LayoutSection` flows and wraps normally, sized only by
|
|
110
|
-
`--measure-min`/`--unit`, no viewport-height chunking.
|
|
111
|
-
|
|
112
|
-
`LayoutSection` is an **opt-in full-width row**:
|
|
113
|
-
|
|
114
|
-
- `grid-column: 1 / -1`, `grid-template-columns: subgrid` — inherits
|
|
115
|
-
however many explicit columns the root's `auto-fill` resolved. This is
|
|
116
|
-
legal: subgrid adopts the parent's resolved explicit track count
|
|
117
|
-
whatever it is; it only breaks when something tries to _address_ a
|
|
118
|
-
column by number, which nothing in this design does. A `.span-2` class
|
|
119
|
-
inside a subgridded section asks for "2 of however many columns exist,"
|
|
120
|
-
the same trick the prototype's own `.span-2` container-query gate uses
|
|
121
|
-
(§6) — it works identically whether the parent's tracks came from a
|
|
122
|
-
fixed count or from `auto-fill`.
|
|
123
|
-
- Block-size defaults to `100svh` (overridable via a `height` prop), and
|
|
124
|
-
it runs its own §3 steps 4–6 scoped to itself — same global
|
|
125
|
-
`--unit`/`--edge-min`/`--lpf` from `:root`, applied per-section instead
|
|
126
|
-
of once per-page.
|
|
127
|
-
- `align` prop: `'split'` (the prototype's default 40/60 optical-center
|
|
128
|
-
padding split) or `'center'` (`place-content: center` — true
|
|
129
|
-
horizontal+vertical centering). Explicit choice, not a fight against
|
|
130
|
-
`align-items: stretch` defaults — this directly addresses the prior
|
|
131
|
-
centering pain: the old `LayoutSection`/`GridItem` combo had no
|
|
132
|
-
first-class centering prop, so centering meant fighting
|
|
133
|
-
`grid-auto-rows`'s fixed track height and the container's default
|
|
134
|
-
stretch behavior.
|
|
135
|
-
|
|
136
|
-
## §5 Components
|
|
137
|
-
|
|
138
|
-
```text
|
|
139
|
-
layers/structure/layout/app/components/
|
|
140
|
-
├── HStack.vue / VStack.vue / ZStack.vue / Spacer.vue # unchanged
|
|
141
|
-
└── Layout/
|
|
142
|
-
├── Main.vue # rebuilt: root auto-fill grid, --fs/--unit owner
|
|
143
|
-
├── Section.vue # rebuilt: opt-in full-width subgrid row, §4
|
|
144
|
-
├── Cell.vue # new, replaces Grid/Item.vue
|
|
145
|
-
├── Hero.vue # new, replaces the `hero` GridItem preset
|
|
146
|
-
├── Grid/Debug.vue # rebuilt: visualizes --unit/field boundaries
|
|
147
|
-
└── Page/
|
|
148
|
-
├── index.vue # unchanged
|
|
149
|
-
└── Header.vue # unchanged
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
- **`LayoutMain`** — kept name (minimizes churn for whatever later
|
|
153
|
-
migrates to it), rebuilt internals. Renders `<main>` as the root
|
|
154
|
-
auto-fill grid. Registers `--fs`, binds config tunables to CSS custom
|
|
155
|
-
properties via `:style`.
|
|
156
|
-
- **`LayoutSection`** — see §4.
|
|
157
|
-
- **`LayoutCell`** (replaces `LayoutGridItem`) — `variant: 'block' |
|
|
158
|
-
'plate'` prop (border vs. filled, matching the prototype's `.block`/
|
|
159
|
-
`.plate`), `span2` / `span2Rows` / `span3Rows` boolean/enum props. No
|
|
160
|
-
`colStart`/`rowStart`/`preset`/`layer`/`bleed` — those go in the
|
|
161
|
-
migration guide as removed, with the nearest equivalent noted.
|
|
162
|
-
- **`LayoutHero`** (replaces the `hero` `GridItem` preset) — standalone,
|
|
163
|
-
full-viewport (`100svh`) flex-centered, deliberately outside the grid
|
|
164
|
-
entirely (no `--fields`, no column derivation) — matches the
|
|
165
|
-
prototype's `.hero`.
|
|
166
|
-
- **`LayoutGridDebug`** — same `⌘⇧G` shortcut, rewritten to overlay
|
|
167
|
-
`--unit`/field boundaries (via `getComputedStyle`) instead of a fixed
|
|
168
|
-
column count, since column count is now emergent.
|
|
169
|
-
- `Layout/Grid/Item.vue` and `Layout/Section/{Gallery,Hero,Split}.vue` —
|
|
170
|
-
deleted; superseded by `Cell`/`Hero`/`Section`.
|
|
171
|
-
|
|
172
|
-
## §6 CSS `@property` registration
|
|
173
|
-
|
|
174
|
-
Every derived custom property gets a `syntax` descriptor, extending the
|
|
175
|
-
prototype's existing `--fs` registration:
|
|
176
|
-
|
|
177
|
-
| Property | `syntax` |
|
|
178
|
-
| ---------------------------------- | ----------- |
|
|
179
|
-
| `--fs` | `<length>` |
|
|
180
|
-
| `--unit` | `<length>` |
|
|
181
|
-
| `--edge-min` | `<length>` |
|
|
182
|
-
| `--measure-min` | `<length>` |
|
|
183
|
-
| `--lpf` | `<integer>` |
|
|
184
|
-
| `--lines` | `<integer>` |
|
|
185
|
-
| `--fields` | `<integer>` |
|
|
186
|
-
| `--avail-b`, `--type-b`, `--slack` | `<length>` |
|
|
187
|
-
|
|
188
|
-
Registration guards against Pitfall 1's failure mode (§7) as new CSS is
|
|
189
|
-
added later: an unregistered custom property built from `calc()`/
|
|
190
|
-
`round()` silently substitutes as a token stream instead of a resolved
|
|
191
|
-
value at points that require one, invalidating the whole declaration and
|
|
192
|
-
falling back to implicit auto-sized tracks — a squash bug that's invisible
|
|
193
|
-
to `pnpm build` and only catchable via real browser `getComputedStyle()`
|
|
194
|
-
inspection.
|
|
195
|
-
|
|
196
|
-
## §7 Pitfalls carried forward (verified in the prototype, must not regress)
|
|
197
|
-
|
|
198
|
-
1. **`repeat(var(--n), ...)` silently invalidates.** `repeat()`'s
|
|
199
|
-
track-count argument requires a literal `<integer>` at computed-value
|
|
200
|
-
time — an unregistered `calc()`/`round()`-derived custom property
|
|
201
|
-
doesn't satisfy that. Fix: `repeat(auto-fill, minmax(<length>, 1fr))`,
|
|
202
|
-
never a `var()`-derived count. This is _why_ §2 rejects a mathematical
|
|
203
|
-
`--cols` ladder for v1.
|
|
204
|
-
2. **Span utilities forcing malformed implicit tracks.** `span-2`
|
|
205
|
-
unconditionally applying `grid-column: span 2` can force CSS Grid to
|
|
206
|
-
fabricate a content-sized implicit column when only 1 explicit column
|
|
207
|
-
resolved (narrow/medium viewport), squashing siblings. Fix:
|
|
208
|
-
`grid-auto-columns: minmax(measure-min, 1fr)` (belt-and-braces) plus
|
|
209
|
-
gating `.span-2` behind `@container viewport (min-width: 2 *
|
|
210
|
-
measure-min + gutter)` so it only activates once 2 columns have
|
|
211
|
-
genuinely resolved.
|
|
212
|
-
3. **Hand-synced container-query thresholds.** `@container` conditions
|
|
213
|
-
can't reference custom properties — the `@container cell (max-width:
|
|
214
|
-
22rem)` / `@container viewport (min-width: 46rem)` thresholds must be
|
|
215
|
-
hand-kept in sync with `--measure-min`, commented at both ends.
|
|
216
|
-
|
|
217
|
-
## §8 Constraints to preserve
|
|
218
|
-
|
|
219
|
-
- Every fluid `clamp()` keeps a `rem` term — a pure `vw`/`cqi` middle term
|
|
220
|
-
ignores browser zoom, fails WCAG 1.4.4.
|
|
221
|
-
- Never `line-height: normal` on `:root` — font-metric dependent, whole
|
|
222
|
-
grid would reflow on webfont swap.
|
|
223
|
-
- `svh`/`svi`, never `dvh`/`vw`/`vh` — `dvh` recomputes on mobile URL-bar
|
|
224
|
-
collapse, reflowing mid-scroll.
|
|
225
|
-
- `lh`/`rlh` don't resolve correctly in media queries (resolve against
|
|
226
|
-
initial font there) — use `rem`, or a container query with `cqi`.
|
|
227
|
-
- `container-type` never on `body` (becomes the `position: fixed`
|
|
228
|
-
containing block for descendants — an unrelated footgun).
|
|
229
|
-
|
|
230
|
-
## §9 Config
|
|
231
|
-
|
|
232
|
-
`app.config.ts`:
|
|
233
|
-
|
|
234
|
-
```ts
|
|
235
|
-
layoutLayer: {
|
|
236
|
-
ui: {
|
|
237
|
-
grid: {
|
|
238
|
-
mode: 'fluid' | 'disabled'
|
|
239
|
-
tunables: {
|
|
240
|
-
measureMin: string // e.g. '22rem'
|
|
241
|
-
edgeMin: {
|
|
242
|
-
min: string
|
|
243
|
-
max: string
|
|
244
|
-
} // clamp bounds
|
|
245
|
-
lpf: {
|
|
246
|
-
min: number
|
|
247
|
-
max: number
|
|
248
|
-
} // lines-per-field bounds
|
|
249
|
-
}
|
|
250
|
-
layers: GridLayers // z-index system, unchanged
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
`useGridConfig()`:
|
|
257
|
-
|
|
258
|
-
```ts
|
|
259
|
-
const { config, mode, isEnabled, layers, useZIndex, cssVars } = useGridConfig()
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
- `getPreset` — removed (no addressable placement left to preset).
|
|
263
|
-
- `cssVars` — new: computed map of tunables → CSS custom property
|
|
264
|
-
strings, consumed by `LayoutMain`/`LayoutSection`'s `:style` binding.
|
|
265
|
-
This is the JS→CSS bridge; per §2, it carries no dedicated TS interface
|
|
266
|
-
beyond the existing `GridConfig` type in `layouts.ts`.
|
|
267
|
-
- `mode`/`isEnabled`/`layers`/`useZIndex` — unchanged behavior.
|
|
268
|
-
`'disabled'` mode renders a plain `<main>`, no grid CSS, same fallback
|
|
269
|
-
as today.
|
|
270
|
-
|
|
271
|
-
## §10 Testing
|
|
272
|
-
|
|
273
|
-
- `gridPlacementStyle.ts`/`.test.ts` — deleted. Placement is static CSS
|
|
274
|
-
classes now (`span2`, etc.); there's no positioning math left to unit
|
|
275
|
-
test.
|
|
276
|
-
- New: a small test for `useGridConfig`'s `cssVars` mapping and
|
|
277
|
-
`mode`/`isEnabled` resolution (mirrors the existing composable test
|
|
278
|
-
shape).
|
|
279
|
-
- Manual verification: `getComputedStyle` sweep at 500 / 768 / 900 /
|
|
280
|
-
1024 / 1440 / 1920px, checking `gridTemplateColumns`/`gridAutoRows`
|
|
281
|
-
against expectation at each width, and that `.span-2`/`--fields`
|
|
282
|
-
thresholds gate correctly — the same method that caught Pitfalls 1–2 in
|
|
283
|
-
the prototype, since computed-value grid bugs are invisible to
|
|
284
|
-
`pnpm build`'s pure syntax check.
|
|
285
|
-
- Playground: existing `apps/playground/app/pages/layout.vue` demo
|
|
286
|
-
rebuilt against the new components — visual check of continuous grid,
|
|
287
|
-
section centering (both `align` modes), hero, debug overlay.
|
|
288
|
-
|
|
289
|
-
## §11 Deliverables
|
|
290
|
-
|
|
291
|
-
1. Rebuilt `layers/structure/layout` per §5–§9.
|
|
292
|
-
2. `docs/LAYOUT.md` rewritten to describe the new system (supersedes the
|
|
293
|
-
6/12/18 breakpoint documentation).
|
|
294
|
-
3. A migration guide document (old → new API mapping: removed props,
|
|
295
|
-
nearest equivalents, config shape changes) for later use when
|
|
296
|
-
`layers/content`, `layers/structure/navigation`, and the
|
|
297
|
-
playground/starter apps are updated. Not implemented as part of this
|
|
298
|
-
task.
|
|
299
|
-
4. §0's spec-conflict reconciliation resolved before implementation
|
|
300
|
-
starts.
|
|
301
|
-
|
|
302
|
-
## §12 Not building
|
|
303
|
-
|
|
304
|
-
- No numbered column/row placement API (`colStart`, `rowStart`).
|
|
305
|
-
- No mathematically-generated `--cols` (§2, §7 pitfall 1).
|
|
306
|
-
- No consumer migration (content layer, navigation, playground/starter
|
|
307
|
-
call sites) — guide only.
|
|
308
|
-
- No TypeScript interface for the CSS var bridge — `@property` is the
|
|
309
|
-
only typing layer (§2, §6).
|
|
310
|
-
- No changes to `HStack`/`VStack`/`ZStack`/`Spacer`, `LayoutPage`/
|
|
311
|
-
`LayoutPageHeader`, or the z-index layer system beyond what's needed to
|
|
312
|
-
keep them working against the rebuilt `LayoutMain`.
|