srcdev-nuxt-components 9.4.10 → 9.4.12
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 +18 -0
- package/.claude/component-ledger/audit.json +1 -1
- package/.claude/component-ledger/output.html +1 -1
- package/.claude/skills/components/input-number-core.md +214 -0
- package/.claude/skills/components/input-select-core.md +151 -0
- package/.claude/skills/components/input-text-core.md +16 -0
- package/.claude/skills/components/input-textarea-core.md +154 -0
- package/.claude/skills/components/select-menu.md +195 -0
- package/.claude/skills/components/toggle-switch-core.md +150 -0
- package/.claude/skills/index.md +5 -0
- package/.vscode/srcdev-component-input-number.code-snippets +65 -0
- package/.vscode/srcdev-component-input-select.code-snippets +42 -0
- package/.vscode/srcdev-component-input-textarea.code-snippets +40 -0
- package/.vscode/srcdev-component-select-menu.code-snippets +65 -0
- package/.vscode/srcdev-component-toggle-switch.code-snippets +49 -0
- package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +1 -1
- package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/animations/marquee-scroller/MarqueeScroller.vue +1 -1
- package/app/components/01.atoms/animations/marquee-scroller/stories/MarqueeScroller.stories.ts +1 -1
- package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/animations/section-parallax/SectionParallax.vue +1 -1
- package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +2 -2
- package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +2 -2
- package/app/components/01.atoms/card/CardCore.vue +4 -4
- package/app/components/01.atoms/clipped-panel/CONSUMER-STYLING.md +2 -2
- package/app/components/01.atoms/clipped-panel/ClippedPanel.vue +2 -2
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +2 -2
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue +2 -2
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +1 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +1 -1
- package/app/components/01.atoms/display-tooltip/CONSUMER-STYLING.md +8 -8
- package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +8 -8
- package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +6 -6
- package/app/components/01.atoms/pop-over/PopOver.vue +6 -6
- package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +1 -1
- package/app/components/02.molecules/navigation/deep-expanding-menu/DeepExpandingMenu.vue +1 -1
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +1 -1
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/DeepExpandingMenuClassic.vue +1 -1
- package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +11 -0
- package/app/components/02.molecules/pricing-card/PricingCard.vue +3 -1
- package/app/components/02.molecules/pricing-card/stories/PricingCard.stories.ts +2 -0
- package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +13 -0
- package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +168 -0
- package/app/components/02.molecules/select-menu/SelectMenu.vue +384 -0
- package/app/components/02.molecules/select-menu/stories/SelectMenu.stories.ts +359 -0
- package/app/components/02.molecules/select-menu/tests/SelectMenu.spec.ts +476 -0
- package/app/components/02.molecules/select-menu/tests/__snapshots__/SelectMenu.spec.ts.snap +42 -0
- package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +3 -3
- package/app/components/03.organisms/image-galleries/carousel-flip/CarouselFlip.vue +3 -3
- package/app/components/03.organisms/image-galleries/carousel-flip/stories/CarouselFlip.stories.ts +18 -18
- package/app/components/05.forms/input-button/CONSUMER-STYLING.md +2 -7
- package/app/components/05.forms/input-button/InputButtonCore.vue +1 -5
- package/app/components/05.forms/input-number/CONSUMER-STYLING.md +26 -6
- package/app/components/05.forms/input-number/InputNumberCore.vue +125 -85
- package/app/components/05.forms/input-number/stories/InputNumberCore.stories.ts +92 -0
- package/app/components/05.forms/input-number/tests/InputNumberCore.spec.ts +119 -0
- package/app/components/05.forms/input-number/variants/InputNumberDefault.vue +30 -22
- package/app/components/05.forms/input-number/variants/stories/InputNumberDefault.stories.ts +123 -0
- package/app/components/05.forms/input-number/variants/tests/InputNumberDefault.spec.ts +143 -0
- package/app/components/05.forms/input-range/CONSUMER-STYLING.md +2 -2
- package/app/components/05.forms/input-range/InputRangeCore.vue +2 -2
- package/app/components/05.forms/input-select/InputSelectCore.vue +23 -30
- package/app/components/05.forms/input-select/stories/InputSelectCore.stories.ts +2 -2
- package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +115 -0
- package/app/components/05.forms/input-select/tests/InputSelectCore.spec.ts +129 -0
- package/app/components/05.forms/input-select/variants/InputSelectWithLabel.vue +1 -1
- package/app/components/05.forms/input-select/variants/tests/InputSelectWithLabel.spec.ts +87 -0
- package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +14 -0
- package/app/components/05.forms/input-text/variants/InputTextAsNumberWithLabel.vue +1 -1
- package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +55 -0
- package/app/components/05.forms/input-textarea/InputTextareaCore.vue +24 -16
- package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +1 -1
- package/app/components/05.forms/input-textarea/tests/InputTextareaCore.spec.ts +119 -0
- package/app/components/05.forms/input-textarea/variants/InputTextareaWithLabel.vue +3 -13
- package/app/components/05.forms/input-textarea/variants/tests/InputTextareaWithLabel.spec.ts +93 -0
- package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +95 -10
- package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +29 -0
- package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +120 -119
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchCore.stories.ts +1 -1
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +1 -1
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +2 -2
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitchCore.spec.ts +101 -0
- package/app/components/05.forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +3 -5
- package/app/components/05.forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +1 -2
- package/app/components/05.forms/toggle-switch/variants/tests/ToggleSwitchWithLabel.spec.ts +77 -0
- package/app/components/05.forms/toggle-switch/variants/tests/ToggleSwitchWithLabelInline.spec.ts +66 -0
- package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +4 -4
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +6 -6
- package/app/types/components/index.ts +1 -0
- package/app/types/components/select-menu.d.ts +5 -0
- package/package.json +1 -1
- package/.vscode/srcdev-component-toggle-switch-core.code-snippets +0 -13
|
@@ -291,7 +291,7 @@ onUnmounted(() => {
|
|
|
291
291
|
flex-shrink: 0;
|
|
292
292
|
|
|
293
293
|
border: var(--marquee-scroller-item-border-width, 1px) solid
|
|
294
|
-
var(--marquee-scroller-item-border-colour,
|
|
294
|
+
var(--marquee-scroller-item-border-colour, var(--slate-10));
|
|
295
295
|
border-radius: var(--marquee-scroller-item-border-radius, 4px);
|
|
296
296
|
|
|
297
297
|
&:hover {
|
package/app/components/01.atoms/animations/marquee-scroller/stories/MarqueeScroller.stories.ts
CHANGED
|
@@ -33,7 +33,7 @@ const logoSlots = logoData
|
|
|
33
33
|
.map(
|
|
34
34
|
(item) => `
|
|
35
35
|
<template #${item.id}>
|
|
36
|
-
<div style="display: grid; place-items: center; width: 100%; height: 100%; background:
|
|
36
|
+
<div style="display: grid; place-items: center; width: 100%; height: 100%; background: #eee; font-weight: 600;">
|
|
37
37
|
${item.content}
|
|
38
38
|
</div>
|
|
39
39
|
</template>`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
| `--section-parallax-min-height-fixed` | `120vh` | Section height once the parallax effect is active — taller than the base height to give enough scroll travel to see the motion. |
|
|
9
9
|
| `--section-parallax-background-position` | `center` | `background-position` of the image. |
|
|
10
10
|
| `--section-parallax-background-size` | `cover` | `background-size` of the image. |
|
|
11
|
-
| `--section-parallax-background-colour` | `
|
|
11
|
+
| `--section-parallax-background-colour` | `var(--slate-01)` | Fallback colour visible if the image fails to load or hasn't loaded yet. |
|
|
12
12
|
|
|
13
13
|
```vue
|
|
14
14
|
<SectionParallax
|
|
@@ -38,7 +38,7 @@ watch(
|
|
|
38
38
|
background-size: var(--section-parallax-background-size, cover);
|
|
39
39
|
position: relative;
|
|
40
40
|
|
|
41
|
-
background-color: var(--section-parallax-background-colour,
|
|
41
|
+
background-color: var(--section-parallax-background-colour, var(--slate-01));
|
|
42
42
|
width: 100%;
|
|
43
43
|
|
|
44
44
|
@media (hover: hover) and (pointer: fine) {
|
|
@@ -9,8 +9,8 @@ CanvasSwitcher itself exposes the following public tokens:
|
|
|
9
9
|
| `--canvas-switcher-gap` | `2rem` | Gap between the switcher's own children (currently just the list) |
|
|
10
10
|
| `--canvas-switcher-item-gap` | `1rem` | Gap between each button in the list |
|
|
11
11
|
| `--canvas-switcher-icon-size` | `2.4rem` | Width/height of each icon |
|
|
12
|
-
| `--canvas-switcher-icon-colour` | `
|
|
13
|
-
| `--canvas-switcher-icon-colour-current` | `
|
|
12
|
+
| `--canvas-switcher-icon-colour` | `var(--slate-10)` | Icon colour, resting state |
|
|
13
|
+
| `--canvas-switcher-icon-colour-current` | `var(--green-10)` | Icon colour when that button's canvas is selected (`aria-pressed="true"`) |
|
|
14
14
|
|
|
15
15
|
## Class passthrough
|
|
16
16
|
|
|
@@ -78,10 +78,10 @@ watch(
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
.canvas-switcher-button.input-button-core {
|
|
81
|
-
color: var(--canvas-switcher-icon-colour,
|
|
81
|
+
color: var(--canvas-switcher-icon-colour, var(--slate-10));
|
|
82
82
|
|
|
83
83
|
&[aria-pressed="true"] {
|
|
84
|
-
color: var(--canvas-switcher-icon-colour-current,
|
|
84
|
+
color: var(--canvas-switcher-icon-colour-current, var(--green-10));
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
.icon {
|
|
@@ -90,18 +90,18 @@ watch(
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
&.solid {
|
|
93
|
-
--_card-background-color:
|
|
93
|
+
--_card-background-color: var(--slate-00);
|
|
94
94
|
--_card-border: 0.2rem solid var(--slate-08);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
&.subtle {
|
|
98
|
-
--_card-background-color: color-mix(in oklab,
|
|
98
|
+
--_card-background-color: color-mix(in oklab, var(--slate-01) 50%, transparent);
|
|
99
99
|
--_card-border: 0.2rem solid var(--slate-08);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
&.soft {
|
|
103
|
-
--_card-background-color: color-mix(in oklab,
|
|
104
|
-
--_card-box-shadow-color: color-mix(in oklab,
|
|
103
|
+
--_card-background-color: color-mix(in oklab, var(--slate-01) 20%, transparent);
|
|
104
|
+
--_card-box-shadow-color: color-mix(in oklab, var(--slate-02) 80%, transparent);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
&.outline {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
| Token | Default | Controls |
|
|
6
6
|
|---|---|---|
|
|
7
|
-
| `--clipped-panel-background-colour` | `
|
|
8
|
-
| `--clipped-panel-outline-colour` | `
|
|
7
|
+
| `--clipped-panel-background-colour` | `hsl(0, 0%, 96%)` | Panel background |
|
|
8
|
+
| `--clipped-panel-outline-colour` | `hsl(0, 29%, 3%)` | Outline colour, and the panel's text/icon colour (`color`) |
|
|
9
9
|
| `--clipped-panel-outline-width` | `1px` | Outline width |
|
|
10
10
|
|
|
11
11
|
```css
|
|
@@ -30,9 +30,9 @@ watch(
|
|
|
30
30
|
<style lang="css">
|
|
31
31
|
@layer components {
|
|
32
32
|
.clipped-panel {
|
|
33
|
-
--_outline-colour: var(--clipped-panel-outline-colour,
|
|
33
|
+
--_outline-colour: var(--clipped-panel-outline-colour, hsl(0, 29%, 3%));
|
|
34
34
|
|
|
35
|
-
background-color: var(--clipped-panel-background-colour,
|
|
35
|
+
background-color: var(--clipped-panel-background-colour, hsl(0, 0%, 96%));
|
|
36
36
|
color: var(--_outline-colour);
|
|
37
37
|
outline: var(--clipped-panel-outline-width, 1px) solid var(--_outline-colour);
|
|
38
38
|
|
package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
| `--dashboard-quad-grid-gap` | `2rem` | Gap between the four slot panels |
|
|
8
8
|
| `--dashboard-quad-grid-padding` | `2rem` | Padding inside each slot panel |
|
|
9
9
|
| `--dashboard-quad-grid-outline-width` | `0.1rem` | Slot panel outline width |
|
|
10
|
-
| `--dashboard-quad-grid-outline-colour` | `
|
|
10
|
+
| `--dashboard-quad-grid-outline-colour` | `black` | Slot panel outline colour |
|
|
11
11
|
| `--dashboard-quad-grid-outline-offset` | `0` | Slot panel outline offset |
|
|
12
12
|
| `--dashboard-quad-grid-border-width` | `0` | Slot panel border width (off by default — the panel edge is drawn by the outline) |
|
|
13
|
-
| `--dashboard-quad-grid-border-colour` | `
|
|
13
|
+
| `--dashboard-quad-grid-border-colour` | `black` | Slot panel border colour, only visible once `--dashboard-quad-grid-border-width` is set |
|
|
14
14
|
| `--dashboard-quad-grid-border-radius` | `0.5rem` | Slot panel corner radius |
|
|
15
15
|
| `--dashboard-quad-grid-rule-width` | `0.1rem` | Width of the grid gap rule line (CSS Gap Decorations — see Notes) |
|
|
16
16
|
| `--dashboard-quad-grid-rule-colour` | `transparent` | Colour of the grid gap rule line, invisible by default |
|
|
@@ -53,10 +53,10 @@ watch(
|
|
|
53
53
|
& > div {
|
|
54
54
|
padding: var(--dashboard-quad-grid-padding, 2rem);
|
|
55
55
|
outline: var(--dashboard-quad-grid-outline-width, 0.1rem) solid
|
|
56
|
-
var(--dashboard-quad-grid-outline-colour,
|
|
56
|
+
var(--dashboard-quad-grid-outline-colour, black);
|
|
57
57
|
outline-offset: var(--dashboard-quad-grid-outline-offset, 0);
|
|
58
58
|
border: var(--dashboard-quad-grid-border-width, 0) solid
|
|
59
|
-
var(--dashboard-quad-grid-border-colour,
|
|
59
|
+
var(--dashboard-quad-grid-border-colour, black);
|
|
60
60
|
border-radius: var(--dashboard-quad-grid-border-radius, 0.5rem);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -282,7 +282,7 @@ const RuleDecorationsTemplate: StoryFn<DashboardQuadGridArgs> = (args) => ({
|
|
|
282
282
|
"--dashboard-quad-grid-border-width: 0",
|
|
283
283
|
"--dashboard-quad-grid-border-radius: 0",
|
|
284
284
|
"--dashboard-quad-grid-rule-width: 0.2rem",
|
|
285
|
-
"--dashboard-quad-grid-rule-colour:
|
|
285
|
+
"--dashboard-quad-grid-rule-colour: #cbd5e1",
|
|
286
286
|
"--dashboard-quad-grid-rule-inset: 0",
|
|
287
287
|
].join("; ");
|
|
288
288
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| `--dashboard-stats-grid-gap` | `1.2rem` | Gap between panels, in every row |
|
|
8
8
|
| `--dashboard-stats-grid-panel-padding` | `1.2rem` | Padding inside each panel |
|
|
9
9
|
| `--dashboard-stats-grid-border-width` | `0.1rem` | Panel border width |
|
|
10
|
-
| `--dashboard-stats-grid-border-colour` | `
|
|
10
|
+
| `--dashboard-stats-grid-border-colour` | `hsl(0, 29%, 3%)` | Panel border colour |
|
|
11
11
|
| `--dashboard-stats-grid-border-radius` | `1.2rem` | Panel corner radius |
|
|
12
12
|
| `--dashboard-stats-grid-rule-width` | `0.1rem` | Width of the grid gap rule line (CSS Gap Decorations — see Notes) |
|
|
13
13
|
| `--dashboard-stats-grid-rule-colour` | `transparent` | Colour of the grid gap rule line, invisible by default |
|
|
@@ -57,7 +57,7 @@ watch(
|
|
|
57
57
|
.dashboard-stats-grid {
|
|
58
58
|
.panel {
|
|
59
59
|
border: var(--dashboard-stats-grid-border-width, 0.1rem) solid
|
|
60
|
-
var(--dashboard-stats-grid-border-colour,
|
|
60
|
+
var(--dashboard-stats-grid-border-colour, hsl(0, 29%, 3%));
|
|
61
61
|
border-radius: var(--dashboard-stats-grid-border-radius, 1.2rem);
|
|
62
62
|
padding: var(--dashboard-stats-grid-panel-padding, 1.2rem);
|
|
63
63
|
height: auto;
|
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
| `--display-tooltip-popover-padding` | `1.2rem` | Popover panel content padding |
|
|
16
16
|
| `--display-tooltip-popover-content-gap` | `1.2rem` | Gap between stacked children in the `tooltipContent` slot |
|
|
17
17
|
| `--display-tooltip-popover-outline-width` | `0.1rem` | Popover panel outline (border) width |
|
|
18
|
-
| `--display-tooltip-popover-outline-colour` | `
|
|
19
|
-
| `--display-tooltip-popover-text-colour` | `
|
|
20
|
-
| `--display-tooltip-popover-background-colour` | `
|
|
18
|
+
| `--display-tooltip-popover-outline-colour` | `var(--slate-02)` | Popover panel outline (border) colour |
|
|
19
|
+
| `--display-tooltip-popover-text-colour` | `var(--slate-09)` | Popover panel text colour |
|
|
20
|
+
| `--display-tooltip-popover-background-colour` | `var(--slate-00)` | Popover panel background |
|
|
21
21
|
| `--display-tooltip-popover-border-radius` | `0.8rem` | Popover panel corner radius |
|
|
22
|
-
| `--display-tooltip-popover-shadow` | `
|
|
22
|
+
| `--display-tooltip-popover-shadow` | `0 0.4rem 1.6rem rgba(0,0,0,.12)` | Popover panel elevation shadow |
|
|
23
23
|
| `--display-tooltip-popover-offset` | `0.1rem` | Gap between the trigger and the popover panel |
|
|
24
|
-
| `--display-tooltip-close-button-colour` | `
|
|
24
|
+
| `--display-tooltip-close-button-colour` | `var(--slate-09)` | Close button text colour (used by `DisplayTooltipDefined`) |
|
|
25
25
|
| `--display-tooltip-close-button-border-width` | `0.1rem` | Close button border width |
|
|
26
|
-
| `--display-tooltip-close-button-border-colour` | `
|
|
26
|
+
| `--display-tooltip-close-button-border-colour` | `var(--slate-03)` | Close button border colour |
|
|
27
27
|
| `--display-tooltip-close-button-outline-width` | `0.1rem` | Close button outline width |
|
|
28
28
|
| `--display-tooltip-close-button-outline-colour` | `transparent` | Close button outline colour at rest (no permanent ring) |
|
|
29
|
-
| `--display-tooltip-close-button-border-colour-hover` | `
|
|
30
|
-
| `--display-tooltip-close-button-outline-colour-hover` | `
|
|
29
|
+
| `--display-tooltip-close-button-border-colour-hover` | `var(--slate-06)` | Close button border colour on hover/focus |
|
|
30
|
+
| `--display-tooltip-close-button-outline-colour-hover` | `var(--slate-06)` | Close button outline colour on hover/focus |
|
|
31
31
|
| `--display-tooltip-close-button-padding` | `0.4rem 1rem` | Close button padding |
|
|
32
32
|
|
|
33
33
|
```css
|
|
@@ -115,13 +115,13 @@ watch(
|
|
|
115
115
|
width: var(--display-tooltip-popover-width, 30rem);
|
|
116
116
|
|
|
117
117
|
outline: var(--display-tooltip-popover-outline-width, 0.1rem) solid
|
|
118
|
-
var(--display-tooltip-popover-outline-colour,
|
|
119
|
-
color: var(--display-tooltip-popover-text-colour,
|
|
120
|
-
background-color: var(--display-tooltip-popover-background-colour,
|
|
118
|
+
var(--display-tooltip-popover-outline-colour, var(--slate-02));
|
|
119
|
+
color: var(--display-tooltip-popover-text-colour, var(--slate-09));
|
|
120
|
+
background-color: var(--display-tooltip-popover-background-colour, var(--slate-00));
|
|
121
121
|
border-radius: var(--display-tooltip-popover-border-radius, 0.8rem);
|
|
122
122
|
box-shadow: var(
|
|
123
123
|
--display-tooltip-popover-shadow,
|
|
124
|
-
|
|
124
|
+
0 0.4rem 1.6rem rgba(0, 0, 0, 0.12)
|
|
125
125
|
);
|
|
126
126
|
|
|
127
127
|
position-anchor: var(--_anchor-name);
|
|
@@ -147,9 +147,9 @@ watch(
|
|
|
147
147
|
.display-tooltip-close-button {
|
|
148
148
|
all: unset;
|
|
149
149
|
cursor: pointer;
|
|
150
|
-
color: var(--display-tooltip-close-button-colour,
|
|
150
|
+
color: var(--display-tooltip-close-button-colour, var(--slate-09));
|
|
151
151
|
border: var(--display-tooltip-close-button-border-width, 0.1rem) solid
|
|
152
|
-
var(--display-tooltip-close-button-border-colour,
|
|
152
|
+
var(--display-tooltip-close-button-border-colour, var(--slate-03));
|
|
153
153
|
outline: var(--display-tooltip-close-button-outline-width, 0.1rem) solid transparent;
|
|
154
154
|
|
|
155
155
|
font-weight: 600;
|
|
@@ -160,11 +160,11 @@ watch(
|
|
|
160
160
|
text-decoration: underline;
|
|
161
161
|
border-color: var(
|
|
162
162
|
--display-tooltip-close-button-border-colour-hover,
|
|
163
|
-
|
|
163
|
+
var(--slate-06)
|
|
164
164
|
);
|
|
165
165
|
outline-color: var(
|
|
166
166
|
--display-tooltip-close-button-outline-colour-hover,
|
|
167
|
-
|
|
167
|
+
var(--slate-06)
|
|
168
168
|
);
|
|
169
169
|
outline-offset: 0.2rem;
|
|
170
170
|
}
|
|
@@ -9,21 +9,21 @@
|
|
|
9
9
|
| `--pop-over-trigger-outline-colour-hover` | `var(--theme-ring)` | Trigger outline colour on focus-visible |
|
|
10
10
|
| `--pop-over-width` | `30rem` | Popover panel width |
|
|
11
11
|
| `--pop-over-border-width` | `0.1rem` | Popover panel border width |
|
|
12
|
-
| `--pop-over-border-colour` | `
|
|
12
|
+
| `--pop-over-border-colour` | `var(--slate-02)` | Popover panel border colour |
|
|
13
13
|
| `--pop-over-border-radius` | `0.8rem` | Popover panel corner radius |
|
|
14
|
-
| `--pop-over-background-colour` | `
|
|
15
|
-
| `--pop-over-text-colour` | `
|
|
16
|
-
| `--pop-over-shadow` | `
|
|
14
|
+
| `--pop-over-background-colour` | `var(--slate-00)` | Popover panel background |
|
|
15
|
+
| `--pop-over-text-colour` | `var(--slate-09)` | Popover panel text colour |
|
|
16
|
+
| `--pop-over-shadow` | `0 0.4rem 1.6rem rgba(0,0,0,.12)` | Popover panel elevation shadow |
|
|
17
17
|
| `--pop-over-transition-duration` | `200ms` | Open/close fade duration |
|
|
18
18
|
| `--pop-over-content-padding` | `1.6rem` | Padding around the `content` slot |
|
|
19
19
|
| `--pop-over-content-padding-block-start` | `3.2rem` | Extra top padding so content clears the close button |
|
|
20
20
|
| `--pop-over-close-button-offset` | `0.8rem` | Distance of the close button from the panel's top/right edges |
|
|
21
21
|
| `--pop-over-close-button-size` | `2.4rem` | Close button box width/height |
|
|
22
22
|
| `--pop-over-close-button-border-radius` | `50%` | Close button corner radius |
|
|
23
|
-
| `--pop-over-close-button-colour` | `
|
|
23
|
+
| `--pop-over-close-button-colour` | `var(--slate-06)` | Close button icon colour |
|
|
24
24
|
| `--pop-over-close-button-icon-size` | `1.4rem` | Close button icon glyph size |
|
|
25
25
|
| `--pop-over-close-button-outline-width` | `0.1rem` | Close button focus/hover outline width |
|
|
26
|
-
| `--pop-over-close-button-surface-hover` | `
|
|
26
|
+
| `--pop-over-close-button-surface-hover` | `var(--slate-01)` | Close button background on hover/focus-visible |
|
|
27
27
|
| `--pop-over-close-button-outline-colour-hover` | `var(--theme-ring)` | Close button outline colour on hover/focus-visible |
|
|
28
28
|
|
|
29
29
|
```css
|
|
@@ -102,13 +102,13 @@ watch(
|
|
|
102
102
|
margin: 0;
|
|
103
103
|
inset: auto;
|
|
104
104
|
border: var(--pop-over-border-width, 0.1rem) solid
|
|
105
|
-
var(--pop-over-border-colour,
|
|
105
|
+
var(--pop-over-border-colour, var(--slate-02));
|
|
106
106
|
border-radius: var(--pop-over-border-radius, 0.8rem);
|
|
107
|
-
background-color: var(--pop-over-background-colour,
|
|
108
|
-
color: var(--pop-over-text-colour,
|
|
107
|
+
background-color: var(--pop-over-background-colour, var(--slate-00));
|
|
108
|
+
color: var(--pop-over-text-colour, var(--slate-09));
|
|
109
109
|
box-shadow: var(
|
|
110
110
|
--pop-over-shadow,
|
|
111
|
-
|
|
111
|
+
0 0.4rem 1.6rem rgba(0, 0, 0, 0.12)
|
|
112
112
|
);
|
|
113
113
|
width: var(--pop-over-width, 30rem);
|
|
114
114
|
|
|
@@ -139,12 +139,12 @@ watch(
|
|
|
139
139
|
width: var(--pop-over-close-button-size, 2.4rem);
|
|
140
140
|
height: var(--pop-over-close-button-size, 2.4rem);
|
|
141
141
|
border-radius: var(--pop-over-close-button-border-radius, 50%);
|
|
142
|
-
color: var(--pop-over-close-button-colour,
|
|
142
|
+
color: var(--pop-over-close-button-colour, var(--slate-06));
|
|
143
143
|
outline: var(--pop-over-close-button-outline-width, 0.1rem) solid transparent;
|
|
144
144
|
|
|
145
145
|
&:hover,
|
|
146
146
|
&:focus-visible {
|
|
147
|
-
background-color: var(--pop-over-close-button-surface-hover,
|
|
147
|
+
background-color: var(--pop-over-close-button-surface-hover, var(--slate-01));
|
|
148
148
|
outline-color: var(--pop-over-close-button-outline-colour-hover, var(--theme-ring));
|
|
149
149
|
outline-offset: 0.1rem;
|
|
150
150
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| `--deep-expanding-menu-gap` | `2.4rem` | Gap between top-level items |
|
|
8
8
|
| `--deep-expanding-menu-link-border-width` | `0.2rem` | Bottom border width on links and group toggles |
|
|
9
9
|
| `--deep-expanding-menu-link-padding-block` | `0.8rem` | Vertical padding on links and group toggles |
|
|
10
|
-
| `--deep-expanding-menu-link-border-colour-hover` | `
|
|
10
|
+
| `--deep-expanding-menu-link-border-colour-hover` | `var(--blue-10)` | Bottom border colour on hover/focus |
|
|
11
11
|
| `--deep-expanding-menu-icon-size` | `1.2rem` | Caret icon size |
|
|
12
12
|
| `--deep-expanding-menu-panel-width` | `min(100%, 50vw)` | Popover panel width |
|
|
13
13
|
| `--deep-expanding-menu-panel-background-colour` | `white` | Popover panel background |
|
package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
| `--deep-expanding-menu-classic-item-gap` | `2.4rem` | Gap between top-level items |
|
|
9
9
|
| `--deep-expanding-menu-classic-link-border-width` | `0.2rem` | Bottom border width on links and group toggles |
|
|
10
10
|
| `--deep-expanding-menu-classic-link-padding-block` | `0.8rem` | Vertical padding on links and group toggles |
|
|
11
|
-
| `--deep-expanding-menu-classic-link-border-colour-hover` | `
|
|
11
|
+
| `--deep-expanding-menu-classic-link-border-colour-hover` | `var(--blue-10)` | Bottom border colour on hover/focus |
|
|
12
12
|
| `--deep-expanding-menu-classic-icon-size` | `1.2rem` | Caret icon size |
|
|
13
13
|
| `--deep-expanding-menu-classic-panel-offset-top` | `4rem` | Panel offset from the toggle |
|
|
14
14
|
| `--deep-expanding-menu-classic-panel-width` | `20rem` | Panel width below the `768px` breakpoint |
|
|
@@ -131,6 +131,17 @@ When displaying multiple cards side-by-side (common in pricing pages), wrap in a
|
|
|
131
131
|
|
|
132
132
|
---
|
|
133
133
|
|
|
134
|
+
## Highlight badge text
|
|
135
|
+
|
|
136
|
+
`isHighlighted` shows a top-centred badge reading "Most Popular". Pass `badge-text` to change it,
|
|
137
|
+
e.g. for localisation:
|
|
138
|
+
|
|
139
|
+
```vue
|
|
140
|
+
<PricingCard planName="Standard" :price="99" is-highlighted :badge-text="t('pricing.mostPopular')" />
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
134
145
|
## Discount ribbon
|
|
135
146
|
|
|
136
147
|
Pass `ribbon-text` to render a diagonal corner ribbon (top-right, 45°) for marketing callouts —
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component :is="tag" class="pricing-card" :class="[elementClasses, { 'is-highlighted': isHighlighted }]">
|
|
3
|
-
<div v-if="isHighlighted" class="pricing-card__badge">
|
|
3
|
+
<div v-if="isHighlighted" class="pricing-card__badge">{{ badgeText }}</div>
|
|
4
4
|
|
|
5
5
|
<div v-if="ribbonText" class="pricing-card__ribbon-clip">
|
|
6
6
|
<span class="pricing-card__ribbon">{{ ribbonText }}</span>
|
|
@@ -41,6 +41,7 @@ interface Props {
|
|
|
41
41
|
description?: string;
|
|
42
42
|
features?: string[];
|
|
43
43
|
isHighlighted?: boolean;
|
|
44
|
+
badgeText?: string;
|
|
44
45
|
ctaText?: string;
|
|
45
46
|
ctaDisabled?: boolean;
|
|
46
47
|
ribbonText?: string;
|
|
@@ -54,6 +55,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
54
55
|
description: undefined,
|
|
55
56
|
features: () => [],
|
|
56
57
|
isHighlighted: false,
|
|
58
|
+
badgeText: "Most Popular",
|
|
57
59
|
ctaText: "Get started",
|
|
58
60
|
ctaDisabled: false,
|
|
59
61
|
ribbonText: undefined,
|
|
@@ -11,6 +11,7 @@ const meta: Meta<typeof PricingCard> = {
|
|
|
11
11
|
billingPeriod: { control: "text" },
|
|
12
12
|
description: { control: "text" },
|
|
13
13
|
isHighlighted: { control: "boolean" },
|
|
14
|
+
badgeText: { control: "text" },
|
|
14
15
|
ctaText: { control: "text" },
|
|
15
16
|
ctaDisabled: { control: "boolean" },
|
|
16
17
|
ribbonText: { control: "text" },
|
|
@@ -22,6 +23,7 @@ const meta: Meta<typeof PricingCard> = {
|
|
|
22
23
|
description: "Perfect for freelancers and solo practitioners.",
|
|
23
24
|
features: ["Embed on one domain", "Unlimited consultations", "Email support", "Monthly updates"],
|
|
24
25
|
isHighlighted: false,
|
|
26
|
+
badgeText: "Most Popular",
|
|
25
27
|
ctaText: "Get started",
|
|
26
28
|
ctaDisabled: false,
|
|
27
29
|
ribbonText: undefined,
|
|
@@ -84,6 +84,19 @@ describe("PricingCard", () => {
|
|
|
84
84
|
expect(wrapper.text()).toContain("Most Popular");
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
it("renders custom badge text when highlighted", () => {
|
|
88
|
+
const wrapper = mount(PricingCard, {
|
|
89
|
+
props: {
|
|
90
|
+
planName: "Test Plan",
|
|
91
|
+
price: 100,
|
|
92
|
+
isHighlighted: true,
|
|
93
|
+
badgeText: "Le plus populaire",
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(wrapper.find(".pricing-card__badge").text()).toBe("Le plus populaire");
|
|
98
|
+
});
|
|
99
|
+
|
|
87
100
|
it("emits select event with plan name on CTA click", async () => {
|
|
88
101
|
const wrapper = mount(PricingCard, {
|
|
89
102
|
props: {
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# SelectMenu — Consumer Styling Guide
|
|
2
|
+
|
|
3
|
+
## Public token API
|
|
4
|
+
|
|
5
|
+
All `--select-menu-*` tokens are the stable override surface, each falling back to a `--theme-*`
|
|
6
|
+
global token so it matches the rest of the design system out of the box.
|
|
7
|
+
|
|
8
|
+
### Trigger button
|
|
9
|
+
|
|
10
|
+
| Token | Default | Controls |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `--select-menu-trigger-gap` | `0.8rem` | Gap between icon / label / chevron |
|
|
13
|
+
| `--select-menu-trigger-min-height` | `4.4rem` | Trigger minimum height |
|
|
14
|
+
| `--select-menu-trigger-padding-block` | `0.8rem` | Trigger vertical padding |
|
|
15
|
+
| `--select-menu-trigger-padding-inline` | `1.2rem` | Trigger horizontal padding |
|
|
16
|
+
| `--select-menu-trigger-border-width` | `0.1rem` | Trigger border thickness |
|
|
17
|
+
| `--select-menu-trigger-border` | `var(--theme-border)` | Trigger border colour (rest state) |
|
|
18
|
+
| `--select-menu-trigger-border-focus` | `var(--theme-border-focus)` | Trigger border colour on hover/focus |
|
|
19
|
+
| `--select-menu-trigger-border-radius` | `0.5rem` | Trigger corner rounding |
|
|
20
|
+
| `--select-menu-trigger-surface` | `var(--theme-input-surface)` | Trigger background |
|
|
21
|
+
| `--select-menu-trigger-text-color` | `var(--theme-text)` | Trigger label text colour |
|
|
22
|
+
| `--select-menu-trigger-font-size` | `1.6rem` | Trigger label font size |
|
|
23
|
+
| `--select-menu-trigger-outline-width` | `0.2rem` | Focus-visible outline width (trigger and items) |
|
|
24
|
+
| `--select-menu-trigger-icon-size` | `2rem` | Selected option's icon size in the trigger |
|
|
25
|
+
| `--select-menu-trigger-chevron-size` | `1.6rem` | Chevron icon size |
|
|
26
|
+
|
|
27
|
+
### Menu popover
|
|
28
|
+
|
|
29
|
+
| Token | Default | Controls |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `--select-menu-block-distance` | `0.4rem` | Gap between trigger bottom and menu top |
|
|
32
|
+
| `--select-menu-popover-border-width` | `0.1rem` | Popover border thickness |
|
|
33
|
+
| `--select-menu-popover-border` | `var(--theme-border)` | Popover border colour |
|
|
34
|
+
| `--select-menu-popover-surface` | `var(--theme-input-surface)` | Popover background |
|
|
35
|
+
| `--select-menu-popover-border-radius` | `0.5rem` | Popover corner rounding |
|
|
36
|
+
| `--select-menu-popover-min-width` | `18rem` | Minimum popover width |
|
|
37
|
+
| `--select-menu-popover-max-height` | `32rem` | Maximum popover height before scrolling |
|
|
38
|
+
| `--select-menu-popover-shadow` | `0 0.4rem 1.6rem rgb(0 0 0 / 12%)` | Popover drop shadow |
|
|
39
|
+
| `--select-menu-transition-duration` | `200ms` | Open/close fade and chevron-rotate duration |
|
|
40
|
+
|
|
41
|
+
### Options
|
|
42
|
+
|
|
43
|
+
| Token | Default | Controls |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `--select-menu-item-gap` | `0.8rem` | Gap between checkmark / icon / label in a row |
|
|
46
|
+
| `--select-menu-item-padding-block` | `1rem` | Option row vertical padding |
|
|
47
|
+
| `--select-menu-item-padding-inline` | `1.2rem` | Option row horizontal padding |
|
|
48
|
+
| `--select-menu-item-text-color` | `var(--theme-text)` | Option label colour |
|
|
49
|
+
| `--select-menu-item-font-size` | `1.5rem` | Option label font size |
|
|
50
|
+
| `--select-menu-item-surface-hover` | `var(--theme-input-surface-hover)` | Option row background on hover/focus |
|
|
51
|
+
| `--select-menu-item-check-size` | `1.6rem` | Checkmark icon box size |
|
|
52
|
+
| `--select-menu-item-check-color` | `currentcolor` | Checkmark icon colour |
|
|
53
|
+
| `--select-menu-item-icon-size` | `1.8rem` | Per-option icon size |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Global theming — recommended approach
|
|
58
|
+
|
|
59
|
+
Create `assets/styles/setup/07.components/select-menu.css` in the consuming app and set tokens
|
|
60
|
+
on `:root`. This applies to every `SelectMenu` across the site.
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
/* assets/styles/setup/07.components/select-menu.css */
|
|
64
|
+
:root {
|
|
65
|
+
--select-menu-trigger-border-radius: 999rem;
|
|
66
|
+
--select-menu-trigger-surface: var(--brand-surface);
|
|
67
|
+
--select-menu-trigger-border: var(--brand-border);
|
|
68
|
+
|
|
69
|
+
--select-menu-popover-surface: var(--brand-surface);
|
|
70
|
+
--select-menu-popover-border: var(--brand-border);
|
|
71
|
+
--select-menu-popover-shadow: 0 0.8rem 2.4rem rgba(0, 0, 0, 0.15);
|
|
72
|
+
|
|
73
|
+
--select-menu-item-surface-hover: var(--brand-surface-subtle);
|
|
74
|
+
--select-menu-item-check-color: var(--brand-accent);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Per-instance overrides via styleClassPassthrough
|
|
81
|
+
|
|
82
|
+
```vue
|
|
83
|
+
<SelectMenu
|
|
84
|
+
v-model="language"
|
|
85
|
+
:options="languageOptions"
|
|
86
|
+
label="Language"
|
|
87
|
+
:style-class-passthrough="['compact-switcher']"
|
|
88
|
+
/>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
.select-menu.compact-switcher {
|
|
93
|
+
--select-menu-trigger-min-height: 3.2rem;
|
|
94
|
+
--select-menu-trigger-padding-inline: 0.8rem;
|
|
95
|
+
--select-menu-trigger-border-radius: 50%;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Trigger content variants
|
|
102
|
+
|
|
103
|
+
`showIcon` / `showLabel` / `showChevron` control what renders in the trigger — combine them for
|
|
104
|
+
the three common shapes:
|
|
105
|
+
|
|
106
|
+
| Variant | Props |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Icon-only (e.g. flag switcher in a tight header) | `:show-label="false" :show-chevron="false"` |
|
|
109
|
+
| Text + chevron (e.g. a category filter with no per-option icons) | `:show-icon="false"` (default `showLabel`/`showChevron`) |
|
|
110
|
+
| Icon + text + chevron (full select) | Defaults — no overrides needed |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Single-select vs multi-select
|
|
115
|
+
|
|
116
|
+
By default `SelectMenu` is single-select: `v-model` is `string | number | undefined`, the selected
|
|
117
|
+
option shows a checkmark, and picking one closes the popover.
|
|
118
|
+
|
|
119
|
+
Set `multiple` for a checkbox-per-option multi-select instead: `v-model` becomes
|
|
120
|
+
`(string | number)[]`, every option shows a checkbox (checked/unchecked), and picking an option
|
|
121
|
+
toggles it in the array without closing the popover — so several can be picked in one open/close
|
|
122
|
+
cycle. By default the trigger text stays fixed on `placeholder`/`label` as a static category tag
|
|
123
|
+
(e.g. `"Services required"`) regardless of how many options are checked, since a comma-joined list
|
|
124
|
+
of checked options would grow unpredictably long. Set `showSelectionInTrigger` to opt into that
|
|
125
|
+
comma-joined list instead (falling back to `placeholder`/`label` when nothing is checked). The
|
|
126
|
+
trigger icon is not shown in multi-select mode (`showIcon` has no effect), since there's no single
|
|
127
|
+
selected option to represent.
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
const treatments = ref<string[]>([]);
|
|
132
|
+
const treatmentOptions = [
|
|
133
|
+
{ value: "trim", label: "Trim" },
|
|
134
|
+
{ value: "layers", label: "Layers" },
|
|
135
|
+
{ value: "restyle", label: "Restyle" },
|
|
136
|
+
{ value: "straightening", label: "Straightening" },
|
|
137
|
+
];
|
|
138
|
+
</script>
|
|
139
|
+
|
|
140
|
+
<template>
|
|
141
|
+
<SelectMenu v-model="treatments" :options="treatmentOptions" label="Services required" multiple />
|
|
142
|
+
|
|
143
|
+
<!-- Trigger updates to "Layers, Restyle" etc. as options are checked -->
|
|
144
|
+
<SelectMenu
|
|
145
|
+
v-model="treatments"
|
|
146
|
+
:options="treatmentOptions"
|
|
147
|
+
label="Services required"
|
|
148
|
+
multiple
|
|
149
|
+
show-selection-in-trigger
|
|
150
|
+
/>
|
|
151
|
+
</template>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
For several independent single-select filter categories (rather than one multi-select category),
|
|
155
|
+
place multiple single-select `SelectMenu` instances side by side instead — see the "Filter Bar"
|
|
156
|
+
story.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Notes
|
|
161
|
+
|
|
162
|
+
- **Popover API + CSS anchor positioning** — same mechanism as `ActionMenu`. Broadly supported
|
|
163
|
+
(Chrome 114+, Firefox 125+, Safari 17+). No polyfill is included.
|
|
164
|
+
- **Popover left-aligns with the trigger** by default (`left: anchor(left)`), unlike `ActionMenu`
|
|
165
|
+
which right-aligns — matches native `<select>` dropdown behaviour. Flips above the trigger near
|
|
166
|
+
the bottom of the viewport (`position-try-fallbacks: flip-block`).
|
|
167
|
+
- **Chevron rotation** is pure CSS via `:has(.select-menu-popover:popover-open)` — no JS state
|
|
168
|
+
needed for the visual, though `isOpen` is still tracked internally to drive `aria-expanded`.
|