kmcom-nuxt-layers 4.0.0 → 5.0.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/superpowers/plans/2026-09-03-layout-layer-fluid-rebuild.md +8 -8
- package/docs/superpowers/specs/2026-08-30-layer-taxonomy-tier-7-design.md +1 -1
- package/docs/superpowers/specs/2026-08-31-swiss-grid-layer-design.md +3 -3
- package/docs/superpowers/specs/2026-09-03-layout-layer-fluid-rebuild-design.md +3 -3
- package/layers/content/app/components/Blog/Article.vue +1 -1
- package/layers/content/app/components/Gallery/Detail.vue +8 -8
- package/layers/content/app/components/Gallery/Grid.vue +8 -8
- package/layers/content/app/components/Gallery/ImageDetail.vue +6 -6
- package/layers/content/app/components/Gallery/Lightbox.vue +3 -3
- package/layers/content/app/components/NuxtContent/Detail.vue +1 -1
- package/layers/content/app/components/NuxtContent/List.vue +1 -1
- package/layers/content/app/components/Portfolio/ColorPalette.vue +5 -5
- package/layers/content/app/components/Portfolio/Detail.vue +1 -1
- package/layers/content/app/components/Portfolio/List.vue +1 -1
- package/layers/content/app/components/Portfolio/Typography.vue +5 -5
- package/layers/content/app/components/content/Figure.vue +1 -1
- package/layers/core/app/assets/css/core.css +9 -9
- package/layers/core/app/assets/css/layout.css +1 -1
- package/layers/core/app/components/DiagnosticsPage.vue +15 -15
- package/layers/core/app/components/Element.test.ts +1 -1
- package/layers/core/app/components/ElementTw.test.ts +1 -1
- package/layers/core/app/components/ErrorBoundary.vue +5 -5
- package/layers/core/app/composables/useElementGrid.test.ts +1 -1
- package/layers/core/app/composables/useElementInteraction.test.ts +1 -1
- package/layers/core/app/composables/useElementLayout.test.ts +1 -1
- package/layers/core/app/composables/useElementSizing.test.ts +1 -1
- package/layers/core/app/composables/useElementSurface.test.ts +1 -1
- package/layers/core/app/composables/useLayoutAttrs.test.ts +1 -1
- package/layers/core/app/error.vue +1 -1
- package/layers/core/app/pages/[...slug].vue +2 -2
- package/layers/core/app/utils/browserInfo.test.ts +1 -1
- package/layers/core/app/utils/featureClasses.test.ts +1 -1
- package/layers/core/app/utils/scrollGuardClamp.test.ts +1 -1
- package/layers/core/app/utils/styleToTailwindClasses.test.ts +1 -1
- package/layers/data/forms/app/utils/contact-schema.test.ts +1 -1
- package/layers/data/forms/app/utils/fieldProps.test.ts +1 -1
- package/layers/data/mailer/shared/contact.ts +23 -0
- package/layers/data/metadata/providers/comicvine/server/utils/metadata-comicvine/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/client.test.ts +1 -1
- package/layers/data/metadata/providers/google-books/server/utils/metadata-google-books/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/client.test.ts +1 -1
- package/layers/data/metadata/providers/openlibrary/server/utils/metadata-openlibrary/normalise.test.ts +1 -1
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/client.test.ts +1 -1
- package/layers/data/metadata/providers/themoviedb/server/utils/metadata-tmdb/normalise.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/cache.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/provider-registry.test.ts +1 -1
- package/layers/data/metadata/server/utils/metadata/search.test.ts +1 -1
- package/layers/data/metadata/shared/types/index.ts +2 -0
- package/layers/data/metadata/shared/types/metadata.ts +59 -0
- package/layers/data/metadata/shared/types/providers.ts +36 -0
- package/layers/delivery/feeds/app/assets/css/feeds.css +23 -11
- package/layers/delivery/feeds/app/components/Feeds/Index.vue +10 -10
- package/layers/delivery/feeds/app/components/Feeds/RouteCard.vue +1 -1
- package/layers/delivery/feeds/public/feed/style.css +16 -16
- package/layers/delivery/feeds/server/utils/content-adapter.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/feed-author.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/feed-config.test.ts +1 -1
- package/layers/delivery/feeds/server/utils/formats.test.ts +1 -1
- package/layers/delivery/scripts/app/components/BaselineStatus.vue +3 -1
- package/layers/delivery/seo/app/utils/seoConfig.test.ts +1 -1
- package/layers/design-system/theming/app/assets/css/theme.css +0 -1
- package/layers/design-system/theming/app/components/ThemePicker/AccentButton.vue +2 -2
- package/layers/design-system/theming/app/components/ThemePicker/Menu.vue +3 -3
- package/layers/design-system/theming/app/composables/useAccentColor.ts +4 -1
- package/layers/design-system/theming/app/plugins/theme.client.ts +15 -13
- package/layers/design-system/theming/app/utils/themeAdapter.ts +1 -1
- package/layers/design-system/theming/nuxt.config.ts +1 -1
- package/layers/design-system/theming/server/utils/accent-css.test.ts +1 -1
- package/layers/design-system/theming/server/utils/fouc-config.test.ts +1 -1
- package/layers/design-system/typography/app/components/Typography/TextStroke.vue +1 -1
- package/layers/design-system/visual/app/assets/css/visual.css +0 -1
- package/layers/design-system/visual/app/components/Accent/Scene.vue +2 -2
- package/layers/design-system/visual/app/components/Tint/Overlay.vue +1 -1
- package/layers/design-system/visual/app/utils/colorTokens.test.ts +1 -1
- package/layers/design-system/visual/app/utils/gradientStyle.test.ts +1 -1
- package/layers/design-system/visual/app/utils/responsiveSizes.test.ts +1 -1
- package/layers/motion/animations/app/components/Motion/Marquee.vue +1 -1
- package/layers/motion/animations/app/components/Motion/MarqueeText.vue +3 -3
- package/layers/motion/scroll/app/components/Motion/HorizontalScroll.vue +1 -1
- package/layers/motion/scroll/app/components/Motion/PinnedSection.vue +2 -2
- package/layers/motion/scroll/app/components/Motion/ScrollProgress.vue +2 -2
- package/layers/motion/scroll/app/components/Motion/ScrollStats.vue +6 -6
- package/layers/motion/transitions/app/assets/css/transitions.css +12 -12
- package/layers/render/canvas/app/composables/useRendererCapabilities.ts +2 -1
- package/layers/render/canvas/package.json +2 -1
- package/layers/render/shader/app/assets/css/shader.css +5 -5
- package/layers/render/shader/app/components/Mesh/Plane.vue +3 -1
- package/layers/render/shader/app/shaders/common/grain.ts +1 -1
- package/layers/render/shader/app/types/tsl.ts +1 -1
- package/layers/render/shader/app/utils/tsl/index.ts +2 -0
- package/layers/structure/grid/app/assets/css/grid.css +2 -0
- package/layers/structure/grid/app/composables/useGridTracks.test.ts +1 -1
- package/layers/structure/grid/app/types/tracks.test.ts +1 -1
- package/layers/structure/grid/app/utils/placement.test.ts +1 -1
- package/layers/structure/layout/app/components/Layout/Grid/Debug.vue +1 -1
- package/layers/structure/layout/app/components/Layout/Page/Header.vue +3 -3
- package/layers/structure/layout/app/components/Layout/Page/index.vue +16 -11
- package/layers/structure/layout/app/utils/gridPlacementStyle.test.ts +1 -1
- package/layers/structure/navigation/app/components/Mast/Nav.vue +1 -1
- package/layers/structure/navigation/app/components/Mast/NavModal.vue +2 -2
- package/layers/structure/navigation/app/utils/site.test.ts +1 -1
- package/layers/structure/routing/app/utils/resolveRoute.test.ts +1 -1
- package/package.json +22 -32
|
@@ -1146,7 +1146,7 @@ Column count is now emergent (native `auto-fill`), so there's nothing left to tr
|
|
|
1146
1146
|
|
|
1147
1147
|
<template>
|
|
1148
1148
|
<Teleport to="body">
|
|
1149
|
-
<div v-if="visible" :style class="layout-grid-debug
|
|
1149
|
+
<div v-if="visible" :style class="layout-grid-debug fixed inset-0 z-9999" aria-hidden="true" />
|
|
1150
1150
|
</Teleport>
|
|
1151
1151
|
</template>
|
|
1152
1152
|
```
|
|
@@ -1208,7 +1208,7 @@ The old page documented the 6/12/18 preset system in detail; that entire API is
|
|
|
1208
1208
|
<div class="flex items-center gap-4">
|
|
1209
1209
|
<UButton to="/" variant="ghost" icon="i-lucide-arrow-left" />
|
|
1210
1210
|
<div>
|
|
1211
|
-
<h1 class="text-3xl font-bold
|
|
1211
|
+
<h1 class="text-highlighted text-3xl font-bold">Layout Layer</h1>
|
|
1212
1212
|
<p class="text-muted">Fluid grid, sections, and page components</p>
|
|
1213
1213
|
</div>
|
|
1214
1214
|
<div class="ml-auto">
|
|
@@ -1232,14 +1232,14 @@ The old page documented the 6/12/18 preset system in detail; that entire API is
|
|
|
1232
1232
|
:span2="cell.span2"
|
|
1233
1233
|
>
|
|
1234
1234
|
<h3 class="font-mono text-sm">Cell {{ cell.id }}</h3>
|
|
1235
|
-
<p class="text-
|
|
1235
|
+
<p class="text-muted text-sm">variant: {{ cell.variant }}</p>
|
|
1236
1236
|
</LayoutCell>
|
|
1237
1237
|
</div>
|
|
1238
1238
|
</section>
|
|
1239
1239
|
|
|
1240
1240
|
<LayoutSection align="split" class="mt-12">
|
|
1241
1241
|
<div class="flex items-center justify-center">
|
|
1242
|
-
<div class="
|
|
1242
|
+
<div class="space-y-2 text-center">
|
|
1243
1243
|
<h2 class="text-2xl font-bold">LayoutSection align="split"</h2>
|
|
1244
1244
|
<p class="text-muted">
|
|
1245
1245
|
100svh block, optical 40/60 padding split derived from --lines/--fields.
|
|
@@ -1249,7 +1249,7 @@ The old page documented the 6/12/18 preset system in detail; that entire API is
|
|
|
1249
1249
|
</LayoutSection>
|
|
1250
1250
|
|
|
1251
1251
|
<LayoutSection align="center">
|
|
1252
|
-
<div class="
|
|
1252
|
+
<div class="space-y-2 text-center">
|
|
1253
1253
|
<h2 class="text-2xl font-bold">LayoutSection align="center"</h2>
|
|
1254
1254
|
<p class="text-muted">
|
|
1255
1255
|
place-content: center — true horizontal+vertical centering, no fighting align-items:
|
|
@@ -1268,7 +1268,7 @@ The old page documented the 6/12/18 preset system in detail; that entire API is
|
|
|
1268
1268
|
|
|
1269
1269
|
<section class="space-y-8">
|
|
1270
1270
|
<div>
|
|
1271
|
-
<h2 class="text-2xl font-bold
|
|
1271
|
+
<h2 class="mb-2 text-2xl font-bold">Z-Index System</h2>
|
|
1272
1272
|
<p class="text-muted">
|
|
1273
1273
|
Unchanged from the old system — read via
|
|
1274
1274
|
<code class="font-mono text-sm">useGridConfig().useZIndex(layer)</code>
|
|
@@ -1276,13 +1276,13 @@ The old page documented the 6/12/18 preset system in detail; that entire API is
|
|
|
1276
1276
|
</div>
|
|
1277
1277
|
<UCard>
|
|
1278
1278
|
<pre
|
|
1279
|
-
class="bg-muted text-highlighted
|
|
1279
|
+
class="bg-muted text-highlighted overflow-x-auto rounded-lg p-4 text-sm"
|
|
1280
1280
|
><code>const { useZIndex } = useGridConfig()
|
|
1281
1281
|
const zModal = useZIndex('modal') // → 400</code></pre>
|
|
1282
1282
|
</UCard>
|
|
1283
1283
|
</section>
|
|
1284
1284
|
|
|
1285
|
-
<div class="flex gap-4
|
|
1285
|
+
<div class="flex justify-center gap-4 pt-4">
|
|
1286
1286
|
<UButton to="/ui" variant="outline" icon="i-lucide-arrow-left">UI Layer Demo</UButton>
|
|
1287
1287
|
<UButton to="/" icon="i-lucide-home">Back to Home</UButton>
|
|
1288
1288
|
<UButton to="/core" variant="outline" trailing-icon="i-lucide-arrow-right">
|
|
@@ -52,7 +52,7 @@ regardless of layer), so `apps/playground/app/pages/baseline.vue` and `index.vue
|
|
|
52
52
|
playground. `app.config.ts`, `feed-catalog.ts` (collection resolution, missing-collection
|
|
53
53
|
warnings), `feed-head.ts` plugin (auto-discovery `<link rel="alternate">` tags), `feed-service.ts`,
|
|
54
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
|
|
55
|
+
Index.vue`, `Feeds/RouteCard.vue` — real, thorough, already well-tested
|
|
56
56
|
(`content-adapter.test.ts`, `feed-author.test.ts`, `feed-config.test.ts`, `formats.test.ts`),
|
|
57
57
|
consumed by `apps/playground/app/pages/feeds.vue`.
|
|
58
58
|
|
|
@@ -64,11 +64,11 @@ versa.
|
|
|
64
64
|
The artifact leaves the exact alias set open (§13). Resolved here:
|
|
65
65
|
|
|
66
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
|
|
67
|
+
half=6, third=4, quarter=3` — independent of the grid's live column
|
|
68
68
|
count, the same mental model as Bootstrap-style 12-col systems.
|
|
69
69
|
- Because `columns` can be less than 12 at smaller breakpoints (4 at `xs`,
|
|
70
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
|
|
71
|
+
value, current column count)` — computed in the component, not CSS
|
|
72
72
|
`calc()` (integer `grid-column: span N` can't come from a fractional
|
|
73
73
|
division). This keeps `half` always rendering as "half of whatever this
|
|
74
74
|
breakpoint's grid actually has," clamped so it never overflows a
|
|
@@ -85,7 +85,7 @@ New components, this layer, alongside `SwissGrid`/`SwissGridItem`:
|
|
|
85
85
|
For groups of items that wrap as a unit (tag lists, button rows,
|
|
86
86
|
metadata chips) — distinct from `SwissGrid`, which is column-track-based.
|
|
87
87
|
- **`Flow`** — vertical stack with automatic rhythm: renders `> * + *
|
|
88
|
-
{ margin-block-start: var(--fluid-space-<size>) }` scoped via a CSS
|
|
88
|
+
{ margin-block-start: var(--fluid-space-<size>) }` scoped via a CSS
|
|
89
89
|
class, `size` prop selecting the `core` fluid-space token. For prose-like
|
|
90
90
|
vertical sequences where every child needs the same gap, without each
|
|
91
91
|
child managing its own margin.
|
|
@@ -155,7 +155,7 @@ layers/structure/layout/app/components/
|
|
|
155
155
|
properties via `:style`.
|
|
156
156
|
- **`LayoutSection`** — see §4.
|
|
157
157
|
- **`LayoutCell`** (replaces `LayoutGridItem`) — `variant: 'block' |
|
|
158
|
-
'plate'` prop (border vs. filled, matching the prototype's `.block`/
|
|
158
|
+
'plate'` prop (border vs. filled, matching the prototype's `.block`/
|
|
159
159
|
`.plate`), `span2` / `span2Rows` / `span3Rows` boolean/enum props. No
|
|
160
160
|
`colStart`/`rowStart`/`preset`/`layer`/`bleed` — those go in the
|
|
161
161
|
migration guide as removed, with the nearest equivalent noted.
|
|
@@ -207,11 +207,11 @@ inspection.
|
|
|
207
207
|
resolved (narrow/medium viewport), squashing siblings. Fix:
|
|
208
208
|
`grid-auto-columns: minmax(measure-min, 1fr)` (belt-and-braces) plus
|
|
209
209
|
gating `.span-2` behind `@container viewport (min-width: 2 *
|
|
210
|
-
measure-min + gutter)` so it only activates once 2 columns have
|
|
210
|
+
measure-min + gutter)` so it only activates once 2 columns have
|
|
211
211
|
genuinely resolved.
|
|
212
212
|
3. **Hand-synced container-query thresholds.** `@container` conditions
|
|
213
213
|
can't reference custom properties — the `@container cell (max-width:
|
|
214
|
-
22rem)` / `@container viewport (min-width: 46rem)` thresholds must be
|
|
214
|
+
22rem)` / `@container viewport (min-width: 46rem)` thresholds must be
|
|
215
215
|
hand-kept in sync with `--measure-min`, commented at both ends.
|
|
216
216
|
|
|
217
217
|
## §8 Constraints to preserve
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<template>
|
|
21
21
|
<NuxtContentDetail collection="blog" :slug not-found-message="Blog post not found">
|
|
22
22
|
<template #headline="{ item }">
|
|
23
|
-
<div class="flex items-center gap-3 text-sm
|
|
23
|
+
<div class="text-muted flex items-center gap-3 text-sm">
|
|
24
24
|
<time v-if="asBlog(item).date">{{ formatDate(asBlog(item).date) }}</time>
|
|
25
25
|
<UBadge v-if="asBlog(item).badge" color="primary" variant="subtle">
|
|
26
26
|
{{ asBlog(item).badge }}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<NuxtContentDetail collection="gallery" :slug not-found-message="Gallery not found">
|
|
26
26
|
<template #headline="{ item }">
|
|
27
27
|
<div class="flex flex-wrap items-center gap-2">
|
|
28
|
-
<span v-if="asGallery(item).images?.length" class="text-
|
|
28
|
+
<span v-if="asGallery(item).images?.length" class="text-muted text-sm">
|
|
29
29
|
{{ asGallery(item).images!.length }} image{{
|
|
30
30
|
asGallery(item).images!.length === 1 ? '' : 's'
|
|
31
31
|
}}
|
|
@@ -49,30 +49,30 @@
|
|
|
49
49
|
<div
|
|
50
50
|
v-for="(img, idx) in asGallery(item).images"
|
|
51
51
|
:key="img.src"
|
|
52
|
-
class="overflow-hidden rounded-lg
|
|
52
|
+
class="group relative overflow-hidden rounded-lg"
|
|
53
53
|
>
|
|
54
|
-
<NuxtLink :to="`/gallery/${slug}/${idx}`" class="block
|
|
54
|
+
<NuxtLink :to="`/gallery/${slug}/${idx}`" class="relative block overflow-hidden">
|
|
55
55
|
<img
|
|
56
56
|
:src="img.src"
|
|
57
57
|
:alt="img.alt"
|
|
58
|
-
class="w-full
|
|
58
|
+
class="h-48 w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
59
59
|
/>
|
|
60
60
|
<div
|
|
61
|
-
class="absolute inset-0
|
|
61
|
+
class="bg-primary/60 absolute inset-0 flex items-center justify-center opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
|
62
62
|
>
|
|
63
|
-
<span class="
|
|
63
|
+
<span class="px-3 text-center text-sm font-semibold text-white">
|
|
64
64
|
{{ img.title || img.alt }}
|
|
65
65
|
</span>
|
|
66
66
|
</div>
|
|
67
67
|
</NuxtLink>
|
|
68
68
|
<button
|
|
69
|
-
class="absolute top-2 right-2 z-10
|
|
69
|
+
class="absolute top-2 right-2 z-10 cursor-pointer rounded-full bg-black/50 p-1.5 text-white opacity-0 transition-opacity duration-300 group-hover:opacity-100 hover:bg-black/70"
|
|
70
70
|
@click.stop="() => openLightbox(asGallery(item).images!, idx)"
|
|
71
71
|
>
|
|
72
72
|
<UIcon name="i-lucide-expand" class="size-4" />
|
|
73
73
|
</button>
|
|
74
74
|
<div v-if="img.caption" class="p-2">
|
|
75
|
-
<p class="text-
|
|
75
|
+
<p class="text-muted line-clamp-1 text-xs">
|
|
76
76
|
{{ img.caption }}
|
|
77
77
|
</p>
|
|
78
78
|
</div>
|
|
@@ -15,30 +15,30 @@
|
|
|
15
15
|
v-for="item in items"
|
|
16
16
|
:key="item.id"
|
|
17
17
|
:to="item.path"
|
|
18
|
-
class="group
|
|
18
|
+
class="group border-default block overflow-hidden rounded-lg border"
|
|
19
19
|
>
|
|
20
20
|
<div class="relative overflow-hidden">
|
|
21
21
|
<img
|
|
22
22
|
v-if="item.images?.[0]"
|
|
23
23
|
:src="item.images[0].src"
|
|
24
24
|
:alt="item.images[0].alt"
|
|
25
|
-
class="w-full
|
|
25
|
+
class="h-48 w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
26
26
|
/>
|
|
27
27
|
<div
|
|
28
|
-
class="absolute inset-0
|
|
28
|
+
class="bg-primary/60 absolute inset-0 flex items-center justify-center opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
|
29
29
|
>
|
|
30
|
-
<span class="text-
|
|
30
|
+
<span class="px-3 text-center font-semibold text-white">
|
|
31
31
|
{{ item.title }}
|
|
32
32
|
</span>
|
|
33
33
|
</div>
|
|
34
34
|
</div>
|
|
35
|
-
<div class="
|
|
36
|
-
<p class="font-medium
|
|
37
|
-
<p v-if="item.description" class="text-
|
|
35
|
+
<div class="space-y-1.5 p-3">
|
|
36
|
+
<p class="text-highlighted font-medium">{{ item.title }}</p>
|
|
37
|
+
<p v-if="item.description" class="text-muted line-clamp-2 text-sm">
|
|
38
38
|
{{ item.description }}
|
|
39
39
|
</p>
|
|
40
40
|
<div class="flex flex-wrap items-center gap-2">
|
|
41
|
-
<span v-if="item.images?.length" class="text-
|
|
41
|
+
<span v-if="item.images?.length" class="text-muted text-xs">
|
|
42
42
|
{{ item.images.length }} image{{ item.images.length === 1 ? '' : 's' }}
|
|
43
43
|
</span>
|
|
44
44
|
<UBadge v-for="tag in item.tags" :key="tag" color="neutral" variant="subtle" size="xs">
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
<!-- Ambient glow radiating from the image -->
|
|
44
44
|
<div
|
|
45
45
|
v-if="image.ambient"
|
|
46
|
-
class="absolute -inset-12 sm:-inset-20
|
|
46
|
+
class="pointer-events-none absolute -inset-12 sm:-inset-20"
|
|
47
47
|
aria-hidden="true"
|
|
48
48
|
>
|
|
49
49
|
<img
|
|
50
50
|
:src="image.src"
|
|
51
51
|
alt=""
|
|
52
|
-
class="
|
|
52
|
+
class="h-full w-full scale-x-200 object-cover opacity-40 bg-blend-luminosity mix-blend-darken blur-3xl saturate-300 dark:opacity-35 dark:mix-blend-lighten"
|
|
53
53
|
/>
|
|
54
54
|
<!-- class="w-full h-full object-cover rounded-3xl blur-3xl opacity-80 dark:opacity-30 saturate-200 scale-110 bg-blend-overlay dark:mix-blend-color" -->
|
|
55
55
|
</div>
|
|
@@ -63,13 +63,13 @@
|
|
|
63
63
|
/>
|
|
64
64
|
<figcaption
|
|
65
65
|
v-if="image.caption"
|
|
66
|
-
class="relative mt-3 text-center text-sm
|
|
66
|
+
class="text-muted relative mt-3 text-center text-sm italic"
|
|
67
67
|
>
|
|
68
68
|
{{ image.caption }}
|
|
69
69
|
</figcaption>
|
|
70
70
|
</figure>
|
|
71
71
|
|
|
72
|
-
<div class="flex items-center justify-between
|
|
72
|
+
<div class="mt-6 flex items-center justify-between">
|
|
73
73
|
<UButton
|
|
74
74
|
v-if="hasPrevious"
|
|
75
75
|
:to="`/gallery/${slug}/${index - 1}`"
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
</UButton>
|
|
81
81
|
<span v-else />
|
|
82
82
|
|
|
83
|
-
<span class="text-
|
|
83
|
+
<span class="text-muted text-sm"> {{ index + 1 }} / {{ totalImages }} </span>
|
|
84
84
|
|
|
85
85
|
<UButton
|
|
86
86
|
v-if="hasNext"
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
</div>
|
|
95
95
|
</UPageBody>
|
|
96
96
|
</div>
|
|
97
|
-
<div v-else class="text-muted text-center
|
|
97
|
+
<div v-else class="text-muted py-12 text-center">Image not found</div>
|
|
98
98
|
</template>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
:ui="{ content: 'bg-black/95 flex items-center justify-center' }"
|
|
51
51
|
>
|
|
52
52
|
<template #content>
|
|
53
|
-
<div class="relative
|
|
53
|
+
<div class="relative flex h-full w-full items-center justify-center p-4">
|
|
54
54
|
<!-- Close -->
|
|
55
55
|
<UButton
|
|
56
56
|
icon="i-lucide-x"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
:alt="currentImage.alt"
|
|
83
83
|
:width="currentImage.width"
|
|
84
84
|
:height="currentImage.height"
|
|
85
|
-
class="max-
|
|
85
|
+
class="max-h-full max-w-full object-contain"
|
|
86
86
|
/>
|
|
87
87
|
|
|
88
88
|
<!-- Next -->
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
/>
|
|
98
98
|
|
|
99
99
|
<!-- Counter -->
|
|
100
|
-
<div class="absolute bottom-4 left-1/2 -translate-x-1/2 text-
|
|
100
|
+
<div class="absolute bottom-4 left-1/2 -translate-x-1/2 text-sm text-white">
|
|
101
101
|
{{ currentIndex + 1 }} / {{ images.length }}
|
|
102
102
|
</div>
|
|
103
103
|
</div>
|
|
@@ -58,6 +58,6 @@
|
|
|
58
58
|
<NuxtContentToc v-bind="item.body?.toc?.links ? { links: item.body.toc.links } : {}" />
|
|
59
59
|
</template>
|
|
60
60
|
</UPage>
|
|
61
|
-
<div v-else class="text-muted text-center
|
|
61
|
+
<div v-else class="text-muted py-12 text-center">{{ notFoundMessage }}</div>
|
|
62
62
|
</div>
|
|
63
63
|
</template>
|
|
@@ -16,18 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
<template>
|
|
18
18
|
<div v-if="colors.length" class="space-y-6">
|
|
19
|
-
<h3 class="text-2xl font-semibold tracking-tight
|
|
19
|
+
<h3 class="text-highlighted text-2xl font-semibold tracking-tight">Palette</h3>
|
|
20
20
|
<LinksGroup class="palette-grid gap-3">
|
|
21
21
|
<div v-for="color in colors" :key="color.value">
|
|
22
22
|
<div
|
|
23
|
-
class="aspect-2/3
|
|
23
|
+
class="border-default/20 flex aspect-2/3 cursor-default flex-col justify-between rounded-lg border p-4 shadow-lg"
|
|
24
24
|
:style="{ backgroundColor: color.value, color: contrastColor(color.value) }"
|
|
25
25
|
>
|
|
26
26
|
<div>
|
|
27
|
-
<p class="text-sm font-medium
|
|
28
|
-
<p v-if="color.usage" class="text-xs
|
|
27
|
+
<p class="text-sm leading-tight font-medium">{{ color.name }}</p>
|
|
28
|
+
<p v-if="color.usage" class="mt-1 text-xs opacity-60">{{ color.usage }}</p>
|
|
29
29
|
</div>
|
|
30
|
-
<p class="text-xs
|
|
30
|
+
<p class="font-mono text-xs uppercase opacity-50">{{ color.value }}</p>
|
|
31
31
|
</div>
|
|
32
32
|
</div>
|
|
33
33
|
</LinksGroup>
|
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
10
|
<div v-if="typography.length" class="space-y-6">
|
|
11
|
-
<h3 class="text-2xl font-semibold tracking-tight
|
|
11
|
+
<h3 class="text-highlighted text-2xl font-semibold tracking-tight">Typography</h3>
|
|
12
12
|
<div class="mt-8 flex flex-col gap-24">
|
|
13
13
|
<div v-for="font in typography" :key="font.name" class="flex flex-col gap-6">
|
|
14
14
|
<div class="flex items-baseline justify-between gap-4">
|
|
15
|
-
<p class="font-name font-semibold
|
|
15
|
+
<p class="font-name text-highlighted truncate font-semibold tracking-tight">
|
|
16
16
|
{{ font.name }}
|
|
17
17
|
</p>
|
|
18
|
-
<p v-if="font.usage" class="text-
|
|
18
|
+
<p v-if="font.usage" class="text-muted shrink-0 text-sm">{{ font.usage }}</p>
|
|
19
19
|
</div>
|
|
20
20
|
<p class="font-sample text-muted tracking-wide">ABCDEFGHabcdefgh 0123456789</p>
|
|
21
21
|
<div class="flex items-center gap-4">
|
|
22
|
-
<span class="text-
|
|
22
|
+
<span class="text-muted font-mono text-xs tracking-widest uppercase opacity-50">
|
|
23
23
|
Weights
|
|
24
24
|
</span>
|
|
25
25
|
<span
|
|
26
26
|
v-for="weight in font.weights"
|
|
27
27
|
:key="weight"
|
|
28
|
-
class="text-
|
|
28
|
+
class="text-muted font-mono text-xs tracking-widest uppercase"
|
|
29
29
|
>
|
|
30
30
|
{{ weight }}
|
|
31
31
|
</span>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<template>
|
|
18
18
|
<figure class="my-6">
|
|
19
19
|
<img :src :alt :width :height class="w-full rounded-lg" />
|
|
20
|
-
<figcaption v-if="caption" class="mt-2 text-center text-sm
|
|
20
|
+
<figcaption v-if="caption" class="text-muted mt-2 text-center text-sm italic">
|
|
21
21
|
{{ caption }}
|
|
22
22
|
</figcaption>
|
|
23
23
|
</figure>
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
source/import order still decides the winner. */
|
|
18
18
|
@layer theme, base, components, utilities;
|
|
19
19
|
|
|
20
|
-
@import
|
|
21
|
-
@import
|
|
20
|
+
@import "tailwindcss";
|
|
21
|
+
@import "@nuxt/ui";
|
|
22
22
|
|
|
23
23
|
@config '#layers/core/tailwind.config.js';
|
|
24
24
|
|
|
@@ -28,18 +28,18 @@
|
|
|
28
28
|
@source '../../../../*/app/**/*.{vue,ts}';
|
|
29
29
|
@source '../../../../../apps/*/app/**/*.{vue,ts}';
|
|
30
30
|
|
|
31
|
-
@import
|
|
32
|
-
@import
|
|
33
|
-
@import
|
|
34
|
-
@import
|
|
35
|
-
@import
|
|
31
|
+
@import "#layers/core/app/assets/css/layout.css";
|
|
32
|
+
@import "#layers/core/app/assets/css/base.css";
|
|
33
|
+
@import "#layers/core/app/assets/css/tokens/breakpoints.css";
|
|
34
|
+
@import "#layers/core/app/assets/css/tokens/spacing-fluid.css";
|
|
35
|
+
@import "#layers/core/app/assets/css/tokens/container.css";
|
|
36
36
|
|
|
37
37
|
/* Relative path, not the '#layers/typography' alias — that alias only exists
|
|
38
38
|
when the typography layer is in a consumer's `extends`. This file is a CSS
|
|
39
39
|
import (needed so Tailwind treats it as part of this one build root, see
|
|
40
40
|
typography.css's header comment), and must resolve even for consumers that
|
|
41
41
|
only extend core, since it lives in the same single published package. */
|
|
42
|
-
@import
|
|
42
|
+
@import "../../../../design-system/typography/app/assets/css/typography.css";
|
|
43
43
|
|
|
44
44
|
/* Same relative-path requirement as typography.css above. tokens.css defines
|
|
45
45
|
an `@theme static` block (radius/shadow/duration) — per the CSS
|
|
@@ -51,4 +51,4 @@
|
|
|
51
51
|
every rounded-, shadow-, duration- utility fell back to Tailwind's stock
|
|
52
52
|
defaults instead of this file's values. Confirmed via compiled dev output:
|
|
53
53
|
the custom --shadow-sm value never appeared; Tailwind's built-in default did. */
|
|
54
|
-
@import
|
|
54
|
+
@import "../../../../design-system/theming/app/assets/css/tokens.css";
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
<ClientOnly>
|
|
31
31
|
<div class="space-y-8">
|
|
32
32
|
<div class="text-center">
|
|
33
|
-
<h1 class="text-4xl font-bold
|
|
33
|
+
<h1 class="mb-2 text-4xl font-bold">Core Layer Diagnostics</h1>
|
|
34
34
|
<p class="text-gray-500 dark:text-gray-400">Feature detection and system information</p>
|
|
35
35
|
</div>
|
|
36
36
|
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
</template>
|
|
125
125
|
<div class="space-y-2">
|
|
126
126
|
<div class="flex items-center gap-2">
|
|
127
|
-
<span class="font-medium
|
|
127
|
+
<span class="w-24 font-medium">Type:</span>
|
|
128
128
|
<span v-if="isMobile" class="text-primary">Mobile</span>
|
|
129
129
|
<span v-else-if="isTablet" class="text-primary">Tablet</span>
|
|
130
130
|
<span v-else-if="isDesktop" class="text-primary">Desktop</span>
|
|
@@ -138,16 +138,16 @@
|
|
|
138
138
|
</template>
|
|
139
139
|
<div class="space-y-2">
|
|
140
140
|
<div class="flex items-center gap-2">
|
|
141
|
-
<span class="font-medium
|
|
141
|
+
<span class="w-24 font-medium">Status:</span>
|
|
142
142
|
<span v-if="isOnline" class="text-green-500">Online</span>
|
|
143
143
|
<span v-else class="text-red-500">Offline</span>
|
|
144
144
|
</div>
|
|
145
145
|
<div class="flex items-center gap-2">
|
|
146
|
-
<span class="font-medium
|
|
146
|
+
<span class="w-24 font-medium">Type:</span>
|
|
147
147
|
<span>{{ effectiveType || 'unknown' }}</span>
|
|
148
148
|
</div>
|
|
149
149
|
<div class="flex items-center gap-2">
|
|
150
|
-
<span class="font-medium
|
|
150
|
+
<span class="w-24 font-medium">Quality:</span>
|
|
151
151
|
<span
|
|
152
152
|
:class="{
|
|
153
153
|
'text-green-500': connectionQuality === 'excellent',
|
|
@@ -160,13 +160,13 @@
|
|
|
160
160
|
</span>
|
|
161
161
|
</div>
|
|
162
162
|
<div class="flex items-center gap-2">
|
|
163
|
-
<span class="font-medium
|
|
163
|
+
<span class="w-24 font-medium">Speed:</span>
|
|
164
164
|
<span v-if="isFast" class="text-green-500">Fast</span>
|
|
165
165
|
<span v-else-if="isSlow" class="text-red-500">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
|
-
<span class="font-medium
|
|
169
|
+
<span class="w-24 font-medium">Data Saver:</span>
|
|
170
170
|
<span class="text-yellow-500">Enabled</span>
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
@@ -178,16 +178,16 @@
|
|
|
178
178
|
</template>
|
|
179
179
|
<div class="space-y-2">
|
|
180
180
|
<div class="flex items-center gap-2">
|
|
181
|
-
<span class="font-medium
|
|
182
|
-
<span class="
|
|
181
|
+
<span class="w-24 font-medium">Mode:</span>
|
|
182
|
+
<span class="text-primary uppercase">{{ mode }}</span>
|
|
183
183
|
</div>
|
|
184
184
|
<div class="flex items-center gap-2">
|
|
185
|
-
<span class="font-medium
|
|
185
|
+
<span class="w-24 font-medium">Environment:</span>
|
|
186
186
|
<span v-if="isClient" class="text-primary">Client</span>
|
|
187
187
|
<span v-else-if="isServer" class="text-primary">Server</span>
|
|
188
188
|
</div>
|
|
189
189
|
<div class="flex items-center gap-2">
|
|
190
|
-
<span class="font-medium
|
|
190
|
+
<span class="w-24 font-medium">Hydrated:</span>
|
|
191
191
|
<span v-if="isHydrated" class="text-green-500">Yes</span>
|
|
192
192
|
<span v-else class="text-yellow-500">No</span>
|
|
193
193
|
</div>
|
|
@@ -200,17 +200,17 @@
|
|
|
200
200
|
</template>
|
|
201
201
|
<div class="space-y-2">
|
|
202
202
|
<div class="flex items-center gap-2">
|
|
203
|
-
<span class="font-medium
|
|
203
|
+
<span class="w-24 font-medium">Installed:</span>
|
|
204
204
|
<span v-if="isInstalled" class="text-green-500">Yes</span>
|
|
205
205
|
<span v-else class="text-gray-500">No</span>
|
|
206
206
|
</div>
|
|
207
207
|
<div class="flex items-center gap-2">
|
|
208
|
-
<span class="font-medium
|
|
208
|
+
<span class="w-24 font-medium">Installable:</span>
|
|
209
209
|
<span v-if="canInstall" class="text-green-500">Yes</span>
|
|
210
210
|
<span v-else class="text-gray-500">No</span>
|
|
211
211
|
</div>
|
|
212
212
|
<div v-if="needRefresh" class="flex items-center gap-2">
|
|
213
|
-
<span class="font-medium
|
|
213
|
+
<span class="w-24 font-medium">Update:</span>
|
|
214
214
|
<span class="text-yellow-500">Available</span>
|
|
215
215
|
</div>
|
|
216
216
|
</div>
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
</div>
|
|
219
219
|
|
|
220
220
|
<template #fallback>
|
|
221
|
-
<div class="text-
|
|
221
|
+
<div class="text-muted py-16 text-center">Loading diagnostics…</div>
|
|
222
222
|
</template>
|
|
223
223
|
</ClientOnly>
|
|
224
224
|
</UContainer>
|
|
@@ -61,25 +61,25 @@
|
|
|
61
61
|
<template #error="{ error, clearError }">
|
|
62
62
|
<slot name="error" :error :clear-error>
|
|
63
63
|
<!-- Default error UI -->
|
|
64
|
-
<div class="
|
|
64
|
+
<div class="border-error bg-error/10 rounded-lg border p-4">
|
|
65
65
|
<div class="flex items-start gap-3">
|
|
66
66
|
<!-- Error icon -->
|
|
67
67
|
<span
|
|
68
|
-
class="iconify i-lucide:alert-circle mt-0.5 shrink-0
|
|
68
|
+
class="iconify i-lucide:alert-circle text-error mt-0.5 shrink-0"
|
|
69
69
|
aria-hidden="true"
|
|
70
70
|
/>
|
|
71
71
|
|
|
72
72
|
<!-- Error content -->
|
|
73
73
|
<div class="flex-1 space-y-2">
|
|
74
74
|
<!-- Error message -->
|
|
75
|
-
<p class="text-sm font-medium
|
|
75
|
+
<p class="text-error text-sm font-medium">
|
|
76
76
|
{{ message }}
|
|
77
77
|
</p>
|
|
78
78
|
|
|
79
79
|
<!-- Error details (dev only) -->
|
|
80
80
|
<details v-if="showDetails && import.meta.dev" class="text-xs">
|
|
81
|
-
<summary class="cursor-pointer
|
|
82
|
-
<pre class="mt-2 overflow-x-auto rounded
|
|
81
|
+
<summary class="text-muted cursor-pointer">Show error details</summary>
|
|
82
|
+
<pre class="bg-elevated mt-2 overflow-x-auto rounded p-2">{{ error }}</pre>
|
|
83
83
|
</details>
|
|
84
84
|
|
|
85
85
|
<!-- Retry button -->
|