srcdev-nuxt-components 9.4.9 → 9.4.11
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 +38 -6
- package/.claude/component-ledger/audit.json +1 -1
- package/.claude/component-ledger/build.mjs +26 -0
- package/.claude/component-ledger/output.html +8 -3
- package/.claude/component-ledger/template.html +7 -2
- package/.claude/skills/component-dynamic-slots.md +1 -1
- package/.claude/skills/components/alert-mask-core.md +84 -0
- package/.claude/skills/components/canvas-switcher.md +1 -1
- package/.claude/skills/components/carousel-flip.md +112 -168
- package/.claude/skills/components/container-glow.md +123 -0
- package/.claude/skills/components/dashboard-quad-grid.md +98 -0
- package/.claude/skills/components/dashboard-stats-grid.md +103 -0
- package/.claude/skills/components/display-theme-switch.md +60 -0
- package/.claude/skills/components/glowing-border.md +66 -0
- package/.claude/skills/components/input-number-core.md +214 -0
- package/.claude/skills/components/input-range-core.md +142 -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/section-parallax.md +32 -10
- package/.claude/skills/components/select-menu.md +195 -0
- package/.claude/skills/components/toggle-switch-core.md +150 -0
- package/.claude/skills/components/ui-block-decorated.md +56 -0
- package/.claude/skills/components/wipe-away-vertical.md +98 -0
- package/.claude/skills/icon-sets.md +1 -1
- package/.claude/skills/index.md +15 -1
- package/.vscode/css-custom-data.json +38 -0
- package/.vscode/settings.json +3 -0
- package/.vscode/srcdev-component-alert-mask-core.code-snippets +31 -0
- package/.vscode/srcdev-component-carousel-flip.code-snippets +41 -0
- package/.vscode/srcdev-component-container-glow.code-snippets +33 -0
- package/.vscode/srcdev-component-dashboard-quad-grid.code-snippets +36 -0
- package/.vscode/srcdev-component-dashboard-stats-grid.code-snippets +35 -0
- package/.vscode/srcdev-component-display-theme-switch.code-snippets +27 -0
- package/.vscode/srcdev-component-glowing-border.code-snippets +23 -0
- package/.vscode/srcdev-component-input-number.code-snippets +65 -0
- package/.vscode/srcdev-component-input-range.code-snippets +85 -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-section-parallax.code-snippets +27 -0
- package/.vscode/srcdev-component-select-menu.code-snippets +65 -0
- package/.vscode/srcdev-component-toggle-switch.code-snippets +49 -0
- package/.vscode/srcdev-component-ui-block-decorated.code-snippets +24 -0
- package/.vscode/srcdev-component-wipe-away-vertical.code-snippets +25 -0
- package/README.md +18 -37
- package/app/components/{alert-mask → 01.atoms/alert-mask}/AlertMaskCore.vue +16 -17
- package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +46 -0
- package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +79 -0
- package/app/components/{alert-mask → 01.atoms/alert-mask}/tests/AlertMaskCore.spec.ts +10 -10
- package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +86 -0
- package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +299 -0
- package/app/components/01.atoms/animations/container-glow/stories/ContainerGlow.stories.ts +175 -0
- package/app/components/01.atoms/animations/container-glow/tests/ContainerGlow.spec.ts +131 -0
- package/app/components/01.atoms/animations/container-glow/tests/__snapshots__/ContainerGlow.spec.ts.snap +14 -0
- package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +61 -0
- package/app/components/01.atoms/animations/glowing-border/GlowingBorder.vue +132 -0
- package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +165 -0
- package/app/components/01.atoms/animations/glowing-border/tests/GlowingBorder.spec.ts +94 -0
- package/app/components/01.atoms/animations/glowing-border/tests/__snapshots__/GlowingBorder.spec.ts.snap +3 -0
- 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 +44 -0
- package/app/components/{parallax → 01.atoms/animations/section-parallax}/SectionParallax.vue +11 -10
- package/app/components/01.atoms/animations/section-parallax/stories/SectionParallax.stories.ts +98 -0
- package/app/components/01.atoms/animations/section-parallax/tests/SectionParallax.spec.ts +102 -0
- package/app/components/01.atoms/animations/section-parallax/tests/__snapshots__/SectionParallax.spec.ts.snap +9 -0
- package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +70 -0
- package/app/components/01.atoms/animations/view-timeline/WipeAwayVertical.vue +181 -0
- package/app/components/01.atoms/animations/view-timeline/stories/WipeAwayVertical.stories.ts +269 -0
- package/app/components/01.atoms/animations/view-timeline/tests/WipeAwayVertical.spec.ts +127 -0
- package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +3 -3
- package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +2 -2
- package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +1 -1
- 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 +42 -0
- package/app/components/{layout-grids/LayoutGridA.vue → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue} +23 -13
- package/app/components/{layout-grids/stories/LayoutGridA.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts} +151 -23
- package/app/components/{layout-grids/tests/LayoutGridA.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/tests/DashboardQuadGrid.spec.ts} +25 -25
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +41 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +133 -0
- package/app/components/{layout-grids/stories/LayoutGridB.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts} +24 -24
- package/app/components/{layout-grids/tests/LayoutGridB.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/tests/DashboardStatsGrid.spec.ts} +23 -23
- 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/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +39 -0
- package/app/components/01.atoms/ui-block-decorated/UiBlockDecorated.vue +141 -0
- package/app/components/01.atoms/ui-block-decorated/stories/UiBlockDecorated.stories.ts +148 -0
- package/app/components/01.atoms/ui-block-decorated/tests/UiBlockDecorated.spec.ts +80 -0
- package/app/components/01.atoms/ui-block-decorated/tests/__snapshots__/UiBlockDecorated.spec.ts.snap +3 -0
- package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +6 -6
- package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +34 -0
- package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +102 -0
- package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +115 -0
- package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +86 -0
- 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/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 +46 -0
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/CarouselFlip.vue +63 -42
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/stories/CarouselFlip.stories.ts +114 -29
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/tests/CarouselFlip.spec.ts +80 -0
- package/app/components/05.forms/form-field/FormField.vue +1 -1
- package/app/components/05.forms/form-wrapper/FormWrapper.vue +1 -1
- 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 +45 -0
- package/app/components/05.forms/input-range/InputRangeCore.vue +79 -143
- package/app/components/05.forms/input-range/stories/InputRangeCore.stories.ts +126 -0
- package/app/components/05.forms/input-range/tests/InputRangeCore.spec.ts +124 -0
- package/app/components/05.forms/input-range/variants/InputRangeDefault.vue +9 -32
- package/app/components/05.forms/input-range/variants/stories/InputRangeDefault.stories.ts +108 -0
- package/app/components/05.forms/input-range/variants/tests/InputRangeDefault.spec.ts +140 -0
- 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 +220 -0
- 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 +20 -6
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +12 -10
- package/app/types/components/container-glow.d.ts +8 -0
- package/app/types/components/index.ts +2 -1
- package/app/types/components/select-menu.d.ts +5 -0
- package/package.json +3 -2
- package/.vscode/srcdev-component-toggle-switch-core.code-snippets +0 -13
- package/app/components/05.forms/input-range-fancy/InputRangeFancyCore.vue +0 -426
- package/app/components/05.forms/input-range-fancy/InputRangeFancyWithLabel.vue +0 -94
- package/app/components/carousels/CarouselBasic.vue +0 -317
- package/app/components/carousels/CarouselInfinite.vue +0 -358
- package/app/components/container-glow/ContainerGlowCore.vue +0 -296
- package/app/components/container-glow/stories/ContainerGlowCore.stories.ts +0 -337
- package/app/components/display-theme-switch/DisplayThemeSwitch.vue +0 -189
- package/app/components/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +0 -154
- package/app/components/glowing-border/GlowingBorder.vue +0 -142
- package/app/components/glowing-border/stories/GlowingBorder.stories.ts +0 -141
- package/app/components/layout-grids/LayoutGridB.vue +0 -134
- package/app/components/test-storybook/TestStorybook.vue +0 -49
- package/app/components/test-storybook/stories/TestStorybook.stories.ts +0 -28
- package/app/components/ui-block-decorated/UiBlockDecorated.vue +0 -167
- package/app/components/view-timeline/WipeAwayVertical.vue +0 -180
- package/app/types/components/carousel-basic.d.ts +0 -19
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { Meta, StoryFn } from "@nuxtjs/storybook";
|
|
2
|
+
import { reactive } from "vue";
|
|
3
|
+
import InputTextWithLabel from "../../input-text/variants/InputTextWithLabel.vue";
|
|
4
|
+
import InputRangeDefault from "../../input-range/variants/InputRangeDefault.vue";
|
|
5
|
+
import InputNumberDefault from "../../input-number/variants/InputNumberDefault.vue";
|
|
6
|
+
import InputTextareaWithLabel from "../../input-textarea/variants/InputTextareaWithLabel.vue";
|
|
7
|
+
import InputSelectWithLabel from "../../input-select/variants/InputSelectWithLabel.vue";
|
|
8
|
+
import ToggleSwitchWithLabel from "../../toggle-switch/variants/ToggleSwitchWithLabel.vue";
|
|
9
|
+
import InputButtonCore from "../../input-button/InputButtonCore.vue";
|
|
10
|
+
import FormField from "../../form-field/FormField.vue";
|
|
11
|
+
import HeroText from "../../../01.atoms/text-blocks/hero-text/HeroText.vue";
|
|
12
|
+
import type { InputUiVariant, IFormMultipleOptions } from "~/types/forms/types.forms.d";
|
|
13
|
+
|
|
14
|
+
interface MigratedFieldsFormStoryArgs {
|
|
15
|
+
inputVariant: InputUiVariant;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Living reference, not a component of its own — one field per 05.forms component group that
|
|
19
|
+
// currently scores 5/5 in the Component Ledger (.claude/component-ledger/audit.json: tier folder,
|
|
20
|
+
// tests, story, skill doc, CONSUMER-STYLING.md, VS Code snippet). As of 2026-09-23 that's
|
|
21
|
+
// InputTextCore (via InputTextWithLabel), InputRangeCore (via InputRangeDefault), InputNumberCore
|
|
22
|
+
// (via InputNumberDefault), InputTextareaCore (via InputTextareaWithLabel), InputSelectCore
|
|
23
|
+
// (via InputSelectWithLabel), and ToggleSwitchCore (via ToggleSwitchWithLabel) — every other
|
|
24
|
+
// 05.forms component (checkbox, radio, ...) is still mid-migration.
|
|
25
|
+
// Add a field here each time /migrate-component brings another 05.forms component up to 5/5, so
|
|
26
|
+
// this story doubles as a visible migration-progress tracker rather than living only in the
|
|
27
|
+
// ledger's HTML output. No validation wiring (useZodValidation/zod) here — that's the consuming
|
|
28
|
+
// app's concern, this is a visual/composition reference only.
|
|
29
|
+
export default {
|
|
30
|
+
title: "Patterns/Migrated Fields Form",
|
|
31
|
+
argTypes: {
|
|
32
|
+
inputVariant: {
|
|
33
|
+
control: { type: "select" },
|
|
34
|
+
options: ["normal", "outlined", "underlined"],
|
|
35
|
+
description: "Applied to every text-like field in the form at once",
|
|
36
|
+
table: { category: "Styling" },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
args: {
|
|
40
|
+
inputVariant: "normal",
|
|
41
|
+
},
|
|
42
|
+
} as Meta<MigratedFieldsFormStoryArgs>;
|
|
43
|
+
|
|
44
|
+
const Template: StoryFn<MigratedFieldsFormStoryArgs> = (args) => ({
|
|
45
|
+
components: {
|
|
46
|
+
InputTextWithLabel,
|
|
47
|
+
InputRangeDefault,
|
|
48
|
+
InputNumberDefault,
|
|
49
|
+
InputTextareaWithLabel,
|
|
50
|
+
InputSelectWithLabel,
|
|
51
|
+
ToggleSwitchWithLabel,
|
|
52
|
+
InputButtonCore,
|
|
53
|
+
FormField,
|
|
54
|
+
HeroText,
|
|
55
|
+
},
|
|
56
|
+
setup() {
|
|
57
|
+
const state = reactive({
|
|
58
|
+
fullName: "",
|
|
59
|
+
budget: 50,
|
|
60
|
+
quantity: 1,
|
|
61
|
+
notes: "",
|
|
62
|
+
colour: "",
|
|
63
|
+
subscribe: false,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const colourOptions = reactive<IFormMultipleOptions>({
|
|
67
|
+
data: [
|
|
68
|
+
{ id: "1", name: "red", value: "red", label: "Red" },
|
|
69
|
+
{ id: "2", name: "blue", value: "blue", label: "Blue" },
|
|
70
|
+
{ id: "3", name: "green", value: "green", label: "Green" },
|
|
71
|
+
],
|
|
72
|
+
total: 3,
|
|
73
|
+
skip: 0,
|
|
74
|
+
limit: 10,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Demo-only "validation" — a real consuming app would wire this through something like
|
|
78
|
+
// useZodValidation instead (see this file's top comment). Kept deliberately simple so the
|
|
79
|
+
// Continue button has an obvious, reliable way to trigger each field's error state for
|
|
80
|
+
// exercising InputTextWithLabel/InputRangeDefault/InputNumberDefault/InputTextareaWithLabel/
|
|
81
|
+
// InputSelectWithLabel's error UI in Storybook.
|
|
82
|
+
const errors = reactive({
|
|
83
|
+
fullName: "",
|
|
84
|
+
budget: "",
|
|
85
|
+
quantity: "",
|
|
86
|
+
notes: "",
|
|
87
|
+
colour: "",
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const validate = () => {
|
|
91
|
+
errors.fullName = state.fullName.trim() ? "" : "Full name is required";
|
|
92
|
+
errors.budget = state.budget >= 100 ? "" : "Budget must be at least £100";
|
|
93
|
+
errors.quantity = state.quantity >= 1 ? "" : "Quantity must be at least 1";
|
|
94
|
+
errors.notes = state.notes.trim() ? "" : "Notes are required";
|
|
95
|
+
errors.colour = state.colour ? "" : "Please choose a colour";
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const clearErrors = () => {
|
|
99
|
+
errors.fullName = "";
|
|
100
|
+
errors.budget = "";
|
|
101
|
+
errors.quantity = "";
|
|
102
|
+
errors.notes = "";
|
|
103
|
+
errors.colour = "";
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return { args, state, errors, validate, clearErrors, colourOptions };
|
|
107
|
+
},
|
|
108
|
+
template: `
|
|
109
|
+
<div style="margin: 36px; max-width: 480px;">
|
|
110
|
+
<HeroText
|
|
111
|
+
tag="h2"
|
|
112
|
+
font-size="heading"
|
|
113
|
+
:text-content="[{ text: 'Migrated fields', styleClass: 'normal' }]"
|
|
114
|
+
:style-class-passthrough="['mbe-20']"
|
|
115
|
+
/>
|
|
116
|
+
<p style="margin: 0 0 2rem 0; color: #475569; font-size: 1.4rem;">
|
|
117
|
+
One field per 05.forms component that's fully migrated (5/5 on the Component Ledger).
|
|
118
|
+
Click Continue with an empty name, a budget under £100, a quantity under 1, empty notes,
|
|
119
|
+
or no colour chosen to see the error states.
|
|
120
|
+
</p>
|
|
121
|
+
|
|
122
|
+
<form novalidate @submit.prevent="validate">
|
|
123
|
+
<FormField width="wide" :has-gutter="false">
|
|
124
|
+
<InputTextWithLabel
|
|
125
|
+
v-model="state.fullName"
|
|
126
|
+
type="text"
|
|
127
|
+
name="fullName"
|
|
128
|
+
label="Full name"
|
|
129
|
+
placeholder="eg. Jane Smith"
|
|
130
|
+
:error-message="errors.fullName"
|
|
131
|
+
:field-has-error="!!errors.fullName"
|
|
132
|
+
:required="true"
|
|
133
|
+
:input-variant="args.inputVariant"
|
|
134
|
+
/>
|
|
135
|
+
</FormField>
|
|
136
|
+
|
|
137
|
+
<FormField width="wide" :has-gutter="false">
|
|
138
|
+
<InputRangeDefault
|
|
139
|
+
v-model="state.budget"
|
|
140
|
+
name="budget"
|
|
141
|
+
label="Budget (£)"
|
|
142
|
+
:min="0"
|
|
143
|
+
:max="500"
|
|
144
|
+
:step="10"
|
|
145
|
+
:error-message="errors.budget"
|
|
146
|
+
:field-has-error="!!errors.budget"
|
|
147
|
+
>
|
|
148
|
+
<template #left><span aria-hidden="true">−</span></template>
|
|
149
|
+
<template #right><span aria-hidden="true">+</span></template>
|
|
150
|
+
</InputRangeDefault>
|
|
151
|
+
</FormField>
|
|
152
|
+
|
|
153
|
+
<FormField width="wide" :has-gutter="false">
|
|
154
|
+
<InputNumberDefault
|
|
155
|
+
v-model="state.quantity"
|
|
156
|
+
name="quantity"
|
|
157
|
+
label="Quantity"
|
|
158
|
+
:min="1"
|
|
159
|
+
:max="10"
|
|
160
|
+
:error-message="errors.quantity"
|
|
161
|
+
:field-has-error="!!errors.quantity"
|
|
162
|
+
:input-variant="args.inputVariant"
|
|
163
|
+
>
|
|
164
|
+
<template #left><span aria-hidden="true">−</span></template>
|
|
165
|
+
<template #right><span aria-hidden="true">+</span></template>
|
|
166
|
+
</InputNumberDefault>
|
|
167
|
+
</FormField>
|
|
168
|
+
|
|
169
|
+
<FormField width="wide" :has-gutter="false">
|
|
170
|
+
<InputTextareaWithLabel
|
|
171
|
+
v-model="state.notes"
|
|
172
|
+
name="notes"
|
|
173
|
+
label="Notes"
|
|
174
|
+
placeholder="Anything else we should know?"
|
|
175
|
+
:error-message="errors.notes"
|
|
176
|
+
:field-has-error="!!errors.notes"
|
|
177
|
+
:input-variant="args.inputVariant"
|
|
178
|
+
/>
|
|
179
|
+
</FormField>
|
|
180
|
+
|
|
181
|
+
<FormField width="wide" :has-gutter="false">
|
|
182
|
+
<InputSelectWithLabel
|
|
183
|
+
v-model="state.colour"
|
|
184
|
+
v-model:field-data="colourOptions"
|
|
185
|
+
name="colour"
|
|
186
|
+
label="Favourite colour"
|
|
187
|
+
placeholder="Choose a colour"
|
|
188
|
+
:error-message="errors.colour"
|
|
189
|
+
:field-has-error="!!errors.colour"
|
|
190
|
+
:input-variant="args.inputVariant"
|
|
191
|
+
/>
|
|
192
|
+
</FormField>
|
|
193
|
+
|
|
194
|
+
<FormField width="wide" :has-gutter="false">
|
|
195
|
+
<ToggleSwitchWithLabel v-model="state.subscribe" name="subscribe" label="Subscribe to updates" />
|
|
196
|
+
</FormField>
|
|
197
|
+
|
|
198
|
+
<FormField width="wide" :has-gutter="false">
|
|
199
|
+
<div style="display: flex; gap: 1.2rem;">
|
|
200
|
+
<InputButtonCore type="submit" variant="primary" button-text="Continue" />
|
|
201
|
+
<InputButtonCore type="button" variant="tertiary" button-text="Clear errors" @click="clearErrors" />
|
|
202
|
+
</div>
|
|
203
|
+
</FormField>
|
|
204
|
+
</form>
|
|
205
|
+
|
|
206
|
+
<div
|
|
207
|
+
style="margin-top: 2rem; padding: 1.6rem; border-radius: 0.8rem; background: #f8fafc; font-family: monospace; font-size: 1.3rem;"
|
|
208
|
+
>
|
|
209
|
+
<div>fullName: {{ state.fullName || '""' }}</div>
|
|
210
|
+
<div>budget: £{{ state.budget }}</div>
|
|
211
|
+
<div>quantity: {{ state.quantity }}</div>
|
|
212
|
+
<div>notes: {{ state.notes || '""' }}</div>
|
|
213
|
+
<div>colour: {{ state.colour || '""' }}</div>
|
|
214
|
+
<div>subscribe: {{ state.subscribe }}</div>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
`,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export const Default = Template.bind({});
|
|
@@ -23,6 +23,13 @@ token-rename pass, not a redesign.
|
|
|
23
23
|
Geometry (`--input-toggle-*`, `--form-element-*`) is shared across every `05.forms` component and
|
|
24
24
|
untouched by this — see `theming-form-geometry-tokens.md`.
|
|
25
25
|
|
|
26
|
+
### Shape (`round` prop)
|
|
27
|
+
|
|
28
|
+
`--toggle-switch-border-radius` controls the track and thumb's shared `border-radius`. Left unset,
|
|
29
|
+
it defaults to `100vw` (pill shape) when the `round` prop is `true` (the default), or `0.4rem`
|
|
30
|
+
(a rounded-square shape) when `round` is `false` — see the `SquareShape` story. Set the token
|
|
31
|
+
directly to override with an exact value the two-state default doesn't produce.
|
|
32
|
+
|
|
26
33
|
### Track width
|
|
27
34
|
|
|
28
35
|
`--toggle-switch-track-width` overrides the track's width directly. Left unset, the track derives
|
|
@@ -64,3 +71,25 @@ fixed width independent of symbol size).
|
|
|
64
71
|
```vue
|
|
65
72
|
<ToggleSwitchCore id="notifications" name="notifications" style="--toggle-switch-symbol-surface-on: var(--gold-06);" />
|
|
66
73
|
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Migration notes (2026-09-23)
|
|
78
|
+
|
|
79
|
+
- **`round` prop was previously dead** — `ToggleSwitchWithLabel`/`ToggleSwitchWithLabelInline`
|
|
80
|
+
both accepted and forwarded it, but `ToggleSwitchCore` never declared the prop or read it, so
|
|
81
|
+
the Storybook `SquareShape` story rendered identically to `Default`. Fixed by adding `round` to
|
|
82
|
+
`ToggleSwitchCore` and wiring it to the new `--toggle-switch-border-radius` token (see Shape
|
|
83
|
+
above).
|
|
84
|
+
- **`fieldHasError` didn't visually theme the component** — `ToggleSwitchCore` and
|
|
85
|
+
`ToggleSwitchWithLabel` both computed an error-aware theme value but bound `data-theme` to the
|
|
86
|
+
raw `theme` prop instead, so setting `fieldHasError` never applied this library's
|
|
87
|
+
`[data-theme="error"]` theme-token overrides (`_error.css`). Fixed by binding `data-theme` to the
|
|
88
|
+
computed value.
|
|
89
|
+
- Custom `iconOn`/`iconOff` slot content could render as a non-square box (e.g. a 16×16 SVG
|
|
90
|
+
rendering as ~16×20), throwing off centering inside the thumb — fixed by adding
|
|
91
|
+
`line-height: 0` to `.symbol-icon`, which collapses inline leading for any slotted content.
|
|
92
|
+
- Two dead, unread `--_transition-duration` private locals were removed from
|
|
93
|
+
`ToggleSwitchWithLabel`/`ToggleSwitchWithLabelInline` — nothing in either file's CSS or
|
|
94
|
+
`ToggleSwitchCore`'s ever read them (the actual transition durations are hardcoded `0.4s`
|
|
95
|
+
literals in `ToggleSwitchCore`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="toggle-switch-core" :class="elementClasses" :data-theme="
|
|
3
|
-
<div class="toggle-switch-wrapper" :class="wrapperClasses"
|
|
2
|
+
<div class="toggle-switch-core" :class="elementClasses" :data-theme="formUiTheme">
|
|
3
|
+
<div class="toggle-switch-wrapper" :class="wrapperClasses" @click="toggleSwitchValue">
|
|
4
4
|
<input
|
|
5
5
|
:id="inputId"
|
|
6
6
|
v-model="modelValue"
|
|
@@ -44,6 +44,7 @@ interface Props {
|
|
|
44
44
|
falseValue?: string | number | boolean;
|
|
45
45
|
styleClassPassthrough?: string | string[];
|
|
46
46
|
theme?: FormUiTheme;
|
|
47
|
+
round?: boolean;
|
|
47
48
|
ariaDescribedby?: string;
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -54,17 +55,20 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
54
55
|
falseValue: false,
|
|
55
56
|
styleClassPassthrough: () => [],
|
|
56
57
|
theme: "default",
|
|
58
|
+
round: true,
|
|
57
59
|
ariaDescribedby: "",
|
|
58
60
|
});
|
|
59
61
|
|
|
60
62
|
const slots = useSlots();
|
|
61
63
|
const useDefaultIcons = computed(() => !slots.iconOn && !slots.iconOff);
|
|
62
64
|
|
|
63
|
-
const
|
|
65
|
+
const formUiTheme = computed(() => {
|
|
64
66
|
return props.fieldHasError ? "error" : props.theme;
|
|
65
67
|
});
|
|
66
68
|
|
|
67
|
-
const
|
|
69
|
+
const roundedRadiusDefault = computed(() => (props.round ? "100vw" : "0.4rem"));
|
|
70
|
+
|
|
71
|
+
const modelValue = defineModel<string | number | boolean>({ required: true });
|
|
68
72
|
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
69
73
|
|
|
70
74
|
const inputId = computed(() => `toggle-switch-${props.id}`);
|
|
@@ -90,156 +94,153 @@ const toggleSwitchValue = () => {
|
|
|
90
94
|
|
|
91
95
|
<style lang="css">
|
|
92
96
|
@layer components {
|
|
93
|
-
.toggle-switch-core {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
.toggle-switch-core {
|
|
98
|
+
.toggle-switch-label {
|
|
99
|
+
display: block;
|
|
100
|
+
}
|
|
97
101
|
|
|
98
|
-
|
|
99
|
-
|
|
102
|
+
.toggle-switch-wrapper {
|
|
103
|
+
/* --_icon-font-size, --_switch-padding, --_toggle-symbol-border-width are the only locals
|
|
100
104
|
actually read anywhere below — --_icon-on-opacity, --_icon-off-opacity,
|
|
101
105
|
--_symbol-background-color, --_symbol-margin-inline-start, --_symbol-checked-offset were
|
|
102
106
|
declared here but never referenced by any property in this file; removed as dead code
|
|
103
107
|
rather than migrated, since migrating an unread token would just create a new unread
|
|
104
108
|
public one. */
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
--_icon-font-size: 2.4rem;
|
|
110
|
+
--_switch-padding: 0.2rem;
|
|
111
|
+
--_toggle-symbol-border-width: 0.1rem;
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
/* Public --toggle-switch-* tokens, inline-fallback to the shared --theme-* tokens (see
|
|
110
114
|
theming-component-token-pattern.md) — overriding one here doesn't touch every other
|
|
111
115
|
themed input/control that also reads --theme-checkbox-symbol-surface/--theme-border. */
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
116
|
+
--_surface: var(--toggle-switch-surface, var(--theme-checkbox-symbol-surface));
|
|
117
|
+
--_surface-hover: var(--toggle-switch-surface-hover, var(--theme-surface-subtle));
|
|
118
|
+
--_border: var(--toggle-switch-border, var(--theme-border));
|
|
119
|
+
--_border-focus: var(--toggle-switch-border-focus, var(--theme-border-focus));
|
|
120
|
+
--_border-radius: var(--toggle-switch-border-radius, v-bind(roundedRadiusDefault));
|
|
121
|
+
|
|
122
|
+
display: flex;
|
|
123
|
+
flex-direction: column;
|
|
124
|
+
|
|
125
|
+
input {
|
|
126
|
+
height: 0;
|
|
127
|
+
width: 0;
|
|
128
|
+
opacity: 0;
|
|
129
|
+
|
|
130
|
+
&:focus-visible {
|
|
131
|
+
+ .symbol-wrapper {
|
|
132
|
+
outline: var(--form-element-outline-width-focus) solid var(--_border-focus);
|
|
133
|
+
outline-offset: var(--form-element-outline-offset-focus);
|
|
134
|
+
}
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
|
-
}
|
|
132
137
|
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
.symbol-wrapper {
|
|
139
|
+
/* Geometry */
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
/* Track width has no direct public token — it's derived from the same geometry tokens
|
|
137
142
|
that size the thumb, so the track always scales with --input-toggle-symbol-size instead
|
|
138
143
|
of clipping/floating it. Breakdown at the default 0.1rem tokens (= 72px total):
|
|
139
144
|
2×symbol-size (6rem) + 2×form-element-border-width (0.2rem, wrapper border) +
|
|
140
145
|
2×wrapper-padding (0.2rem) + 3×symbol-outline-width (0.3rem) +
|
|
141
146
|
3×symbol-border-width (0.3rem) + 2×symbol-margin (0.2rem). Override
|
|
142
147
|
--toggle-switch-track-width directly if you need a value the formula doesn't produce. */
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
/* UI */
|
|
164
|
-
background-color: var(--_surface);
|
|
165
|
-
border: var(--form-element-border-width) solid var(--_border);
|
|
166
|
-
outline: var(--form-element-outline-width) solid transparent;
|
|
167
|
-
border-radius: 100vw;
|
|
168
|
-
width: var(--_track-width);
|
|
169
|
-
padding: calc(var(--input-toggle-wrapper-padding) + var(--input-toggle-symbol-outline-width));
|
|
170
|
-
|
|
171
|
-
&:hover {
|
|
172
|
-
background-color: var(--_surface-hover);
|
|
173
|
-
cursor: pointer;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.symbol {
|
|
177
|
-
/* Geometry */
|
|
178
|
-
|
|
179
|
-
display: inline-grid;
|
|
180
|
-
grid-template-areas: "icon";
|
|
181
|
-
place-content: center;
|
|
182
|
-
/* position: absolute; */
|
|
183
|
-
overflow: hidden;
|
|
184
|
-
translate: 0 0;
|
|
185
|
-
|
|
186
|
-
aspect-ratio: 1/1;
|
|
148
|
+
--_track-width: var(
|
|
149
|
+
--toggle-switch-track-width,
|
|
150
|
+
calc(
|
|
151
|
+
(2 * var(--input-toggle-symbol-size)) + (2 * var(--form-element-border-width)) +
|
|
152
|
+
(2 * var(--input-toggle-wrapper-padding)) + (3 * var(--input-toggle-symbol-outline-width)) +
|
|
153
|
+
(3 * var(--input-toggle-symbol-border-width)) + (2 * var(--input-toggle-symbol-margin))
|
|
154
|
+
)
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
display: inline-flex;
|
|
158
|
+
align-items: center;
|
|
159
|
+
justify-content: start;
|
|
160
|
+
position: relative;
|
|
161
|
+
transition:
|
|
162
|
+
background-color var(--theme-form-transition-duration) linear,
|
|
163
|
+
border-color var(--theme-form-transition-duration) linear,
|
|
164
|
+
outline var(--theme-form-transition-duration) linear,
|
|
165
|
+
outline-offset var(--theme-form-transition-duration) linear,
|
|
166
|
+
outline var(--theme-form-transition-duration) linear;
|
|
187
167
|
|
|
188
168
|
/* UI */
|
|
189
|
-
|
|
190
|
-
border: var(--
|
|
191
|
-
outline: var(--
|
|
192
|
-
border-radius:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
background-color: var(--toggle-switch-symbol-surface-on, var(--theme-surface));
|
|
200
|
-
/* left: calc(
|
|
201
|
-
100% - var(--input-toggle-symbol-size) - var(--_switch-padding) - (2 * var(--_toggle-symbol-border-width))
|
|
202
|
-
); */
|
|
203
|
-
/* translate: calc(var(--input-toggle-symbol-size) / 2) 0; */
|
|
204
|
-
/* translate: 1.6rem 0; */
|
|
205
|
-
translate: calc(
|
|
206
|
-
var(--input-toggle-symbol-size) + var(--input-toggle-symbol-border-width) +
|
|
207
|
-
var(--input-toggle-symbol-outline-width)
|
|
208
|
-
)
|
|
209
|
-
0;
|
|
169
|
+
background-color: var(--_surface);
|
|
170
|
+
border: var(--form-element-border-width) solid var(--_border);
|
|
171
|
+
outline: var(--form-element-outline-width) solid transparent;
|
|
172
|
+
border-radius: var(--_border-radius);
|
|
173
|
+
width: var(--_track-width);
|
|
174
|
+
padding: calc(var(--input-toggle-wrapper-padding) + var(--input-toggle-symbol-outline-width));
|
|
175
|
+
|
|
176
|
+
&:hover {
|
|
177
|
+
background-color: var(--_surface-hover);
|
|
178
|
+
cursor: pointer;
|
|
210
179
|
}
|
|
211
180
|
|
|
212
|
-
.symbol
|
|
181
|
+
.symbol {
|
|
213
182
|
/* Geometry */
|
|
214
183
|
|
|
215
|
-
display: grid;
|
|
216
|
-
grid-
|
|
184
|
+
display: inline-grid;
|
|
185
|
+
grid-template-areas: "icon";
|
|
217
186
|
place-content: center;
|
|
218
|
-
|
|
187
|
+
overflow: hidden;
|
|
188
|
+
translate: 0 0;
|
|
189
|
+
|
|
190
|
+
aspect-ratio: 1/1;
|
|
219
191
|
|
|
220
192
|
/* UI */
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
/* padding: calc(calc(var(--input-toggle-symbol-size) - var(--_icon-font-size)) / 2); */
|
|
194
|
+
border: var(--input-toggle-symbol-border-width) solid var(--toggle-switch-symbol-border, var(--theme-text));
|
|
195
|
+
outline: var(--input-toggle-symbol-outline-width) solid transparent;
|
|
196
|
+
border-radius: var(--_border-radius);
|
|
197
|
+
background-color: var(--toggle-switch-symbol-surface-off, var(--theme-on-surface));
|
|
224
198
|
transition:
|
|
225
|
-
|
|
226
|
-
color
|
|
227
|
-
|
|
228
|
-
&.
|
|
229
|
-
color: var(--toggle-switch-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
199
|
+
translate 0.4s ease,
|
|
200
|
+
background-color 0.4s linear;
|
|
201
|
+
|
|
202
|
+
&.checked {
|
|
203
|
+
background-color: var(--toggle-switch-symbol-surface-on, var(--theme-surface));
|
|
204
|
+
translate: calc(
|
|
205
|
+
var(--input-toggle-symbol-size) + var(--input-toggle-symbol-border-width) +
|
|
206
|
+
var(--input-toggle-symbol-outline-width)
|
|
207
|
+
)
|
|
208
|
+
0;
|
|
234
209
|
}
|
|
235
210
|
|
|
236
|
-
|
|
237
|
-
|
|
211
|
+
.symbol-icon {
|
|
212
|
+
/* Geometry */
|
|
213
|
+
|
|
214
|
+
display: grid;
|
|
215
|
+
grid-area: icon;
|
|
216
|
+
place-content: center;
|
|
217
|
+
/* Removes line-box leading so slotted icon content sizes to its own intrinsic height. */
|
|
218
|
+
line-height: 0;
|
|
219
|
+
opacity: 0;
|
|
220
|
+
|
|
221
|
+
/* UI */
|
|
222
|
+
width: var(--input-toggle-symbol-size);
|
|
223
|
+
height: var(--input-toggle-symbol-size);
|
|
224
|
+
margin: var(--input-toggle-symbol-margin);
|
|
225
|
+
transition:
|
|
226
|
+
opacity var(--theme-form-transition-duration),
|
|
227
|
+
color var(--theme-form-transition-duration);
|
|
228
|
+
|
|
229
|
+
&.icon-on {
|
|
230
|
+
color: var(--toggle-switch-icon-on-color, var(--theme-on-surface));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
&.icon-off {
|
|
234
|
+
color: var(--toggle-switch-icon-off-color, var(--theme-surface));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
&.active {
|
|
238
|
+
opacity: 1;
|
|
239
|
+
}
|
|
238
240
|
}
|
|
239
241
|
}
|
|
240
242
|
}
|
|
241
243
|
}
|
|
242
244
|
}
|
|
243
245
|
}
|
|
244
|
-
}
|
|
245
246
|
</style>
|
|
@@ -75,7 +75,7 @@ export default {
|
|
|
75
75
|
// Styling
|
|
76
76
|
theme: {
|
|
77
77
|
control: { type: "select" },
|
|
78
|
-
options: ["
|
|
78
|
+
options: ["default", "success", "error", "warning"],
|
|
79
79
|
description: "Toggle switch theme",
|
|
80
80
|
table: {
|
|
81
81
|
category: "Styling",
|
|
@@ -83,7 +83,7 @@ export default {
|
|
|
83
83
|
// Styling
|
|
84
84
|
theme: {
|
|
85
85
|
control: { type: "select" },
|
|
86
|
-
options: ["
|
|
86
|
+
options: ["default", "success", "error", "warning"],
|
|
87
87
|
description: "Toggle switch theme",
|
|
88
88
|
table: {
|
|
89
89
|
category: "Styling",
|
package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts
CHANGED
|
@@ -64,7 +64,7 @@ export default {
|
|
|
64
64
|
// Styling
|
|
65
65
|
theme: {
|
|
66
66
|
control: { type: "select" },
|
|
67
|
-
options: ["
|
|
67
|
+
options: ["default", "success", "error", "warning"],
|
|
68
68
|
description: "Toggle switch theme",
|
|
69
69
|
table: {
|
|
70
70
|
category: "Styling",
|
|
@@ -243,7 +243,7 @@ export const InlineFormExample: StoryFn = () => ({
|
|
|
243
243
|
name="darkMode"
|
|
244
244
|
label="Dark mode"
|
|
245
245
|
label-weight="normal"
|
|
246
|
-
theme="
|
|
246
|
+
theme="default"
|
|
247
247
|
/>
|
|
248
248
|
|
|
249
249
|
<StorybookComponent
|