kmcom-nuxt-layers 6.2.1 → 6.4.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.3.0.md +234 -0
- package/docs/MIGRATION-v6.4.0.md +215 -0
- package/docs/MIGRATION.md +3 -0
- package/docs/adr/0003-modular-step-system-replaces-fluid-clamps.md +16 -0
- package/docs/component-levels.md +117 -0
- package/docs/layout-shift-causes.md +18 -0
- package/layers/content/app/components/Blog/ItemPage.vue +2 -7
- package/layers/content/app/components/Blog/List.vue +9 -2
- package/layers/content/app/components/Blog/Page.vue +9 -19
- package/layers/content/app/components/Gallery/Detail.vue +1 -0
- package/layers/content/app/components/Gallery/Grid.vue +9 -2
- package/layers/content/app/components/Gallery/ImageDetail.vue +0 -6
- package/layers/content/app/components/Gallery/ImagePage.vue +10 -6
- package/layers/content/app/components/Gallery/Page.vue +9 -19
- package/layers/content/app/components/Gallery/SlugPage.vue +2 -7
- package/layers/content/app/components/NuxtContent/Detail.vue +20 -11
- package/layers/content/app/components/NuxtContent/IndexTemplate.vue +21 -0
- package/layers/content/app/components/NuxtContent/List.vue +6 -1
- package/layers/content/app/components/Portfolio/ColorPalette.vue +2 -2
- package/layers/content/app/components/Portfolio/ItemPage.vue +2 -6
- package/layers/content/app/components/Portfolio/List.vue +19 -8
- package/layers/content/app/components/Portfolio/Page.vue +9 -19
- package/layers/content/app/composables/useContentItemSeo.ts +19 -0
- package/layers/content/app/composables/useContentSection.ts +9 -0
- package/layers/content/app/utils/galleryImageMeta.test.ts +30 -0
- package/layers/content/app/utils/galleryImageMeta.ts +11 -0
- package/layers/content/nuxt.config.ts +1 -1
- package/layers/core/app/app.config.ts +2 -2
- package/layers/core/app/app.vue +2 -1
- package/layers/core/app/assets/css/core.css +5 -11
- package/layers/core/app/assets/css/tokens/z-index.css +16 -0
- package/layers/core/app/components/DiagnosticsPage.vue +41 -41
- package/layers/core/app/components/LoadingScreen.vue +2 -0
- package/layers/core/app/utils/loading.test.ts +2 -2
- package/layers/core/app/utils/loading.ts +1 -1
- package/layers/delivery/feeds/app/components/Feeds/Index.vue +36 -75
- package/layers/delivery/feeds/app/components/Feeds/RouteCard.vue +6 -8
- package/layers/design-system/theming/nuxt.config.ts +1 -3
- package/layers/design-system/typography/app/assets/css/typography.css +41 -5
- package/layers/design-system/visual/app/components/Base/Modal.vue +34 -86
- package/layers/design-system/visual/app/components/HoverDimGroup.test.ts +38 -0
- package/layers/design-system/visual/app/components/HoverDimGroup.vue +54 -0
- package/layers/design-system/visual/app/components/Progress/Bar.vue +9 -29
- package/layers/motion/animations/app/components/Motion/Cursor.vue +1 -1
- package/layers/motion/animations/app/components/Motion/Marquee.vue +5 -0
- package/layers/motion/animations/app/components/Motion/MarqueeText.vue +2 -1
- package/layers/motion/animations/app/components/Motion/Staggered.test.ts +40 -0
- package/layers/motion/animations/app/components/Motion/Staggered.vue +37 -42
- package/layers/motion/animations/app/components/Motion/TextReveal.vue +8 -1
- package/layers/motion/animations/app/components/Motion/VelocityEffect.vue +6 -0
- package/layers/motion/animations/app/composables/useCountUp.ts +6 -0
- package/layers/motion/animations/app/composables/useCursorFollower.ts +4 -1
- package/layers/motion/animations/app/utils/pointerMotion.ts +7 -2
- package/layers/motion/scroll/app/components/Motion/HorizontalScroll.vue +9 -0
- package/layers/motion/scroll/app/components/Motion/Parallax.vue +13 -12
- package/layers/motion/scroll/app/components/Motion/PinnedSection.vue +16 -9
- package/layers/motion/scroll/app/composables/useReducedMotion.test.ts +23 -0
- package/layers/motion/scroll/app/composables/useReducedMotion.ts +14 -0
- package/layers/motion/scroll/app/utils/parallax.test.ts +24 -0
- package/layers/motion/scroll/app/utils/parallax.ts +16 -0
- package/layers/motion/scroll/nuxt.config.ts +1 -1
- package/layers/structure/layout/app/components/Layout/Grid/Debug.vue +1 -1
- package/layers/structure/layout/app/components/Layout/Page/index.vue +9 -10
- package/layers/structure/navigation/app/app.config.ts +37 -14
- package/layers/structure/navigation/app/components/Links/Group.vue +12 -38
- package/layers/structure/navigation/app/components/Links/Named.vue +9 -0
- package/layers/structure/navigation/app/components/Mast/Footer.vue +1 -1
- package/layers/structure/navigation/app/components/Mast/Nav.vue +14 -11
- package/layers/structure/navigation/app/components/Mast/NavModal.vue +95 -45
- package/layers/structure/navigation/app/components/Site/Logo.vue +35 -0
- package/layers/structure/navigation/app/components/Site/Subtitle.vue +10 -0
- package/layers/structure/navigation/app/components/Site/Title.vue +8 -0
- package/layers/structure/navigation/app/composables/mastNav.ts +38 -13
- package/layers/structure/navigation/app/types/nav.ts +34 -0
- package/layers/structure/navigation/nuxt.config.ts +7 -1
- package/package.json +1 -1
- /package/layers/{design-system/theming/app/assets/css/tokens.css → core/app/assets/css/tokens/elevation-motion.css} +0 -0
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<div class="space-y-8">
|
|
32
32
|
<div class="text-center">
|
|
33
33
|
<h1 class="mb-2 text-4xl font-bold">Core Layer Diagnostics</h1>
|
|
34
|
-
<p class="text-
|
|
34
|
+
<p class="text-muted">Feature detection and system information</p>
|
|
35
35
|
</div>
|
|
36
36
|
|
|
37
37
|
<UCard>
|
|
@@ -40,33 +40,33 @@
|
|
|
40
40
|
</template>
|
|
41
41
|
<div class="diag-grid-9 gap-3">
|
|
42
42
|
<div class="flex items-center gap-2">
|
|
43
|
-
<span v-if="grid" class="text-
|
|
44
|
-
<span v-else class="text-
|
|
43
|
+
<span v-if="grid" class="text-success">✓</span>
|
|
44
|
+
<span v-else class="text-error">✗</span>
|
|
45
45
|
<span>CSS Grid</span>
|
|
46
46
|
</div>
|
|
47
47
|
<div class="flex items-center gap-2">
|
|
48
|
-
<span v-if="subgrid" class="text-
|
|
49
|
-
<span v-else class="text-
|
|
48
|
+
<span v-if="subgrid" class="text-success">✓</span>
|
|
49
|
+
<span v-else class="text-error">✗</span>
|
|
50
50
|
<span>Subgrid</span>
|
|
51
51
|
</div>
|
|
52
52
|
<div class="flex items-center gap-2">
|
|
53
|
-
<span v-if="containerQueries" class="text-
|
|
54
|
-
<span v-else class="text-
|
|
53
|
+
<span v-if="containerQueries" class="text-success">✓</span>
|
|
54
|
+
<span v-else class="text-error">✗</span>
|
|
55
55
|
<span>Container Queries</span>
|
|
56
56
|
</div>
|
|
57
57
|
<div class="flex items-center gap-2">
|
|
58
|
-
<span v-if="has" class="text-
|
|
59
|
-
<span v-else class="text-
|
|
58
|
+
<span v-if="has" class="text-success">✓</span>
|
|
59
|
+
<span v-else class="text-error">✗</span>
|
|
60
60
|
<span>:has() Selector</span>
|
|
61
61
|
</div>
|
|
62
62
|
<div class="flex items-center gap-2">
|
|
63
|
-
<span v-if="aspectRatio" class="text-
|
|
64
|
-
<span v-else class="text-
|
|
63
|
+
<span v-if="aspectRatio" class="text-success">✓</span>
|
|
64
|
+
<span v-else class="text-error">✗</span>
|
|
65
65
|
<span>Aspect Ratio</span>
|
|
66
66
|
</div>
|
|
67
67
|
<div class="flex items-center gap-2">
|
|
68
|
-
<span v-if="backdropFilter" class="text-
|
|
69
|
-
<span v-else class="text-
|
|
68
|
+
<span v-if="backdropFilter" class="text-success">✓</span>
|
|
69
|
+
<span v-else class="text-error">✗</span>
|
|
70
70
|
<span>Backdrop Filter</span>
|
|
71
71
|
</div>
|
|
72
72
|
</div>
|
|
@@ -78,13 +78,13 @@
|
|
|
78
78
|
</template>
|
|
79
79
|
<div class="diag-grid-8 gap-3">
|
|
80
80
|
<div class="flex items-center gap-2">
|
|
81
|
-
<span v-if="webp" class="text-
|
|
82
|
-
<span v-else class="text-
|
|
81
|
+
<span v-if="webp" class="text-success">✓</span>
|
|
82
|
+
<span v-else class="text-error">✗</span>
|
|
83
83
|
<span>WebP</span>
|
|
84
84
|
</div>
|
|
85
85
|
<div class="flex items-center gap-2">
|
|
86
|
-
<span v-if="avif" class="text-
|
|
87
|
-
<span v-else class="text-
|
|
86
|
+
<span v-if="avif" class="text-success">✓</span>
|
|
87
|
+
<span v-else class="text-error">✗</span>
|
|
88
88
|
<span>AVIF</span>
|
|
89
89
|
</div>
|
|
90
90
|
</div>
|
|
@@ -96,23 +96,23 @@
|
|
|
96
96
|
</template>
|
|
97
97
|
<div class="diag-grid-9 gap-3">
|
|
98
98
|
<div class="flex items-center gap-2">
|
|
99
|
-
<span v-if="intersectionObserver" class="text-
|
|
100
|
-
<span v-else class="text-
|
|
99
|
+
<span v-if="intersectionObserver" class="text-success">✓</span>
|
|
100
|
+
<span v-else class="text-error">✗</span>
|
|
101
101
|
<span>IntersectionObserver</span>
|
|
102
102
|
</div>
|
|
103
103
|
<div class="flex items-center gap-2">
|
|
104
|
-
<span v-if="resizeObserver" class="text-
|
|
105
|
-
<span v-else class="text-
|
|
104
|
+
<span v-if="resizeObserver" class="text-success">✓</span>
|
|
105
|
+
<span v-else class="text-error">✗</span>
|
|
106
106
|
<span>ResizeObserver</span>
|
|
107
107
|
</div>
|
|
108
108
|
<div class="flex items-center gap-2">
|
|
109
|
-
<span v-if="serviceWorker" class="text-
|
|
110
|
-
<span v-else class="text-
|
|
109
|
+
<span v-if="serviceWorker" class="text-success">✓</span>
|
|
110
|
+
<span v-else class="text-error">✗</span>
|
|
111
111
|
<span>Service Worker</span>
|
|
112
112
|
</div>
|
|
113
113
|
<div class="flex items-center gap-2">
|
|
114
|
-
<span v-if="webGL" class="text-
|
|
115
|
-
<span v-else class="text-
|
|
114
|
+
<span v-if="webGL" class="text-success">✓</span>
|
|
115
|
+
<span v-else class="text-error">✗</span>
|
|
116
116
|
<span>WebGL</span>
|
|
117
117
|
</div>
|
|
118
118
|
</div>
|
|
@@ -139,8 +139,8 @@
|
|
|
139
139
|
<div class="space-y-2">
|
|
140
140
|
<div class="flex items-center gap-2">
|
|
141
141
|
<span class="w-24 font-medium">Status:</span>
|
|
142
|
-
<span v-if="isOnline" class="text-
|
|
143
|
-
<span v-else class="text-
|
|
142
|
+
<span v-if="isOnline" class="text-success">Online</span>
|
|
143
|
+
<span v-else class="text-error">Offline</span>
|
|
144
144
|
</div>
|
|
145
145
|
<div class="flex items-center gap-2">
|
|
146
146
|
<span class="w-24 font-medium">Type:</span>
|
|
@@ -150,10 +150,10 @@
|
|
|
150
150
|
<span class="w-24 font-medium">Quality:</span>
|
|
151
151
|
<span
|
|
152
152
|
:class="{
|
|
153
|
-
'text-
|
|
154
|
-
'text-
|
|
155
|
-
'text-
|
|
156
|
-
'text-
|
|
153
|
+
'text-success': connectionQuality === 'excellent',
|
|
154
|
+
'text-warning': connectionQuality === 'good',
|
|
155
|
+
'text-error': connectionQuality === 'poor',
|
|
156
|
+
'text-muted': connectionQuality === 'offline',
|
|
157
157
|
}"
|
|
158
158
|
>
|
|
159
159
|
{{ connectionQuality }}
|
|
@@ -161,13 +161,13 @@
|
|
|
161
161
|
</div>
|
|
162
162
|
<div class="flex items-center gap-2">
|
|
163
163
|
<span class="w-24 font-medium">Speed:</span>
|
|
164
|
-
<span v-if="isFast" class="text-
|
|
165
|
-
<span v-else-if="isSlow" class="text-
|
|
164
|
+
<span v-if="isFast" class="text-success">Fast</span>
|
|
165
|
+
<span v-else-if="isSlow" class="text-error">Slow</span>
|
|
166
166
|
<span v-else>Normal</span>
|
|
167
167
|
</div>
|
|
168
168
|
<div v-if="saveData" class="flex items-center gap-2">
|
|
169
169
|
<span class="w-24 font-medium">Data Saver:</span>
|
|
170
|
-
<span class="text-
|
|
170
|
+
<span class="text-warning">Enabled</span>
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
173
173
|
</UCard>
|
|
@@ -188,8 +188,8 @@
|
|
|
188
188
|
</div>
|
|
189
189
|
<div class="flex items-center gap-2">
|
|
190
190
|
<span class="w-24 font-medium">Hydrated:</span>
|
|
191
|
-
<span v-if="isHydrated" class="text-
|
|
192
|
-
<span v-else class="text-
|
|
191
|
+
<span v-if="isHydrated" class="text-success">Yes</span>
|
|
192
|
+
<span v-else class="text-warning">No</span>
|
|
193
193
|
</div>
|
|
194
194
|
</div>
|
|
195
195
|
</UCard>
|
|
@@ -201,17 +201,17 @@
|
|
|
201
201
|
<div class="space-y-2">
|
|
202
202
|
<div class="flex items-center gap-2">
|
|
203
203
|
<span class="w-24 font-medium">Installed:</span>
|
|
204
|
-
<span v-if="isInstalled" class="text-
|
|
205
|
-
<span v-else class="text-
|
|
204
|
+
<span v-if="isInstalled" class="text-success">Yes</span>
|
|
205
|
+
<span v-else class="text-muted">No</span>
|
|
206
206
|
</div>
|
|
207
207
|
<div class="flex items-center gap-2">
|
|
208
208
|
<span class="w-24 font-medium">Installable:</span>
|
|
209
|
-
<span v-if="canInstall" class="text-
|
|
210
|
-
<span v-else class="text-
|
|
209
|
+
<span v-if="canInstall" class="text-success">Yes</span>
|
|
210
|
+
<span v-else class="text-muted">No</span>
|
|
211
211
|
</div>
|
|
212
212
|
<div v-if="needRefresh" class="flex items-center gap-2">
|
|
213
213
|
<span class="w-24 font-medium">Update:</span>
|
|
214
|
-
<span class="text-
|
|
214
|
+
<span class="text-warning">Available</span>
|
|
215
215
|
</div>
|
|
216
216
|
</div>
|
|
217
217
|
</UCard>
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
'Helvetica Neue',
|
|
93
93
|
Arial,
|
|
94
94
|
sans-serif;
|
|
95
|
+
|
|
95
96
|
/* `backwards`, not `both` - a held end state would block the exit transition below */
|
|
96
97
|
animation: loading-enter 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.1s backwards;
|
|
97
98
|
}
|
|
@@ -110,6 +111,7 @@
|
|
|
110
111
|
font-stretch: ultra-expanded;
|
|
111
112
|
font-size: clamp(3rem, 35cqw + 1rem, 18rem);
|
|
112
113
|
line-height: 0.8;
|
|
114
|
+
|
|
113
115
|
/* Equal-width digits - the counter doesn't jitter as it ticks */
|
|
114
116
|
font-variant-numeric: tabular-nums;
|
|
115
117
|
}
|
|
@@ -6,9 +6,9 @@ const FRAME = 1 / 60
|
|
|
6
6
|
|
|
7
7
|
describe('resolveLoadingConfig', () => {
|
|
8
8
|
it('fills unset keys with defaults but keeps falsy values that were set', () => {
|
|
9
|
-
expect(resolveLoadingConfig(undefined)).toMatchObject({ enabled:
|
|
9
|
+
expect(resolveLoadingConfig(undefined)).toMatchObject({ enabled: false, minDuration: 1500 })
|
|
10
10
|
expect(resolveLoadingConfig({ loading: { minDuration: 0, label: '' } })).toMatchObject({
|
|
11
|
-
enabled:
|
|
11
|
+
enabled: false,
|
|
12
12
|
minDuration: 0,
|
|
13
13
|
label: '',
|
|
14
14
|
})
|
|
@@ -2,7 +2,7 @@ import type { LoadingConfig } from '../types/loading'
|
|
|
2
2
|
|
|
3
3
|
/** Fallbacks for keys app.config leaves unset - core's app.config ships the same values. */
|
|
4
4
|
const LOADING_DEFAULTS: LoadingConfig = {
|
|
5
|
-
enabled:
|
|
5
|
+
enabled: false,
|
|
6
6
|
minDuration: 1500,
|
|
7
7
|
maxDuration: 3000,
|
|
8
8
|
label: 'Loading',
|
|
@@ -20,18 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
<template>
|
|
22
22
|
<div
|
|
23
|
-
class="feeds-shell relative overflow-hidden rounded-4xl border
|
|
24
|
-
style="container-type: inline-size"
|
|
23
|
+
class="feeds-shell border-default bg-muted @container relative overflow-hidden rounded-4xl border shadow-xl"
|
|
25
24
|
>
|
|
26
25
|
<div class="pointer-events-none absolute inset-0">
|
|
26
|
+
<div class="bg-primary/20 absolute top-0 -right-20 h-72 w-72 rounded-full blur-3xl" />
|
|
27
|
+
<div class="bg-secondary/10 absolute bottom-0 -left-20 h-80 w-80 rounded-full blur-3xl" />
|
|
27
28
|
<div
|
|
28
|
-
class="absolute top-0
|
|
29
|
-
/>
|
|
30
|
-
<div
|
|
31
|
-
class="absolute bottom-0 -left-20 h-80 w-80 rounded-full bg-sky-400/12 blur-3xl dark:bg-sky-500/10"
|
|
32
|
-
/>
|
|
33
|
-
<div
|
|
34
|
-
class="absolute inset-x-8 top-0 h-px bg-linear-to-r from-transparent via-orange-400/35 to-transparent"
|
|
29
|
+
class="via-primary/35 absolute inset-x-8 top-0 h-px bg-linear-to-r from-transparent to-transparent"
|
|
35
30
|
/>
|
|
36
31
|
</div>
|
|
37
32
|
|
|
@@ -39,19 +34,17 @@
|
|
|
39
34
|
<div class="feeds-split grid gap-6">
|
|
40
35
|
<div class="space-y-6">
|
|
41
36
|
<div
|
|
42
|
-
class="inline-flex items-center gap-2 rounded-full border
|
|
37
|
+
class="border-default bg-default/80 text-primary inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs font-semibold tracking-[0.35em] uppercase shadow-sm backdrop-blur"
|
|
43
38
|
>
|
|
44
39
|
<UIcon name="i-lucide-rss" class="text-sm" />
|
|
45
40
|
Feeds layer
|
|
46
41
|
</div>
|
|
47
42
|
|
|
48
43
|
<div class="space-y-3">
|
|
49
|
-
<h1
|
|
50
|
-
class="feeds-h1 max-w-3xl font-semibold tracking-tight text-slate-950 dark:text-slate-50"
|
|
51
|
-
>
|
|
44
|
+
<h1 class="feeds-h1 text-highlighted max-w-3xl font-semibold tracking-tight">
|
|
52
45
|
Feed catalog for {{ catalog.site.title }}
|
|
53
46
|
</h1>
|
|
54
|
-
<p class="feeds-body max-w-2xl leading-7
|
|
47
|
+
<p class="feeds-body text-toned max-w-2xl leading-7">
|
|
55
48
|
Configured in <code class="font-mono text-[0.9em]">app.config.ts</code>, validated
|
|
56
49
|
against <code class="font-mono text-[0.9em]">content.config.ts</code>, and rendered as
|
|
57
50
|
a human-readable index for readers and site owners.
|
|
@@ -60,82 +53,56 @@
|
|
|
60
53
|
|
|
61
54
|
<div class="feeds-cards-grid gap-3">
|
|
62
55
|
<div
|
|
63
|
-
class="
|
|
56
|
+
class="border-default bg-default/75 rounded-2xl border p-4 shadow-sm backdrop-blur"
|
|
64
57
|
>
|
|
65
|
-
<p
|
|
66
|
-
|
|
67
|
-
>
|
|
68
|
-
Default
|
|
69
|
-
</p>
|
|
70
|
-
<p class="mt-2 text-lg font-semibold text-slate-950 dark:text-slate-100">
|
|
58
|
+
<p class="text-muted text-xs font-semibold tracking-[0.3em] uppercase">Default</p>
|
|
59
|
+
<p class="text-highlighted mt-2 text-lg font-semibold">
|
|
71
60
|
{{ catalog.feed.defaultCollection }}
|
|
72
61
|
</p>
|
|
73
|
-
<p class="mt-1 text-xs
|
|
74
|
-
Shorthand routes point here.
|
|
75
|
-
</p>
|
|
62
|
+
<p class="text-muted mt-1 text-xs">Shorthand routes point here.</p>
|
|
76
63
|
</div>
|
|
77
64
|
|
|
78
65
|
<div
|
|
79
|
-
class="
|
|
66
|
+
class="border-default bg-default/75 rounded-2xl border p-4 shadow-sm backdrop-blur"
|
|
80
67
|
>
|
|
81
|
-
<p
|
|
82
|
-
|
|
83
|
-
>
|
|
84
|
-
Exposed
|
|
85
|
-
</p>
|
|
86
|
-
<p class="mt-2 text-lg font-semibold text-slate-950 dark:text-slate-100">
|
|
68
|
+
<p class="text-muted text-xs font-semibold tracking-[0.3em] uppercase">Exposed</p>
|
|
69
|
+
<p class="text-highlighted mt-2 text-lg font-semibold">
|
|
87
70
|
{{ catalog.collectionGroups.length }} collections
|
|
88
71
|
</p>
|
|
89
|
-
<p class="mt-1 text-xs
|
|
90
|
-
Published in the feed catalog.
|
|
91
|
-
</p>
|
|
72
|
+
<p class="text-muted mt-1 text-xs">Published in the feed catalog.</p>
|
|
92
73
|
</div>
|
|
93
74
|
|
|
94
75
|
<div
|
|
95
|
-
class="
|
|
76
|
+
class="border-default bg-default/75 rounded-2xl border p-4 shadow-sm backdrop-blur"
|
|
96
77
|
>
|
|
97
|
-
<p
|
|
98
|
-
|
|
99
|
-
>
|
|
100
|
-
Limit
|
|
101
|
-
</p>
|
|
102
|
-
<p class="mt-2 text-lg font-semibold text-slate-950 dark:text-slate-100">
|
|
78
|
+
<p class="text-muted text-xs font-semibold tracking-[0.3em] uppercase">Limit</p>
|
|
79
|
+
<p class="text-highlighted mt-2 text-lg font-semibold">
|
|
103
80
|
{{ catalog.feed.limit }} items
|
|
104
81
|
</p>
|
|
105
|
-
<p class="mt-1 text-xs
|
|
106
|
-
Applied to each feed response.
|
|
107
|
-
</p>
|
|
82
|
+
<p class="text-muted mt-1 text-xs">Applied to each feed response.</p>
|
|
108
83
|
</div>
|
|
109
84
|
</div>
|
|
110
85
|
|
|
111
86
|
<div
|
|
112
87
|
v-if="catalog.site.url || catalog.site.description"
|
|
113
|
-
class="flex flex-wrap items-center gap-3 rounded-2xl border
|
|
88
|
+
class="border-default bg-default/70 flex flex-wrap items-center gap-3 rounded-2xl border px-4 py-3 text-sm shadow-sm backdrop-blur"
|
|
114
89
|
>
|
|
115
|
-
<span
|
|
116
|
-
|
|
117
|
-
>
|
|
118
|
-
Site
|
|
119
|
-
</span>
|
|
120
|
-
<span v-if="catalog.site.description" class="text-slate-700 dark:text-slate-300">
|
|
90
|
+
<span class="text-muted text-xs font-semibold tracking-[0.3em] uppercase"> Site </span>
|
|
91
|
+
<span v-if="catalog.site.description" class="text-toned">
|
|
121
92
|
{{ catalog.site.description }}
|
|
122
93
|
</span>
|
|
123
94
|
<code
|
|
124
95
|
v-if="catalog.site.url"
|
|
125
|
-
class="
|
|
96
|
+
class="bg-elevated text-muted rounded-full px-2 py-1 font-mono text-xs"
|
|
126
97
|
>
|
|
127
98
|
{{ catalog.site.url }}
|
|
128
99
|
</code>
|
|
129
100
|
</div>
|
|
130
101
|
</div>
|
|
131
102
|
|
|
132
|
-
<aside
|
|
133
|
-
class="rounded-[1.5rem] border border-slate-200/80 bg-white/75 p-4 shadow-sm backdrop-blur dark:border-slate-800 dark:bg-slate-900/45"
|
|
134
|
-
>
|
|
103
|
+
<aside class="border-default bg-default/75 rounded-3xl border p-4 shadow-sm backdrop-blur">
|
|
135
104
|
<div class="flex items-center justify-between gap-3">
|
|
136
|
-
<p
|
|
137
|
-
class="text-[0.68rem] font-semibold tracking-[0.35em] text-slate-500 uppercase dark:text-slate-400"
|
|
138
|
-
>
|
|
105
|
+
<p class="text-muted text-xs font-semibold tracking-[0.35em] uppercase">
|
|
139
106
|
Global routes
|
|
140
107
|
</p>
|
|
141
108
|
<UBadge color="neutral" variant="subtle" size="xs">
|
|
@@ -161,18 +128,14 @@
|
|
|
161
128
|
<div class="space-y-4">
|
|
162
129
|
<div class="flex flex-wrap items-end justify-between gap-4">
|
|
163
130
|
<div>
|
|
164
|
-
<p
|
|
165
|
-
class="text-[0.68rem] font-semibold tracking-[0.35em] text-slate-500 uppercase dark:text-slate-400"
|
|
166
|
-
>
|
|
131
|
+
<p class="text-muted text-xs font-semibold tracking-[0.35em] uppercase">
|
|
167
132
|
Collection routes
|
|
168
133
|
</p>
|
|
169
|
-
<h2
|
|
170
|
-
class="mt-2 text-2xl font-semibold tracking-tight text-slate-950 dark:text-slate-100"
|
|
171
|
-
>
|
|
134
|
+
<h2 class="text-highlighted mt-2 text-2xl font-semibold tracking-tight">
|
|
172
135
|
Each exposed collection gets RSS, Atom, and JSON.
|
|
173
136
|
</h2>
|
|
174
137
|
</div>
|
|
175
|
-
<p class="max-w-lg text-sm
|
|
138
|
+
<p class="text-muted max-w-lg text-sm">
|
|
176
139
|
Add or remove collections in <code class="font-mono text-[0.9em]">app.config.ts</code>
|
|
177
140
|
and the catalog updates automatically.
|
|
178
141
|
</p>
|
|
@@ -183,21 +146,19 @@
|
|
|
183
146
|
v-for="group in catalog.collectionGroups"
|
|
184
147
|
:key="group.collection"
|
|
185
148
|
:ui="{ body: 'p-0' }"
|
|
186
|
-
class="
|
|
149
|
+
class="border-default bg-default/80 overflow-hidden shadow-sm backdrop-blur"
|
|
187
150
|
>
|
|
188
151
|
<div
|
|
189
|
-
class="flex flex-wrap items-start justify-between gap-4 border-b
|
|
152
|
+
class="border-default flex flex-wrap items-start justify-between gap-4 border-b px-5 py-4"
|
|
190
153
|
>
|
|
191
154
|
<div>
|
|
192
|
-
<p
|
|
193
|
-
class="text-[0.68rem] font-semibold tracking-[0.35em] text-slate-500 uppercase dark:text-slate-400"
|
|
194
|
-
>
|
|
155
|
+
<p class="text-muted text-xs font-semibold tracking-[0.35em] uppercase">
|
|
195
156
|
Collection
|
|
196
157
|
</p>
|
|
197
|
-
<h3 class="mt-2 text-xl font-semibold
|
|
158
|
+
<h3 class="text-highlighted mt-2 text-xl font-semibold">
|
|
198
159
|
{{ group.label }}
|
|
199
160
|
</h3>
|
|
200
|
-
<p class="mt-1 font-mono text-sm
|
|
161
|
+
<p class="text-muted mt-1 font-mono text-sm">
|
|
201
162
|
{{ group.collection }}
|
|
202
163
|
</p>
|
|
203
164
|
</div>
|
|
@@ -215,13 +176,13 @@
|
|
|
215
176
|
<UCard
|
|
216
177
|
v-else
|
|
217
178
|
:ui="{ body: 'p-0' }"
|
|
218
|
-
class="border-
|
|
179
|
+
class="border-accented bg-default/70 border-dashed shadow-none"
|
|
219
180
|
>
|
|
220
181
|
<div class="space-y-2 p-5">
|
|
221
|
-
<p class="text-sm font-medium
|
|
182
|
+
<p class="text-highlighted text-sm font-medium">
|
|
222
183
|
No collection feeds are currently exposed.
|
|
223
184
|
</p>
|
|
224
|
-
<p class="text-
|
|
185
|
+
<p class="text-muted text-sm">
|
|
225
186
|
Add page collections to
|
|
226
187
|
<code class="font-mono text-[0.9em]">feedsLayer.feed.collections</code>
|
|
227
188
|
in <code class="font-mono text-[0.9em]">app.config.ts</code>.
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
> = {
|
|
18
18
|
index: {
|
|
19
|
-
strip: 'bg-
|
|
20
|
-
dot: 'bg-
|
|
19
|
+
strip: 'bg-accented',
|
|
20
|
+
dot: 'bg-inverted/40',
|
|
21
21
|
},
|
|
22
22
|
rss: {
|
|
23
23
|
strip: 'bg-orange-400',
|
|
@@ -50,23 +50,21 @@
|
|
|
50
50
|
<UCard
|
|
51
51
|
:to="route.path"
|
|
52
52
|
:ui="{ body: 'p-0' }"
|
|
53
|
-
class="group @container relative overflow-hidden
|
|
53
|
+
class="group border-default bg-default/90 hover:border-accented @container relative overflow-hidden shadow-none transition duration-200 hover:-translate-y-0.5 hover:shadow-md"
|
|
54
54
|
>
|
|
55
55
|
<div class="absolute inset-y-0 left-0 w-1" :class="routeTone.strip" />
|
|
56
56
|
<div :class="compact ? 'flex items-center gap-3 p-3' : 'flex items-center gap-3 p-4'">
|
|
57
57
|
<span class="h-2.5 w-2.5 rounded-full" :class="routeTone.dot" />
|
|
58
58
|
<div class="min-w-0 flex-1">
|
|
59
59
|
<div class="flex items-start justify-between gap-3">
|
|
60
|
-
<p class="
|
|
60
|
+
<p class="text-highlighted font-medium">
|
|
61
61
|
{{ route.label }}
|
|
62
62
|
</p>
|
|
63
|
-
<code
|
|
64
|
-
class="shrink-0 rounded-full bg-slate-100 px-2 py-1 font-mono text-[0.72rem] text-slate-600 dark:bg-slate-800 dark:text-slate-300"
|
|
65
|
-
>
|
|
63
|
+
<code class="bg-elevated text-muted shrink-0 rounded-full px-2 py-1 font-mono text-xs">
|
|
66
64
|
{{ route.path }}
|
|
67
65
|
</code>
|
|
68
66
|
</div>
|
|
69
|
-
<p class="mt-1 text-xs
|
|
67
|
+
<p class="text-muted mt-1 text-xs">
|
|
70
68
|
{{ getRouteDescription() }}
|
|
71
69
|
</p>
|
|
72
70
|
</div>
|
|
@@ -25,9 +25,7 @@ export default defineNuxtConfig({
|
|
|
25
25
|
'#layers/theming/types': `${import.meta.dirname}/app/types`,
|
|
26
26
|
},
|
|
27
27
|
|
|
28
|
-
// tokens
|
|
29
|
-
// CSS single-build-root rule (see .claude/rules/nuxt-layers.md) it must fold into core.css's
|
|
30
|
-
// @import chain via relative path instead, or its @theme block is silently inert.
|
|
28
|
+
// Shadow/duration tokens live in core (core/app/assets/css/tokens/elevation-motion.css).
|
|
31
29
|
css: ['#layers/theming/app/assets/css/theme.css'],
|
|
32
30
|
|
|
33
31
|
plugins: ['#layers/theming/app/plugins/theme.client.ts'],
|
|
@@ -31,12 +31,25 @@
|
|
|
31
31
|
--type-scale: 1.26;
|
|
32
32
|
--type-snap: 0.0625rem; /* rounding interval: rem so it scales with the root; never px, never 0 */
|
|
33
33
|
|
|
34
|
-
/* Fluid display step
|
|
35
|
-
length to the unitless exponent pow() needs; normalised
|
|
36
|
-
|
|
37
|
-
larger root doesn't lower
|
|
34
|
+
/* Fluid display step: --display-from at ≤360px → --display-to at ≥1280px (57.5 = 920px / 16).
|
|
35
|
+
tan(atan2(length, 1rem)) casts the length to the unitless exponent pow() needs; normalised
|
|
36
|
+
by 1rem (not 1px) so the exponent doesn't move with the user's root font size; the vw term
|
|
37
|
+
is scaled by root / 16px so a larger root doesn't lower it at a given width (h1 stays
|
|
38
|
+
visibly larger). Defaults reduce to clamp(5rem, 4.2176rem + 3.4784vw·k, 7rem).
|
|
39
|
+
--step-display resolves var() here at :root, so overriding --display-from/to on a subtree
|
|
40
|
+
only reaches elements that recompute it: text-step-display and h1 do. */
|
|
41
|
+
--display-from: 5;
|
|
42
|
+
--display-to: 7;
|
|
38
43
|
--step-display: tan(
|
|
39
|
-
atan2(
|
|
44
|
+
atan2(
|
|
45
|
+
clamp(
|
|
46
|
+
var(--display-from) * 1rem,
|
|
47
|
+
var(--display-from) * 1rem + (var(--display-to) - var(--display-from)) * (100vw - 360px) *
|
|
48
|
+
tan(atan2(1rem, 16px)) / 57.5,
|
|
49
|
+
var(--display-to) * 1rem
|
|
50
|
+
),
|
|
51
|
+
1rem
|
|
52
|
+
)
|
|
40
53
|
);
|
|
41
54
|
}
|
|
42
55
|
|
|
@@ -252,6 +265,18 @@
|
|
|
252
265
|
}
|
|
253
266
|
|
|
254
267
|
@utility text-step-display {
|
|
268
|
+
/* Recomputed here so [--display-from:4] [--display-to:9] on the element takes effect */
|
|
269
|
+
--step-display: tan(
|
|
270
|
+
atan2(
|
|
271
|
+
clamp(
|
|
272
|
+
var(--display-from) * 1rem,
|
|
273
|
+
var(--display-from) * 1rem + (var(--display-to) - var(--display-from)) * (100vw - 360px) *
|
|
274
|
+
tan(atan2(1rem, 16px)) / 57.5,
|
|
275
|
+
var(--display-to) * 1rem
|
|
276
|
+
),
|
|
277
|
+
1rem
|
|
278
|
+
)
|
|
279
|
+
);
|
|
255
280
|
--step: var(--step-display);
|
|
256
281
|
|
|
257
282
|
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|
|
@@ -283,6 +308,17 @@
|
|
|
283
308
|
|
|
284
309
|
/* Same expressions as the text-step-* utilities. h1 uses the display step. */
|
|
285
310
|
h1:where(:not([data-slot])) {
|
|
311
|
+
--step-display: tan(
|
|
312
|
+
atan2(
|
|
313
|
+
clamp(
|
|
314
|
+
var(--display-from) * 1rem,
|
|
315
|
+
var(--display-from) * 1rem + (var(--display-to) - var(--display-from)) * (100vw - 360px) *
|
|
316
|
+
tan(atan2(1rem, 16px)) / 57.5,
|
|
317
|
+
var(--display-to) * 1rem
|
|
318
|
+
),
|
|
319
|
+
1rem
|
|
320
|
+
)
|
|
321
|
+
);
|
|
286
322
|
--step: var(--step-display);
|
|
287
323
|
|
|
288
324
|
font-size: calc(var(--type-base) * pow(var(--type-scale), var(--step)));
|