kmcom-nuxt-layers 1.6.38 → 1.6.39
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.
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# UPage + Swiss Grid Integration
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
`<LayoutMain>` renders `<main class="mastmain">` which sets:
|
|
6
|
+
|
|
7
|
+
```css
|
|
8
|
+
.mastmain {
|
|
9
|
+
grid-auto-rows: calc((100vh - 11 * gap) / 12); /* ≈ 8.5vh per row */
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Every direct child that doesn't explicitly span rows becomes ~8.5vh tall. `<UPage>` and Nuxt UI's page components (`UPageSection`, `UPageHero`, etc.) don't span rows — so they collapse.
|
|
14
|
+
|
|
15
|
+
`.basesection` fixes this for `<LayoutSection>` by spanning 12 rows:
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
.basesection {
|
|
19
|
+
grid-row: span 12; /* 12 × 8.5vh ≈ 100vh */
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`<UPage>` has no equivalent. It's designed for document flow, not a fixed-row grid.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Approaches
|
|
28
|
+
|
|
29
|
+
### Option A — `minmax` on `grid-auto-rows` (Recommended)
|
|
30
|
+
|
|
31
|
+
**Change in `grids.css`:**
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
.mastmain {
|
|
35
|
+
/* Before */
|
|
36
|
+
grid-auto-rows: var(--grid-row-height);
|
|
37
|
+
|
|
38
|
+
/* After — allow rows to grow beyond their minimum */
|
|
39
|
+
grid-auto-rows: minmax(var(--grid-row-height), auto);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The mobile breakpoint already uses this. Apply it at all breakpoints.
|
|
44
|
+
|
|
45
|
+
**What changes:**
|
|
46
|
+
- `<LayoutSection>` spanning 12 rows = at least `12 × 8.5vh ≈ 100vh` (min preserved)
|
|
47
|
+
- `<UPage>` in a single row = auto-sized to its content height
|
|
48
|
+
- Column alignment is fully preserved
|
|
49
|
+
|
|
50
|
+
**Trade-off:** `rowStart` placement in `<LayoutGridItem>` becomes less predictable when rows above it grow beyond their minimum. `rowSpan` presets are unaffected.
|
|
51
|
+
|
|
52
|
+
**Implementation:** One-line CSS change in the layout layer source.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### Option B — `display: contents` on UPage
|
|
57
|
+
|
|
58
|
+
Configure `<UPage>` to be transparent to the grid so its children participate directly:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
// In frontend app.config.ts, override the layout layer's UPage config:
|
|
62
|
+
ui: {
|
|
63
|
+
page: {
|
|
64
|
+
root: 'col-span-full [display:contents]',
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
With `display: contents`, `<UPage>` generates no box — its children (`UPageHero`, `UPageSection`, etc.) become direct grid items in `mastmain`.
|
|
70
|
+
|
|
71
|
+
**What changes:**
|
|
72
|
+
- `<UPage>` styling is effectively gone (use with care)
|
|
73
|
+
- Each child component becomes a grid item and needs its own column/row spanning
|
|
74
|
+
- Requires configuring `UPageSection`, `UPageHero`, etc. similarly
|
|
75
|
+
|
|
76
|
+
**Trade-off:** You lose `<UPage>`'s layout structure. Works best when you're using it purely as a semantic grouping with no visual styling.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Option C — `<LayoutPage>` component (Hybrid mode)
|
|
81
|
+
|
|
82
|
+
A new component that gives pages an explicit choice between Swiss Grid and normal document flow:
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<!-- layers/layout/app/components/Layout/Page/index.vue -->
|
|
86
|
+
<script setup lang="ts">
|
|
87
|
+
interface Props {
|
|
88
|
+
mode?: 'swiss' | 'flow'
|
|
89
|
+
}
|
|
90
|
+
const { mode = 'swiss' } = defineProps<Props>()
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<template>
|
|
94
|
+
<!-- Swiss: children participate directly in mastmain grid (use LayoutSection) -->
|
|
95
|
+
<template v-if="mode === 'swiss'">
|
|
96
|
+
<slot />
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<!-- Flow: UPage mode — auto-height row that fills content -->
|
|
100
|
+
<div
|
|
101
|
+
v-else
|
|
102
|
+
class="col-span-full"
|
|
103
|
+
style="grid-row: auto / span 999; height: max-content; min-height: 0"
|
|
104
|
+
>
|
|
105
|
+
<UPage>
|
|
106
|
+
<slot />
|
|
107
|
+
</UPage>
|
|
108
|
+
</div>
|
|
109
|
+
</template>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Usage:
|
|
113
|
+
|
|
114
|
+
```vue
|
|
115
|
+
<!-- Swiss Grid page -->
|
|
116
|
+
<template>
|
|
117
|
+
<LayoutPage>
|
|
118
|
+
<LayoutSection full-height>
|
|
119
|
+
<LayoutGridItem preset="centered">
|
|
120
|
+
<h1>Title</h1>
|
|
121
|
+
</LayoutGridItem>
|
|
122
|
+
</LayoutSection>
|
|
123
|
+
</LayoutPage>
|
|
124
|
+
</template>
|
|
125
|
+
|
|
126
|
+
<!-- UPage page inside LayoutMain -->
|
|
127
|
+
<template>
|
|
128
|
+
<LayoutPage mode="flow">
|
|
129
|
+
<UPageHero title="About" />
|
|
130
|
+
<UPageSection>...</UPageSection>
|
|
131
|
+
</LayoutPage>
|
|
132
|
+
</template>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Trade-off:** `span 999` is an escape hatch — it works because CSS Grid clamps spans to the available track count. It's pragmatic but not semantically clean. Requires the component to live in the layout layer source.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### Option D — Per-page `<LayoutMain tag="div">` opt-in
|
|
140
|
+
|
|
141
|
+
Don't apply `<LayoutMain>` in the layouts at all. Let pages that want the Swiss Grid add it themselves inside their template:
|
|
142
|
+
|
|
143
|
+
```vue
|
|
144
|
+
<!-- A Swiss Grid page — no UPage -->
|
|
145
|
+
<template>
|
|
146
|
+
<LayoutMain tag="div">
|
|
147
|
+
<LayoutSection full-height>
|
|
148
|
+
<LayoutGridItem preset="hero">
|
|
149
|
+
<h1>Home</h1>
|
|
150
|
+
</LayoutGridItem>
|
|
151
|
+
</LayoutSection>
|
|
152
|
+
</LayoutMain>
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
<!-- A normal page — uses UMain from the layout, no grid involvement -->
|
|
156
|
+
<template>
|
|
157
|
+
<UPage>
|
|
158
|
+
<UPageHero title="About" />
|
|
159
|
+
</UPage>
|
|
160
|
+
</template>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**This is the current approach after the revert.** The layout layer is available everywhere but not globally applied. The `mastmain` CSS class exists — any element can opt in via `class="mastmain"` or `<LayoutMain tag="div">`.
|
|
164
|
+
|
|
165
|
+
**Trade-off:** No automatic column alignment across pages. Pages must explicitly adopt the grid.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Recommendation
|
|
170
|
+
|
|
171
|
+
**Short-term (no code changes required):** Option D — current approach. Build new sections using `<LayoutSection>` / `<LayoutGridItem>` inside pages that want the Swiss Grid. Existing `<UPage>` pages are untouched.
|
|
172
|
+
|
|
173
|
+
**Medium-term (one CSS change):** Option A — change `grid-auto-rows` to `minmax(var(--grid-row-height), auto)` in `grids.css`. This makes `<LayoutMain>` compatible with both Swiss Grid sections and UPage content at the same time, unlocking global application in the layouts with zero page changes.
|
|
174
|
+
|
|
175
|
+
**Long-term:** Migrate pages to the Swiss Grid pattern (no `<UPage>`) to take full advantage of precise row placement and the full 18-column subgrid system.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## CSS Grid Behaviour Reference
|
|
180
|
+
|
|
181
|
+
| Scenario | `grid-auto-rows: 8.5vh` | `grid-auto-rows: minmax(8.5vh, auto)` |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `<LayoutSection>` (spans 12 rows) | ✅ Exactly 100vh | ✅ At least 100vh, grows with content |
|
|
184
|
+
| `<UPage>` (1 auto row) | ❌ Collapsed to 8.5vh | ✅ Grows to content height |
|
|
185
|
+
| `<LayoutGridItem rowStart="3">` | ✅ Predictable position | ⚠️ Position shifts if rows above grew |
|
|
186
|
+
| `<LayoutGridItem rowSpan="6">` | ✅ 6 × 8.5vh = 51vh | ✅ At least 6 × 8.5vh |
|
|
@@ -77,7 +77,7 @@ onMounted(() => {
|
|
|
77
77
|
modifiers: {
|
|
78
78
|
x: gsap.utils.unitize((x) => {
|
|
79
79
|
const mod = contentWidth / 2
|
|
80
|
-
return props.direction === 'left' ? parseFloat(x) % mod :
|
|
80
|
+
return props.direction === 'left' ? parseFloat(x) % mod : Math.abs(parseFloat(x) % mod)
|
|
81
81
|
}),
|
|
82
82
|
},
|
|
83
83
|
})
|
package/package.json
CHANGED