srcdev-nuxt-components 9.4.5 → 9.4.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.
- package/.claude/commands/migrate-component.md +74 -5
- package/.claude/component-ledger/audit.json +1 -1
- package/.claude/component-ledger/build.mjs +27 -0
- package/.claude/component-ledger/output.html +8 -3
- package/.claude/component-ledger/template.html +7 -2
- package/.claude/skills/components/breadcrumb.md +1 -0
- package/.claude/skills/components/column-flow-grid.md +93 -0
- package/.claude/skills/components/content-docs.md +2 -0
- package/.claude/skills/components/display-tooltip-defined.md +3 -0
- package/.claude/skills/components/display-tooltip.md +1 -0
- package/.claude/skills/components/entry-animation.md +88 -0
- package/.claude/skills/components/input-copy.md +2 -0
- package/.claude/skills/components/input-text-core.md +186 -0
- package/.claude/skills/components/marquee-scroller.md +130 -0
- package/.claude/skills/components/masonry-grid.md +153 -0
- package/.claude/skills/components/navigation-items.md +1 -0
- package/.claude/skills/components/pop-over.md +100 -0
- package/.claude/skills/components/responsive-header.md +3 -0
- package/.claude/skills/components/site-header.md +4 -0
- package/.claude/skills/components/site-navigation.md +1 -0
- package/.claude/skills/components/tab-navigation.md +1 -0
- package/.claude/skills/index.md +7 -1
- package/.vscode/srcdev-component-breadcrumb.code-snippets +13 -0
- package/.vscode/srcdev-component-column-flow-grid.code-snippets +39 -0
- package/.vscode/srcdev-component-content-docs.code-snippets +18 -0
- package/.vscode/srcdev-component-display-tooltip-defined.code-snippets +15 -0
- package/.vscode/srcdev-component-display-tooltip.code-snippets +11 -0
- package/.vscode/srcdev-component-entry-animation.code-snippets +29 -0
- package/.vscode/srcdev-component-input-text.code-snippets +107 -0
- package/.vscode/srcdev-component-marquee-scroller.code-snippets +93 -0
- package/.vscode/srcdev-component-masonry-grid.code-snippets +51 -0
- package/.vscode/srcdev-component-pop-over.code-snippets +44 -0
- package/.vscode/srcdev-component-responsive-header.code-snippets +12 -0
- package/.vscode/srcdev-component-site-header.code-snippets +17 -0
- package/.vscode/srcdev-component-site-navigation.code-snippets +30 -0
- package/.vscode/srcdev-component-slider-gallery.code-snippets +38 -0
- package/.vscode/srcdev-component-tab-navigation.code-snippets +30 -0
- package/app/components/01.atoms/animations/entry/EntryAnimation.vue +7 -1
- package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +47 -0
- package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +57 -0
- package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +94 -0
- package/app/components/01.atoms/animations/marquee-scroller/MarqueeScroller.vue +331 -0
- package/app/components/01.atoms/animations/marquee-scroller/stories/MarqueeScroller.stories.ts +151 -0
- package/app/components/01.atoms/animations/marquee-scroller/tests/MarqueeScroller.spec.ts +315 -0
- package/app/components/01.atoms/animations/marquee-scroller/tests/__snapshots__/MarqueeScroller.spec.ts.snap +28 -0
- package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +9 -10
- package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +8 -2
- package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +12 -13
- package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +4 -1
- package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +33 -0
- package/app/components/01.atoms/grids/column-flow-grid/ColumnFlowGrid.vue +55 -0
- package/app/components/01.atoms/grids/column-flow-grid/stories/ColumnFlowGrid.stories.ts +178 -0
- package/app/components/01.atoms/grids/column-flow-grid/tests/ColumnFlowGrid.spec.ts +75 -0
- package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +35 -0
- package/app/components/01.atoms/grids/masonry-grid/MasonryGrid.vue +178 -0
- package/app/components/01.atoms/grids/masonry-grid/stories/MasonryGrid.stories.ts +199 -0
- package/app/components/01.atoms/grids/masonry-grid/tests/MasonryGrid.spec.ts +158 -0
- package/app/components/01.atoms/navigation/breadcrumb/Breadcrumb.vue +4 -1
- package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +54 -0
- package/app/components/01.atoms/pop-over/PopOver.vue +201 -0
- package/app/components/01.atoms/pop-over/stories/PopOver.stories.ts +141 -0
- package/app/components/01.atoms/pop-over/tests/PopOver.spec.ts +195 -0
- package/app/components/01.atoms/pop-over/tests/__snapshots__/PopOver.spec.ts.snap +11 -0
- package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +8 -2
- package/app/components/02.molecules/display-tooltip-defined/DisplayTooltipDefined.vue +16 -3
- package/app/components/02.molecules/display-tooltip-defined/tests/__snapshots__/DisplayTooltipDefined.spec.ts.snap +1 -1
- package/app/components/02.molecules/input-copy/InputCopy.vue +14 -0
- package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +15 -0
- package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +41 -0
- package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +4 -1
- package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +4 -1
- package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +16 -4
- package/app/components/03.organisms/responsive-header/NavigationItems.vue +4 -1
- package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +16 -3
- package/app/components/03.organisms/site-header/SiteHeader.vue +16 -1
- package/app/components/03.organisms/site-header/tests/__snapshots__/SiteHeader.spec.ts.snap +1 -1
- package/app/components/05.forms/input-select/InputSelectCore.vue +1 -1
- package/app/components/05.forms/input-text/InputTextCore.vue +6 -0
- package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +49 -20
- package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +41 -22
- package/app/components/05.forms/input-text/stories/InputTextCore.stories.ts +48 -22
- package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +43 -17
- package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +56 -0
- package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +61 -0
- package/app/components/05.forms/input-text/tests/InputTextCore.spec.ts +60 -0
- package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +46 -0
- package/app/components/05.forms/input-text/variants/InputPasswordWithLabel.vue +7 -1
- package/app/components/05.forms/input-text/variants/InputTextAsNumberWithLabel.vue +8 -2
- package/app/components/05.forms/input-text/variants/InputTextWithLabel.vue +6 -0
- package/app/components/05.forms/input-textarea/stories/InputTextareaCore.stories.ts +20 -20
- package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +32 -26
- package/app/types/components/index.ts +1 -0
- package/app/types/components/marquee-scroller.d.ts +10 -0
- package/app/types/forms/types.forms.d.ts +1 -1
- package/package.json +1 -1
- package/app/components/marquee-scroller/MarqueeScroller.vue +0 -289
- package/app/components/masonry-grid/MasonryGrid.vue +0 -68
- package/app/components/masonry-grid-ordered/MasonryGridOrdered.vue +0 -163
- package/app/components/masonry-grid-ordered/MasonryGridOrderedGridExperiment.vue +0 -259
- package/app/components/masonry-grid-ordered/stories/MasonryGridOrdered.stories.ts +0 -354
- package/app/components/masonry-grid-sorted/MasonryGridSorted.vue +0 -120
- package/app/components/pop-over/PopOver.vue +0 -90
- package/app/layouts/default.vue +0 -308
- package/app/layouts/site-navigation-demo.vue +0 -188
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: MasonryGrid
|
|
3
|
+
description: MasonryGrid — real measured-height masonry layout (greedy shortest-column packing, animated resize), named dynamic slots, itemMinWidth/gap/fixedWidth/justify, CSS token API
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MasonryGrid
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`MasonryGrid` is a genuine masonry layout: each item is measured (its real rendered height) and
|
|
12
|
+
placed into whichever column is currently shortest — a greedy bin-pack, the same technique
|
|
13
|
+
Pinterest-style layouts use. This is different from (and better than) laying items out with CSS
|
|
14
|
+
`columns`, which just fills one column's accumulated height before starting the next and has no
|
|
15
|
+
awareness of "shortest column."
|
|
16
|
+
|
|
17
|
+
Because placement follows natural DOM order directly (item 1 gets measured and placed first, then
|
|
18
|
+
item 2, etc.), there's no reordering trick needed to keep visual and reading order in sync — DOM
|
|
19
|
+
order *is* the packing order, so a screen reader or `Tab` key always encounters items 1, 2, 3...
|
|
20
|
+
in the order they were authored, regardless of which column each one's height ends up landing it
|
|
21
|
+
in visually.
|
|
22
|
+
|
|
23
|
+
**History**: this component absorbed the implementation from `MasonryGridOrdered` (now retired —
|
|
24
|
+
see **Migration history** below), replacing a CSS-`columns`-based reorder trick this component
|
|
25
|
+
used previously (see `git log` / `ColumnFlowGrid`'s history for that era).
|
|
26
|
+
|
|
27
|
+
## When to use this vs. `ColumnFlowGrid`
|
|
28
|
+
|
|
29
|
+
- Use **`ColumnFlowGrid`** (`.claude/skills/components/column-flow-grid.md`) when you don't need
|
|
30
|
+
true masonry packing or animated reflow — a lighter CSS `columns`-only layout, no JS
|
|
31
|
+
measurement, no resize animation.
|
|
32
|
+
- Use **`MasonryGrid`** when you want genuine Pinterest-style packing with items animating into
|
|
33
|
+
new positions on resize.
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Default | Description |
|
|
38
|
+
|------|------|---------|-------------|
|
|
39
|
+
| `tag` | `"div" \| "section" \| "article" \| "main"` | `"div"` | HTML element rendered as the root. |
|
|
40
|
+
| `itemMinWidth` | `number` | `300` | Minimum tile width in pixels — also the fixed tile width when `fixedWidth` is set. |
|
|
41
|
+
| `gap` | `number` | `12` | Gap between tiles in pixels. |
|
|
42
|
+
| `fixedWidth` | `boolean` | `false` | Keep every tile at exactly `itemMinWidth` instead of stretching to fill each column. |
|
|
43
|
+
| `justify` | `"left" \| "center" \| "right"` | `"left"` | How the block of tiles aligns within the wrapper — only visible when `fixedWidth` is set (tiles otherwise stretch to fill the full width, so there's nothing to align). |
|
|
44
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
|
|
45
|
+
|
|
46
|
+
## Slot API
|
|
47
|
+
|
|
48
|
+
Any named slot is accepted — there are no declared slot names, and **no count/data prop to keep
|
|
49
|
+
in sync**. Give slots in whatever order you want them read/tabbed through:
|
|
50
|
+
|
|
51
|
+
```vue
|
|
52
|
+
<MasonryGrid>
|
|
53
|
+
<template #item-1>...</template>
|
|
54
|
+
<template #item-2>...</template>
|
|
55
|
+
<template #item-3>...</template>
|
|
56
|
+
</MasonryGrid>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Basic usage
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<MasonryGrid :item-min-width="280" :gap="16">
|
|
63
|
+
<template v-for="(photo, i) in photos" :key="photo.id" #[`item-${i}`]>
|
|
64
|
+
<img :src="photo.src" :alt="photo.alt" />
|
|
65
|
+
</template>
|
|
66
|
+
</MasonryGrid>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Fixed-width, centered
|
|
70
|
+
|
|
71
|
+
```vue
|
|
72
|
+
<MasonryGrid :fixed-width="true" justify="center" :item-min-width="240">
|
|
73
|
+
<template v-for="(card, i) in cards" :key="card.id" #[`item-${i}`]>
|
|
74
|
+
<Card v-bind="card" />
|
|
75
|
+
</template>
|
|
76
|
+
</MasonryGrid>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## CSS Token Customization
|
|
80
|
+
|
|
81
|
+
| Token | Falls back to | Controls |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `--masonry-grid-item-border-colour` | `var(--theme-border)` | Outline colour around each item |
|
|
84
|
+
| `--masonry-grid-item-padding` | `1.2rem` | Inner padding of each item |
|
|
85
|
+
| `--masonry-grid-transition-duration` | `0.3s` | How long an item takes to slide into its new position on resize |
|
|
86
|
+
|
|
87
|
+
Column width, gap, fixed-width mode, and alignment are controlled via props, not CSS custom
|
|
88
|
+
properties, since column count and item positions are computed in JS from measured pixel values.
|
|
89
|
+
See `CONSUMER-STYLING.md` in the component folder.
|
|
90
|
+
|
|
91
|
+
## Accessibility
|
|
92
|
+
|
|
93
|
+
- The resize/reflow animation (`--masonry-grid-transition-duration`) is wrapped in
|
|
94
|
+
`@media (prefers-reduced-motion: no-preference)` — a visitor with reduced motion enabled sees
|
|
95
|
+
items snap to their new position with no transition.
|
|
96
|
+
- DOM/tab order always matches slot authoring order (see Overview) — no additional ARIA is needed
|
|
97
|
+
to communicate item order.
|
|
98
|
+
|
|
99
|
+
## Notes
|
|
100
|
+
|
|
101
|
+
- **How positioning works**: on mount and on every measured resize, each item is read (`item.
|
|
102
|
+
offsetHeight`) in DOM order and placed at the top of whichever column currently has the least
|
|
103
|
+
accumulated height, via inline `--_position-top`/`--_position-left`/`--_element-width` custom
|
|
104
|
+
properties the component sets directly (not part of the public token API — these are internal
|
|
105
|
+
positioning state, not a styling surface). Column steps are computed in real pixels
|
|
106
|
+
(`itemWidth + gap`) rather than equal percentage slots of the container — a percentage slot only
|
|
107
|
+
matches the item's actual width when the item stretches to fill it (the default, non-`fixedWidth`
|
|
108
|
+
case); with `fixedWidth`, `justify`'s left/center/right offset is also computed here in JS
|
|
109
|
+
(`(wrapperWidth - totalContentWidth) / 2` for `center`, etc.), not via CSS `justify-content` —
|
|
110
|
+
that property has no effect on children once `position: absolute` takes them out of grid flow,
|
|
111
|
+
so it doesn't work here regardless of how it's set.
|
|
112
|
+
- **Single-column fallback**: below the width needed for a second `itemMinWidth` column plus gap,
|
|
113
|
+
items render in normal CSS Grid flow (no absolute positioning) at a single, always-full-width
|
|
114
|
+
column (`grid-template-columns: 1fr`, ignoring `itemMinWidth` entirely) — there's nothing to
|
|
115
|
+
pack with only one column, so it always just fills the container rather than applying
|
|
116
|
+
`itemMinWidth`'s floor. `itemMinWidth` starts governing column width only once there's an actual
|
|
117
|
+
multi-column choice to make (two columns up).
|
|
118
|
+
- **Column count is a JS estimate**: `Math.floor(measuredWidth / (itemMinWidth + gap))`. This
|
|
119
|
+
drives an underlying CSS Grid (`grid-template-columns`, with `768px`/`1024px`/`1280px` container
|
|
120
|
+
query breakpoints) as a no-JS-yet initial layout, which JS then overrides with absolute
|
|
121
|
+
positioning once it has real measurements — so there's no flash of unstyled/overlapping content
|
|
122
|
+
before the first `updateGrid()` run.
|
|
123
|
+
- **Images without explicit dimensions** will change height after they load, but nothing currently
|
|
124
|
+
re-triggers a re-pack when that happens (only container resize does) — a known limitation
|
|
125
|
+
inherited from the original implementation. Set explicit `width`/`height` on images inside slots
|
|
126
|
+
to avoid this, or file a follow-up if it becomes a real problem.
|
|
127
|
+
- **Migration history**: this component's algorithm was ported from `MasonryGridOrdered`
|
|
128
|
+
(`app/components/masonry-grid-ordered/MasonryGridOrdered.vue`), which is now retired along with
|
|
129
|
+
its `MasonryGridOrderedGridExperiment` sibling (an abandoned, more fragile alternative that
|
|
130
|
+
inferred CSS Grid's own auto-placement via `index % columnCount` rather than genuine shortest-
|
|
131
|
+
column packing — never used it). The port modernized typed props (dropped the unused
|
|
132
|
+
`mobilePreferredColCount` prop, and the CSS-string-with-validator `justify` prop became a real
|
|
133
|
+
union type), promoted CSS custom properties to a proper public token API, added
|
|
134
|
+
`prefers-reduced-motion` handling (missing before), and removed a redundant second
|
|
135
|
+
`useResizeObserver` call that duplicated the one `useElementSize` already sets up internally. It
|
|
136
|
+
also replaced `MasonryGrid`'s own previous CSS-`columns`-based reorder-trick implementation,
|
|
137
|
+
which is now `ColumnFlowGrid` (`.claude/skills/components/column-flow-grid.md`). No known
|
|
138
|
+
consumer app was using any of the old APIs/names.
|
|
139
|
+
- **Found after the port, via manual testing**: the original's `--_position-left` used equal
|
|
140
|
+
percentage slots (`minIndex * (100 / columnCount)%`) for every mode. That's fine when items
|
|
141
|
+
stretch to fill their slot, but with `fixedWidth` the item is narrower than its slot, so the
|
|
142
|
+
unused slot space showed up as a much bigger gap than the `gap` prop actually specified — it
|
|
143
|
+
visually looked like `justify-content: space-between`. Also, the CSS `justify-content` the port
|
|
144
|
+
initially added (see above) turned out to be entirely dead: it has no effect on children once
|
|
145
|
+
`position: absolute` removes them from grid flow, so `justify` never did anything either.
|
|
146
|
+
Fixed by computing both column steps and the `justify` offset in real pixels in JS (see **How
|
|
147
|
+
positioning works** above) instead of relying on CSS for either.
|
|
148
|
+
- **Found after that, testing narrow/mobile viewports**: the single-column CSS fallback template
|
|
149
|
+
was `minmax(itemMinWidth, 1fr)`, same as every other breakpoint — on a container narrower than
|
|
150
|
+
`itemMinWidth`, that floor fought the container instead of just filling it, producing a
|
|
151
|
+
non-full-width, misaligned single column. Fixed by making the single-column template a plain
|
|
152
|
+
`1fr` unconditionally (see **Single-column fallback** above) — `itemMinWidth` never had a
|
|
153
|
+
multi-column decision to inform in that case anyway.
|
|
@@ -17,6 +17,7 @@ active-route highlighting, hover indicator).
|
|
|
17
17
|
|------|------|---------|-------|
|
|
18
18
|
| `mainNavigationState` | `ResponsiveHeaderState` | `{ clonedNavLinks: {}, navListVisibility: {}, hasSecondNav: false }` | Shared geometry/visibility state, normally supplied by the parent `ResponsiveHeader` — not something a consumer constructs by hand outside of tests/stories. |
|
|
19
19
|
| `panelVariant` | `"modern" \| "classic"` | `"classic"` | Which panel component renders a dropdown's submenu: `ExpandingPanel` (`"modern"`) or `ExpandingPanelClassic` (`"classic"`, default). `"modern"` is known not to work correctly on WebKit. Normally set via `ResponsiveHeader`'s own `panelVariant` prop rather than directly. See CLAUDE.md pitfall #19. |
|
|
20
|
+
| `ariaLabel` | `string` | `"Overflow navigation menu"` | aria-label on the root `role="menu"` element — override for localisation. Normally set via `ResponsiveHeader`'s own `overflowMenuAriaLabel` prop rather than directly. |
|
|
20
21
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes applied to the root `.overflow-navigation-wrapper` element. |
|
|
21
22
|
|
|
22
23
|
---
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: PopOver
|
|
3
|
+
description: PopOver generic anchor-positioned disclosure panel with consumer-supplied trigger/content slots, placement prop, CSS token API
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PopOver
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`PopOver` renders a fully consumer-supplied trigger that opens an anchor-positioned popover panel
|
|
12
|
+
with fully consumer-supplied content, built on the native Popover API
|
|
13
|
+
(`popover`/`popovertarget`) and CSS anchor-positioning (`anchor-name`/`position-anchor`/
|
|
14
|
+
`anchor()`). Unlike [`DisplayTooltip`](display-tooltip.md) (a fixed icon trigger for inline help
|
|
15
|
+
text) or `ActionMenu` (menu semantics with arrow-key navigation), `PopOver` makes no assumption
|
|
16
|
+
about what the trigger or content look like, and always renders its own visible close button.
|
|
17
|
+
|
|
18
|
+
**Browser support caveat:** CSS anchor-positioning and the Popover API are both comparatively
|
|
19
|
+
recent — check current browser support before relying on this where broad support is a hard
|
|
20
|
+
requirement, same caution as `DisplayTooltip`/`DeepExpandingMenu`'s equivalent gap.
|
|
21
|
+
|
|
22
|
+
## Props
|
|
23
|
+
|
|
24
|
+
| Prop | Type | Default | Description |
|
|
25
|
+
|------|------|---------|-------------|
|
|
26
|
+
| `placement` | `"top" \| "right" \| "bottom" \| "left"` | `"right"` | Which side of the trigger the popover panel opens on. Each side has a `position-try-fallbacks` so the browser flips it automatically if it would overflow the viewport. |
|
|
27
|
+
| `triggerAriaLabel` | `string` | `""` | aria-label on the trigger button — set this when the `trigger` slot is icon-only. Unset (no attribute) by default, since the trigger slot usually carries its own visible/accessible content. |
|
|
28
|
+
| `popoverAriaLabel` | `string` | `""` | aria-label on the popover content region — set this when the `content` slot has no visible heading. |
|
|
29
|
+
| `closeButtonAriaLabel` | `string` | `"Close"` | aria-label on the close button — override for localisation. |
|
|
30
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
|
|
31
|
+
|
|
32
|
+
## Slots
|
|
33
|
+
|
|
34
|
+
| Slot | Description |
|
|
35
|
+
|------|-------------|
|
|
36
|
+
| `trigger` | Content rendered inside the trigger button. |
|
|
37
|
+
| `content` | Content rendered inside the popover panel, below the close button. |
|
|
38
|
+
|
|
39
|
+
## Basic usage
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<PopOver placement="bottom">
|
|
43
|
+
<template #trigger>
|
|
44
|
+
<span>Open popover</span>
|
|
45
|
+
</template>
|
|
46
|
+
<template #content>
|
|
47
|
+
<p>This is some popover content.</p>
|
|
48
|
+
</template>
|
|
49
|
+
</PopOver>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Icon-only trigger:
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<PopOver trigger-aria-label="Show filters" popover-aria-label="Filter options">
|
|
56
|
+
<template #trigger>
|
|
57
|
+
<Icon name="lucide:filter" aria-hidden="true" />
|
|
58
|
+
</template>
|
|
59
|
+
<template #content>
|
|
60
|
+
<p>Filter controls would go here.</p>
|
|
61
|
+
</template>
|
|
62
|
+
</PopOver>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Notes on content
|
|
66
|
+
|
|
67
|
+
The `content` slot's immediate children have their default UA top/bottom margins trimmed (via
|
|
68
|
+
`:first-child`/`:last-child`), so `--pop-over-content-padding`/`-content-padding-block-start` are
|
|
69
|
+
the only source of space above/below the slotted content — a plain `<p>` doesn't stack its own
|
|
70
|
+
`margin-block` on top of the panel's padding. Interior spacing between multiple slotted children
|
|
71
|
+
(e.g. two paragraphs) is untouched.
|
|
72
|
+
|
|
73
|
+
## Behaviour
|
|
74
|
+
|
|
75
|
+
- Opening/closing is handled natively by the Popover API: clicking the trigger toggles the panel,
|
|
76
|
+
clicking the close button or pressing Escape hides it, and focus returns to the trigger
|
|
77
|
+
automatically on close.
|
|
78
|
+
- On open, focus moves to the close button (`handleToggle`, driven by the popover's native
|
|
79
|
+
`toggle` event) so keyboard users land inside the panel immediately.
|
|
80
|
+
|
|
81
|
+
## CSS custom properties
|
|
82
|
+
|
|
83
|
+
See `CONSUMER-STYLING.md` for the full `--pop-over-*` token API (gap, trigger outline, panel
|
|
84
|
+
border/background/text/shadow/width, content padding, and close-button tokens).
|
|
85
|
+
|
|
86
|
+
## Notes
|
|
87
|
+
|
|
88
|
+
- Auto-imported in Nuxt — no manual import needed.
|
|
89
|
+
- 2026-09-13 migration: moved from an unplaced top-level folder (`app/components/pop-over/`) into
|
|
90
|
+
`01.atoms/pop-over/`; converted options-style `defineProps` to `interface Props` +
|
|
91
|
+
`withDefaults`; the slot named `popoverCotent` (typo) was renamed to `content`, and the required
|
|
92
|
+
`popovertarget` prop was replaced with an auto-generated id (`useId()`) so consumers no longer
|
|
93
|
+
need to wire up matching ids themselves; the `role="tooltip"` on the popover panel was removed
|
|
94
|
+
(it described a tooltip, not this component's actual arbitrary-content disclosure semantics);
|
|
95
|
+
added a real, visible close button (the original template referenced one with no styling or
|
|
96
|
+
accessible label — literal `x` text); added `placement` (`top`/`right`/`bottom`/`left`, all with
|
|
97
|
+
`position-try-fallbacks`) — the original only supported opening to the right, with several
|
|
98
|
+
`@position-try` blocks commented out and unused; promoted every hardcoded value to a public CSS
|
|
99
|
+
token; added tests, a Storybook story, this skill doc, and a VS Code snippet (all previously
|
|
100
|
+
missing).
|
|
@@ -107,6 +107,9 @@ buggy toggle-based version too.
|
|
|
107
107
|
| `collapseAtMainNavIntersection` | `boolean` | `false` | Like `collapseBreakpoint`, but the breakpoint is derived automatically from the main nav's own measured width rather than a fixed number. |
|
|
108
108
|
| `allowExpandOnGesture` | `boolean` | `true` | When `true`, hovering/focusing a dropdown summary opens it (in addition to click). When `false`, only click toggles it. |
|
|
109
109
|
| `panelVariant` | `"modern" \| "classic"` | `"classic"` | Forwarded to `NavigationItems` for its dropdown submenu panels: `ExpandingPanel` (`"modern"`) or `ExpandingPanelClassic` (`"classic"`, default). `"modern"` is known not to work correctly on WebKit. See CLAUDE.md pitfall #19. |
|
|
110
|
+
| `mainNavAriaLabel` | `string` | `"Main navigation"` | aria-label on the primary nav landmark — override for localisation. |
|
|
111
|
+
| `secondaryNavAriaLabel` | `string` | `"Secondary navigation"` | aria-label on the secondary (overflow) nav landmark — override for localisation. |
|
|
112
|
+
| `overflowMenuAriaLabel` | `string` | `"Overflow navigation menu"` | Forwarded to `NavigationItems`' `ariaLabel` — override for localisation. |
|
|
110
113
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes applied to the root `.navigation` element. |
|
|
111
114
|
|
|
112
115
|
## Slots
|
|
@@ -23,6 +23,10 @@ Branding (logo/wordmark) is entirely consumer-authored via the `#branding` slot
|
|
|
23
23
|
| `pageRowVariant` | `"full" \| "popout" \| "content" \| "inset-content"` | `"content"` | Forwarded to the root `PageRow`'s `variant` prop. |
|
|
24
24
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes on the root `PageRow` — targets `--site-header-*` tokens (see `CONSUMER-STYLING.md`). |
|
|
25
25
|
| `navStyleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes on the nested `ResponsiveHeader` — targets its own `--responsive-header-*`/`--overflow-nav-*` tokens. |
|
|
26
|
+
| `homeNavAriaLabel` | `string` | `"Home Navigation"` | aria-label on the home/branding nav landmark — override for localisation. |
|
|
27
|
+
| `mainNavAriaLabel` | `string` | `"Main navigation"` | Forwarded to `ResponsiveHeader`'s `mainNavAriaLabel` — override for localisation. |
|
|
28
|
+
| `secondaryNavAriaLabel` | `string` | `"Secondary navigation"` | Forwarded to `ResponsiveHeader`'s `secondaryNavAriaLabel` — override for localisation. |
|
|
29
|
+
| `overflowMenuAriaLabel` | `string` | `"Overflow navigation menu"` | Forwarded to `ResponsiveHeader`'s `overflowMenuAriaLabel` — override for localisation. |
|
|
26
30
|
|
|
27
31
|
---
|
|
28
32
|
|
|
@@ -16,6 +16,7 @@ Both the horizontal list and the panel include animated active/hover indicator d
|
|
|
16
16
|
|---|---|---|---|
|
|
17
17
|
| `navItemData` | `NavItemData` | — (required) | Navigation items — see type below |
|
|
18
18
|
| `navAlign` | `"left" \| "center" \| "right"` | `"left"` | Alignment of the horizontal nav list |
|
|
19
|
+
| `ariaLabel` | `string` | `"Site navigation"` | aria-label on the root `<nav>` landmark — override for localisation |
|
|
19
20
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root `<nav>` |
|
|
20
21
|
|
|
21
22
|
## NavItemData type
|
|
@@ -40,6 +40,7 @@ interface NavItemData {
|
|
|
40
40
|
| `nav-item-data` | `NavItemData` | required | Navigation link data — only `main` key is read |
|
|
41
41
|
| `nav-align` | `"left" \| "center" \| "right"` | `"left"` | Positions the tab list within the nav container |
|
|
42
42
|
| `anchor-scroll-offset` | `number \| (() => number)` | — | Pixel offset subtracted from scroll target; pass a getter so it is re-evaluated at click time |
|
|
43
|
+
| `aria-label` | `string` | `"Site navigation"` | aria-label on the root `<nav>` landmark — override for localisation |
|
|
43
44
|
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root `<nav>` element |
|
|
44
45
|
|
|
45
46
|
---
|
package/.claude/skills/index.md
CHANGED
|
@@ -89,6 +89,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
|
|
|
89
89
|
├── grid-stack.md — GridStack: CSS Grid z-axis stacking, slot API, z-order rules, sizing, video+overlay and image+text patterns
|
|
90
90
|
├── scroll-reveal-frame.md — ScrollRevealFrame: generic parallax clipping frame, slot API, image grid pattern, CSS tokens, browser support
|
|
91
91
|
├── scroll-reveal-image.md — ScrollRevealImage: single-image parallax reveal, focalX, imgWidth/imgHeight, responsive frame height
|
|
92
|
+
├── marquee-scroller.md — MarqueeScroller: infinite logo/badge scroller, per-item dynamic slots (marqueeData id), hover/focus/keyboard pause, reduced-motion, CSS tokens
|
|
92
93
|
├── site-navigation.md — SiteNavigation: responsive nav with auto-collapse, burger menu, decorator indicators, CSS token API
|
|
93
94
|
├── tab-navigation.md — TabNavigation: horizontal tab nav with CSS anchor-positioning indicators, anchor scroll, burger collapse, full CSS token API
|
|
94
95
|
├── social-icons-list.md — SocialIconsList: data-driven social icon links, ISocialIcon type, logos: icon names, CSS tokens
|
|
@@ -115,7 +116,12 @@ Each skill is a single markdown file named `<area>-<task>.md`.
|
|
|
115
116
|
├── deep-expanding-menu.md — DeepExpandingMenu: anchor-positioned popover nav panels, browser support caveat, CSS token API
|
|
116
117
|
├── deep-expanding-menu-classic.md — DeepExpandingMenuClassic: <details>-based fallback nav, click-outside close, CSS token API
|
|
117
118
|
├── display-tooltip.md — DisplayTooltip: anchor-positioned popover trigger, browser support caveat, CSS token API
|
|
118
|
-
|
|
119
|
+
├── display-tooltip-defined.md — DisplayTooltipDefined: structured title/body/action tooltip content with close button, composes DisplayTooltip
|
|
120
|
+
├── pop-over.md — PopOver: generic anchor-positioned disclosure panel, consumer-supplied trigger/content slots, placement prop, CSS token API
|
|
121
|
+
├── input-text-core.md — InputTextCore: native text/date/number input primitive, min/max pass-through (date-picker range), CSS token API; Variants section covers InputTextWithLabel/InputPasswordWithLabel/InputTextAsNumberWithLabel
|
|
122
|
+
├── entry-animation.md — EntryAnimation: scroll-driven entry animation wrapper (slide-in/zoom-reveal/exit-blur utility classes), skipAnimation for above-the-fold loop items, reduced-motion handled at the CSS layer
|
|
123
|
+
├── column-flow-grid.md — ColumnFlowGrid (renamed from MasonryGrid): CSS multi-column text-flow layout, named dynamic slots (no count/data prop), itemMinWidth/gap/unit sizing, CSS token API; not a true masonry, see "which one do I want?"
|
|
124
|
+
└── masonry-grid.md — MasonryGrid: real measured-height masonry (greedy shortest-column packing, animated resize) absorbed from the now-retired MasonryGridOrdered; named dynamic slots, fixedWidth/justify, CSS token API
|
|
119
125
|
```
|
|
120
126
|
|
|
121
127
|
## Skill file template
|
|
@@ -10,5 +10,18 @@
|
|
|
10
10
|
" ]\"",
|
|
11
11
|
"/>"
|
|
12
12
|
]
|
|
13
|
+
},
|
|
14
|
+
"SRCDEV Breadcrumb Localised": {
|
|
15
|
+
"description": "Breadcrumb with a localised aria-label",
|
|
16
|
+
"scope": "vue,html",
|
|
17
|
+
"body": [
|
|
18
|
+
"<Breadcrumb",
|
|
19
|
+
" :items=\"[",
|
|
20
|
+
" { label: '$1Services', to: '$2/services' },",
|
|
21
|
+
" { label: '$3${TM_FILENAME_BASE}' },",
|
|
22
|
+
" ]\"",
|
|
23
|
+
" aria-label=\"${4:Breadcrumb}\"",
|
|
24
|
+
"/>"
|
|
25
|
+
]
|
|
13
26
|
}
|
|
14
27
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"SRCDEV ColumnFlowGrid Basic": {
|
|
3
|
+
"description": "Basic ColumnFlowGrid with a few named item slots",
|
|
4
|
+
"scope": "vue,html",
|
|
5
|
+
"body": [
|
|
6
|
+
"<ColumnFlowGrid :item-min-width=\"$1300\" :gap=\"$21.2\">",
|
|
7
|
+
" <template #item-1>",
|
|
8
|
+
" $3",
|
|
9
|
+
" </template>",
|
|
10
|
+
" <template #item-2>",
|
|
11
|
+
" $4",
|
|
12
|
+
" </template>",
|
|
13
|
+
"</ColumnFlowGrid>"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"SRCDEV ColumnFlowGrid Looped": {
|
|
17
|
+
"description": "ColumnFlowGrid rendering a v-for list via dynamic slot names (no count prop needed)",
|
|
18
|
+
"scope": "vue,html",
|
|
19
|
+
"body": [
|
|
20
|
+
"<ColumnFlowGrid :item-min-width=\"$1280\" :gap=\"$21.6\">",
|
|
21
|
+
" <template v-for=\"($3item, $4index) in $5items\" :key=\"$3item.id\" #[`item-${$4index}`]>",
|
|
22
|
+
" $6",
|
|
23
|
+
" </template>",
|
|
24
|
+
"</ColumnFlowGrid>"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"SRCDEV ColumnFlowGrid CSS Override": {
|
|
28
|
+
"description": "CSS override scaffold for ColumnFlowGrid tokens",
|
|
29
|
+
"scope": "css",
|
|
30
|
+
"body": [
|
|
31
|
+
".$1my-page {",
|
|
32
|
+
" .column-flow-grid-wrapper {",
|
|
33
|
+
" --column-flow-grid-item-border-colour: $2;",
|
|
34
|
+
" --column-flow-grid-item-padding: $3;",
|
|
35
|
+
" }",
|
|
36
|
+
"}"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -33,6 +33,24 @@
|
|
|
33
33
|
"</ContentDocs>"
|
|
34
34
|
]
|
|
35
35
|
},
|
|
36
|
+
"SRCDEV ContentDocs Localised Nav Labels": {
|
|
37
|
+
"description": "ContentDocs with localised aria-labels on the docsNav/docsPageNav <nav> landmarks",
|
|
38
|
+
"scope": "vue,html",
|
|
39
|
+
"body": [
|
|
40
|
+
"<ContentDocs",
|
|
41
|
+
" v-model:active-nav-item=\"$1activeNavItem\"",
|
|
42
|
+
" v-model:active-page-nav-item=\"$2activePageNavItem\"",
|
|
43
|
+
" :docs-nav-items=\"$3docsNavItems\"",
|
|
44
|
+
" :docs-page-nav-items=\"$4docsPageNavItems\"",
|
|
45
|
+
" docs-nav-aria-label=\"${5:Docs navigation}\"",
|
|
46
|
+
" docs-page-nav-aria-label=\"${6:On this page}\"",
|
|
47
|
+
">",
|
|
48
|
+
" <template #docsContent>",
|
|
49
|
+
" <p>$7Page content goes here.</p>",
|
|
50
|
+
" </template>",
|
|
51
|
+
"</ContentDocs>"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
36
54
|
"SRCDEV ContentDocs Items Script": {
|
|
37
55
|
"description": "docsNavItems / docsPageNavItems + active-item refs for ContentDocs",
|
|
38
56
|
"scope": "typescript,vue",
|
|
@@ -10,5 +10,20 @@
|
|
|
10
10
|
" }\"",
|
|
11
11
|
"/>"
|
|
12
12
|
]
|
|
13
|
+
},
|
|
14
|
+
"SRCDEV DisplayTooltipDefined Localised Copy": {
|
|
15
|
+
"description": "DisplayTooltipDefined with localised trigger/close-button copy",
|
|
16
|
+
"scope": "vue,html",
|
|
17
|
+
"body": [
|
|
18
|
+
"<DisplayTooltipDefined",
|
|
19
|
+
" :content-text=\"{",
|
|
20
|
+
" tooltipTitle: { tag: 'h4', text: '$1' },",
|
|
21
|
+
" tooltipContent: { tag: 'p', text: '$2' },",
|
|
22
|
+
" }\"",
|
|
23
|
+
" trigger-aria-label=\"${3:Toggle the popover}\"",
|
|
24
|
+
" close-button-text=\"${4:Close}\"",
|
|
25
|
+
" close-button-aria-label=\"${5:Close tool tip}\"",
|
|
26
|
+
"/>"
|
|
27
|
+
]
|
|
13
28
|
}
|
|
14
29
|
}
|
|
@@ -23,5 +23,16 @@
|
|
|
23
23
|
" </template>",
|
|
24
24
|
"</DisplayTooltip>"
|
|
25
25
|
]
|
|
26
|
+
},
|
|
27
|
+
"SRCDEV DisplayTooltip Localised Trigger Label": {
|
|
28
|
+
"description": "DisplayTooltip with a localised triggerAriaLabel",
|
|
29
|
+
"scope": "vue,html",
|
|
30
|
+
"body": [
|
|
31
|
+
"<DisplayTooltip trigger-aria-label=\"${1:Toggle the popover}\">",
|
|
32
|
+
" <template #tooltipContent>",
|
|
33
|
+
" <p>$0</p>",
|
|
34
|
+
" </template>",
|
|
35
|
+
"</DisplayTooltip>"
|
|
36
|
+
]
|
|
26
37
|
}
|
|
27
38
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"SRCDEV EntryAnimation Basic": {
|
|
3
|
+
"description": "Basic EntryAnimation wrapper with a default slide-in animation",
|
|
4
|
+
"scope": "vue,html",
|
|
5
|
+
"body": [
|
|
6
|
+
"<EntryAnimation animation-type=\"$1entry-slide-in\">",
|
|
7
|
+
" <template #default>",
|
|
8
|
+
" $2",
|
|
9
|
+
" </template>",
|
|
10
|
+
"</EntryAnimation>"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"SRCDEV EntryAnimation Looped, Skip First": {
|
|
14
|
+
"description": "EntryAnimation in a v-for loop, skipping the first (above-the-fold) item",
|
|
15
|
+
"scope": "vue,html",
|
|
16
|
+
"body": [
|
|
17
|
+
"<EntryAnimation",
|
|
18
|
+
" v-for=\"($1item, $2index) in $3items\"",
|
|
19
|
+
" :key=\"$1item.id\"",
|
|
20
|
+
" :skip-animation=\"$2index === 0\"",
|
|
21
|
+
" animation-type=\"$4entry-slide-in\"",
|
|
22
|
+
">",
|
|
23
|
+
" <template #default>",
|
|
24
|
+
" $5",
|
|
25
|
+
" </template>",
|
|
26
|
+
"</EntryAnimation>"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"SRCDEV InputTextCore Basic": {
|
|
3
|
+
"description": "Basic InputTextCore native input (no label/error wrapper)",
|
|
4
|
+
"scope": "vue,html",
|
|
5
|
+
"body": [
|
|
6
|
+
"<InputTextCore",
|
|
7
|
+
" id=\"$1fieldId\"",
|
|
8
|
+
" name=\"$2fieldName\"",
|
|
9
|
+
" v-model=\"$3fieldValue\"",
|
|
10
|
+
" type=\"$4text\"",
|
|
11
|
+
" placeholder=\"$5Enter value...\"",
|
|
12
|
+
"/>"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"SRCDEV InputTextCore Date with min/max": {
|
|
16
|
+
"description": "InputTextCore date input constrained to a min/max range (e.g. no dates in the past)",
|
|
17
|
+
"scope": "vue,html",
|
|
18
|
+
"body": [
|
|
19
|
+
"<InputTextCore",
|
|
20
|
+
" id=\"$1appointment-date\"",
|
|
21
|
+
" name=\"$2appointmentDate\"",
|
|
22
|
+
" v-model=\"$3appointmentDate\"",
|
|
23
|
+
" type=\"date\"",
|
|
24
|
+
" :min=\"new Date().toISOString().split('T')[0]\"",
|
|
25
|
+
" max=\"$42027-12-31\"",
|
|
26
|
+
"/>"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"SRCDEV InputTextWithLabel Basic": {
|
|
30
|
+
"description": "InputTextWithLabel: labelled text field with error/description support",
|
|
31
|
+
"scope": "vue,html",
|
|
32
|
+
"body": [
|
|
33
|
+
"<InputTextWithLabel",
|
|
34
|
+
" v-model=\"$1fieldValue\"",
|
|
35
|
+
" id=\"$2fieldId\"",
|
|
36
|
+
" name=\"$3fieldName\"",
|
|
37
|
+
" type=\"$4text\"",
|
|
38
|
+
" label=\"$5Field label\"",
|
|
39
|
+
" :error-message=\"$6errors.fieldName\"",
|
|
40
|
+
" :field-has-error=\"!!$6errors.fieldName\"",
|
|
41
|
+
"/>"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"SRCDEV InputTextWithLabel Date with min/max": {
|
|
45
|
+
"description": "InputTextWithLabel date field constrained to a min/max range",
|
|
46
|
+
"scope": "vue,html",
|
|
47
|
+
"body": [
|
|
48
|
+
"<InputTextWithLabel",
|
|
49
|
+
" v-model=\"$1appointmentDate\"",
|
|
50
|
+
" id=\"$2appointment-date\"",
|
|
51
|
+
" name=\"$2appointmentDate\"",
|
|
52
|
+
" type=\"date\"",
|
|
53
|
+
" label=\"$3Appointment date\"",
|
|
54
|
+
" :min=\"new Date().toISOString().split('T')[0]\"",
|
|
55
|
+
" max=\"$42027-12-31\"",
|
|
56
|
+
" :error-message=\"$5errors.appointmentDate\"",
|
|
57
|
+
" :field-has-error=\"!!$5errors.appointmentDate\"",
|
|
58
|
+
"/>"
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"SRCDEV InputPasswordWithLabel": {
|
|
62
|
+
"description": "InputPasswordWithLabel with show/hide toggle",
|
|
63
|
+
"scope": "vue,html",
|
|
64
|
+
"body": [
|
|
65
|
+
"<InputPasswordWithLabel",
|
|
66
|
+
" v-model=\"$1password\"",
|
|
67
|
+
" name=\"$2password\"",
|
|
68
|
+
" label=\"$3Password\"",
|
|
69
|
+
" :error-message=\"$4errors.password\"",
|
|
70
|
+
" :field-has-error=\"!!$4errors.password\"",
|
|
71
|
+
"/>"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"SRCDEV InputTextAsNumberWithLabel": {
|
|
75
|
+
"description": "InputTextAsNumberWithLabel numeric stepper with min/max/step",
|
|
76
|
+
"scope": "vue,html",
|
|
77
|
+
"body": [
|
|
78
|
+
"<InputTextAsNumberWithLabel",
|
|
79
|
+
" v-model=\"$1quantity\"",
|
|
80
|
+
" name=\"$2quantity\"",
|
|
81
|
+
" label=\"$3Quantity\"",
|
|
82
|
+
" :min=\"$41\"",
|
|
83
|
+
" :max=\"$599\"",
|
|
84
|
+
" :step=\"$61\"",
|
|
85
|
+
" :error-message=\"$7errors.quantity\"",
|
|
86
|
+
" :field-has-error=\"!!$7errors.quantity\"",
|
|
87
|
+
">",
|
|
88
|
+
" <template #left>−</template>",
|
|
89
|
+
" <template #right>+</template>",
|
|
90
|
+
"</InputTextAsNumberWithLabel>"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"SRCDEV InputText CSS Override": {
|
|
94
|
+
"description": "CSS override scaffold for InputTextCore tokens",
|
|
95
|
+
"scope": "css",
|
|
96
|
+
"body": [
|
|
97
|
+
".$1my-page {",
|
|
98
|
+
" .input-text-wrapper {",
|
|
99
|
+
" --input-text-surface: $2;",
|
|
100
|
+
" --input-text-border: $3;",
|
|
101
|
+
" --input-text-border-focus: $4;",
|
|
102
|
+
" --input-text-color: $5;",
|
|
103
|
+
" }",
|
|
104
|
+
"}"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|