srcdev-nuxt-components 9.0.5 → 9.0.7

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.
@@ -4,6 +4,17 @@
4
4
 
5
5
  `EyebrowText` renders a short uppercase label — typically used above a heading to provide context or categorisation. It outputs a single string with configurable tag, size, and colour via CSS custom properties.
6
6
 
7
+ ## Before Adding to a Page
8
+
9
+ Always ask the user for the following before placing the component:
10
+
11
+ 1. **`textContent`** — what is the label text? (passed as-is — do not pre-uppercase)
12
+ 2. **`fontSize`** — which size? (`large` | `medium` | `small`) — default is `medium`
13
+ 3. **`tag`** — does it need to be inline? If yes, use `span`. Otherwise `p` or `div` (default).
14
+ 4. **`styleClassPassthrough`** — any extra classes to add? (layout, spacing, custom styling hooks)
15
+
16
+ Do not assume placeholder text or default content.
17
+
7
18
  ## Props
8
19
 
9
20
  | Prop | Type | Default | Required |
@@ -59,6 +70,7 @@ Define these CSS custom properties in your consuming app to control sizes.
59
70
  ## Styling
60
71
 
61
72
  Key CSS custom properties:
73
+
62
74
  - `--colour-text-eyebrow` — text colour (defaults to an accent/muted tone)
63
75
 
64
76
  Text is always `text-transform: uppercase` — do not pass pre-uppercased strings, as this makes content harder to edit and search.
@@ -4,6 +4,18 @@
4
4
 
5
5
  `HeroText` renders a styled heading with support for mixed text styling (normal/accent segments), configurable font size, layout axis, and an optional icon. It uses Playfair Display font with italic variation for accent segments.
6
6
 
7
+ ## Before Adding to a Page
8
+
9
+ Always ask the user for the following before placing the component:
10
+
11
+ 1. **`tag`** — what heading level? (`h1` | `h2` | `h3` | `h4` | `h5` | `h6`)
12
+ 2. **Text segments** — for each segment, what is the text and should it be `normal` (default) or `accent` (italic, `--colour-text-accent` colour)?
13
+ 3. **`axis`** — should segments sit inline (`horizontal`, default) or stack in a column (`vertical`)?
14
+ 4. **`fontSize`** — which size? (`display` | `title` | `heading` | `subheading` | `label`) — default is `title`
15
+ 5. **`styleClassPassthrough`** — any extra classes to add? (layout, spacing, custom styling hooks)
16
+
17
+ Do not assume placeholder text or default content.
18
+
7
19
  ## Props
8
20
 
9
21
  | Prop | Type | Default | Required |
@@ -87,6 +99,7 @@ Define these CSS custom properties in your consuming app to control sizes.
87
99
  Override via `styleClassPassthrough` or a parent HOC `<style>` block targeting `.hero-text`.
88
100
 
89
101
  Key CSS custom properties:
102
+
90
103
  - `--colour-text-accent` — colour applied to `.accent` spans and the icon
91
104
  - `--hero-text-{scale}` — font size per scale value
92
105
 
@@ -0,0 +1,204 @@
1
+ # LayoutRow Component
2
+
3
+ ## Overview
4
+
5
+ `LayoutRow` is a CSS grid-based layout wrapper that controls how wide its content sits within the page. It uses a named-column grid system (full → popout → content → inset-content) so content can be precisely placed at different widths without custom CSS. It is the primary layout primitive for page sections.
6
+
7
+ ---
8
+
9
+ ## How to use this skill
10
+
11
+ When a developer asks to add a `LayoutRow`, follow the interactive flow below. Do not skip to writing code — work through the questions first to ensure the right variant is chosen. Developers unfamiliar with this system will not know what the options mean without guidance.
12
+
13
+ ---
14
+
15
+ ## Step 1 — Read the current context
16
+
17
+ Before asking anything, read the file the developer is working in and any parent components or pages to determine:
18
+
19
+ 1. **Is this LayoutRow inside another LayoutRow?**
20
+ - If yes, note the parent's `variant`. The inner grid resets relative to the parent's inner width, not the page. Warn the developer (see side effects below).
21
+ - If no, this is page-level — the grid spans the full viewport.
22
+
23
+ 2. **What is the effective current max width?**
24
+ Report this before asking any questions. Examples:
25
+ - "This row will sit at **page level** — the grid spans the full viewport width."
26
+ - "This row is nested inside a `LayoutRow variant="content"` — its maximum available width is **1064px**, not the full viewport."
27
+ - "This row is nested inside `variant="inset-content"` — maximum available width is **840px**."
28
+
29
+ 3. **What content is already nearby?** Note any sibling LayoutRows, headings, or components to give context for alignment.
30
+
31
+ ---
32
+
33
+ ## Step 2 — Ask what the row will contain
34
+
35
+ Ask the developer what is going in this row. Do not assume. Examples to listen for:
36
+
37
+ | Content type | Suggested variant |
38
+ |---|---|
39
+ | Hero, banner, full-bleed image or video | `full` or `full-content` |
40
+ | Coloured background band containing constrained content | `full` wrapping inner `content` |
41
+ | Card grid, media grid, feature row | `popout` |
42
+ | Standard page section (text + components) | `content` |
43
+ | Long-form article, blog post, form | `inset-content` |
44
+ | Sidebar or aside | `inset-content` |
45
+
46
+ Give a suggestion based on their answer, but confirm before proceeding.
47
+
48
+ ---
49
+
50
+ ## Step 3 — Present the width and margin consequences
51
+
52
+ Once you have a candidate variant (or 2–3 options), show the developer exactly what they will get at common viewport widths. Use this reference table:
53
+
54
+ ### Approximate rendered widths by variant
55
+
56
+ | Viewport | `inset-content` | `content` | `popout` | `full` |
57
+ |----------|----------------|-----------|----------|--------|
58
+ | 375px (mobile) | ~355px | ~355px | ~355px | 375px |
59
+ | 768px (tablet) | ~748px | ~748px | ~748px | 768px |
60
+ | 1080px | **840px** | ~1060px | ~1060px | 1080px |
61
+ | 1280px | **840px** | **1064px** | ~1260px | 1280px |
62
+ | 1440px | **840px** | **1064px** | **1400px** | 1440px |
63
+ | 1920px | **840px** | **1064px** | **1400px** | 1920px |
64
+
65
+ > Bold = the variant has reached its maximum and is now letterboxed. Below that threshold it fills the available width minus the minimum gutter (default `1rem` = 10px each side).
66
+
67
+ ### Approximate margin (space each side at wider viewports)
68
+
69
+ | Variant | @ 1080px | @ 1280px | @ 1440px | @ 1920px |
70
+ |---------|---------|---------|---------|---------|
71
+ | `inset-content` | ~120px | ~220px | ~300px | ~540px |
72
+ | `content` | ~10px | ~108px | ~188px | ~428px |
73
+ | `popout` | ~10px | ~10px | ~20px | ~260px |
74
+ | `full` | 0 | 0 | 0 | 0 |
75
+
76
+ Phrase this conversationally. For example:
77
+ > "With `content`, your section will max out at **1064px** wide. On a 1440px screen that leaves about **188px of margin on each side**. On a 1280px screen it's tighter — around **108px** each side. Does that sound right for what you're building?"
78
+
79
+ If they want more breathing room → suggest `inset-content`.
80
+ If they want the content to feel wider → suggest `popout`.
81
+
82
+ ---
83
+
84
+ ## Step 4 — Flag side effects for the chosen variant
85
+
86
+ Before writing code, flag any relevant consequences:
87
+
88
+ **`full` or `full-width`** — Content is completely edge-to-edge with no gutter at any viewport width. If text is placed directly inside without a nested layout wrapper it will touch screen edges on mobile. Suggest `full-content` or a nested `content` LayoutRow for the text.
89
+
90
+ **`full-content`** — Adds `--minimum-content-padding` (default `1rem` = 10px) as inline padding. Still full-bleed visually at most viewport sizes. Good for coloured bands.
91
+
92
+ **`full-content-nopad`** — Truly zero padding. Only use if the child component manages its own edge spacing.
93
+
94
+ **`popout`** — At viewports below ~1400px the popout track shrinks. Between 1280–1440px the margin is very small (~10–20px each side). If the design needs consistent breathing room at 1280px, `content` may be a better choice.
95
+
96
+ **`inset-content` or `content` nested inside a `full` LayoutRow** — This is a common and valid pattern: `full` gives edge-to-edge background, the inner row constrains the text/content. Confirm this is intentional if you see it.
97
+
98
+ **Nested LayoutRow (any variant)** — The inner grid takes the parent's `.layout-row-inner` width as 100%. The `full` variant of the inner LayoutRow will only be as wide as the parent's inner column, not the viewport. Warn the developer if this is surprising.
99
+
100
+ **`-start` / `-end` variants** — These only set `grid-column-start` or `grid-column-end`, not both. Content will stretch to the opposite edge of the grid unless the other end is also constrained. Best for intentional asymmetric designs.
101
+
102
+ ---
103
+
104
+ ## Step 5 — Confirm the remaining props
105
+
106
+ Once the variant is agreed, ask about:
107
+
108
+ 1. **`tag`** — what HTML element? Default is `div`. Common choices:
109
+ - `section` — for a thematic page section (most common)
110
+ - `article` — for self-contained content
111
+ - `header` / `footer` — for page-level header/footer rows
112
+ - `main` — for the primary content area (only once per page)
113
+ - `nav` — for navigation rows
114
+
115
+ 2. **`id`** — needed if this section is a scroll target, skip-link destination, or anchor in navigation. Ask if unsure.
116
+
117
+ 3. **`isLandmark`** — default `false`. Only set `true` if the row is a navigable landmark that needs keyboard focus. Usually `tag="section"` is sufficient — `isLandmark` is rarely needed.
118
+
119
+ 4. **`styleClassPassthrough`** — any extra classes for spacing, background colour, etc.?
120
+
121
+ ---
122
+
123
+ ## Props reference
124
+
125
+ | Prop | Type | Default | Required |
126
+ |------|------|---------|----------|
127
+ | `variant` | see variant list | — | **yes** |
128
+ | `tag` | `"div" \| "section" \| "article" \| "aside" \| "header" \| "footer" \| "main" \| "nav" \| "ul" \| "ol"` | `"div"` | no |
129
+ | `id` | `string` | `null` | no |
130
+ | `isLandmark` | `boolean` | `false` | no |
131
+ | `styleClassPassthrough` | `string \| string[]` | `[]` | no |
132
+ | `dataTestid` | `string` | `"layout-row"` | no |
133
+
134
+ All valid `variant` values:
135
+ `full` · `full-start` · `full-end` · `popout` · `popout-start` · `popout-end` · `content` · `content-start` · `content-end` · `inset-content` · `inset-content-start` · `inset-content-end` · `full-width` · `full-content` · `full-content-nopad`
136
+
137
+ ---
138
+
139
+ ## Usage examples
140
+
141
+ ### Standard section
142
+
143
+ ```vue
144
+ <LayoutRow variant="content" tag="section">
145
+ <p>Sits within the 1064px content track with ~188px margin at 1440px.</p>
146
+ </LayoutRow>
147
+ ```
148
+
149
+ ### Full-bleed hero, text constrained inside
150
+
151
+ ```vue
152
+ <LayoutRow variant="full" tag="section">
153
+ <!-- Background is edge-to-edge -->
154
+ <LayoutRow variant="content">
155
+ <HeroText tag="h1" :textContent="[{ text: 'Welcome' }]" />
156
+ </LayoutRow>
157
+ </LayoutRow>
158
+ ```
159
+
160
+ ### Coloured band (full width + safe padding)
161
+
162
+ ```vue
163
+ <LayoutRow variant="full-content" tag="section" :styleClassPassthrough="['bg-brand']">
164
+ <p>Full-width background, content padded by --minimum-content-padding.</p>
165
+ </LayoutRow>
166
+ ```
167
+
168
+ ### Long-form article body
169
+
170
+ ```vue
171
+ <LayoutRow variant="inset-content" tag="article">
172
+ <p>Comfortable reading column at 840px max.</p>
173
+ </LayoutRow>
174
+ ```
175
+
176
+ ### Feature / card grid (popout)
177
+
178
+ ```vue
179
+ <LayoutRow variant="popout" tag="section">
180
+ <!-- Card grid, image gallery, etc. -->
181
+ </LayoutRow>
182
+ ```
183
+
184
+ ---
185
+
186
+ ## CSS custom properties
187
+
188
+ Override in consuming app to adjust all track sizes globally:
189
+
190
+ | Property | Default | Effect |
191
+ |----------|---------|--------|
192
+ | `--popout-max-width` | `1400px` | Maximum width of the popout track |
193
+ | `--content-max-width` | `1064px` | Maximum width of the content track |
194
+ | `--inset-content-max-width` | `840px` | Maximum width of the inset-content track |
195
+ | `--minimum-content-padding` | `1rem` (10px) | Minimum gutter at small viewports |
196
+
197
+ ---
198
+
199
+ ## Notes
200
+
201
+ - Auto-imported in Nuxt — no import needed.
202
+ - `.layout-row-inner` has `container-type: inline-size` — children can use CSS container queries.
203
+ - The `full`, `full-content`, and `full-width` variants all map to `grid-column: full` — the difference is only whether inline padding is applied.
204
+ - `isLandmark` adds `tabindex="0"` and `aria-label="Layout Row Landmark"`. Prefer a semantic `tag` over this prop where possible.
@@ -27,6 +27,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
27
27
  └── components/
28
28
  ├── eyebrow-text.md — EyebrowText props, usage patterns, styling
29
29
  ├── hero-text.md — HeroText props, usage patterns, styling
30
+ ├── layout-row.md — LayoutRow variant guide, width/margin decisions, usage patterns
30
31
  └── link-text.md — LinkText props, slots, usage patterns, styling
31
32
  ```
32
33
 
@@ -229,6 +229,18 @@ export default defineNuxtConfig({
229
229
 
230
230
  The consuming app's CSS loads after the layer's, so your token overrides win via the cascade.
231
231
 
232
+ ## rem sizing
233
+
234
+ `html` has `font-size: 62.5%` set in `app/assets/styles/setup/01.config/_head.css`, making `1rem = 10px`. Use this when writing any rem values in your theme or component styles:
235
+
236
+ | px | rem |
237
+ | ---- | ------ |
238
+ | 8px | 0.8rem |
239
+ | 12px | 1.2rem |
240
+ | 16px | 1.6rem |
241
+ | 24px | 2.4rem |
242
+ | 32px | 3.2rem |
243
+
232
244
  ## Notes
233
245
 
234
246
  - The `--slate-*` scale comes from the layer and does not need to be redefined — keep all neutral/background tokens pointing at `--slate-*`.
package/README.md CHANGED
@@ -17,9 +17,15 @@ npm install --save srcdev-nuxt-components
17
17
  ```ts
18
18
  defineNuxtConfig({
19
19
  extends: "srcdev-nuxt-components",
20
+ css: [
21
+ "srcdev-nuxt-components/app/assets/styles/main.css",
22
+ "./app/assets/styles/main.css",
23
+ ],
20
24
  });
21
25
  ```
22
26
 
27
+ > **Note**: The layer CSS is not automatically included when installed from `node_modules`. You must explicitly add it to the `css` array as shown above. The second entry (`./app/assets/styles/main.css`) is your app's own stylesheet for overrides — create it if it doesn't exist.
28
+
23
29
  ## Claude Code Skills
24
30
 
25
31
  This package ships Claude Code skills — reference docs for components and development tasks — in the `.claude/` directory.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.0.5",
4
+ "version": "9.0.7",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",