srcdev-nuxt-components 9.6.8 → 9.6.10
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/skills/component-compliance-checklist.md +28 -1
- package/.claude/skills/component-inline-action-button.md +1 -1
- package/.claude/skills/component-local-style-override.md +1 -1
- package/.claude/skills/component-naming.md +17 -12
- package/.claude/skills/components/container-glow.md +2 -2
- package/.claude/skills/components/form-field.md +2 -2
- package/.claude/skills/components/form-wrapper.md +1 -1
- package/.claude/skills/components/glowing-border.md +1 -1
- package/.claude/skills/components/input-description.md +7 -7
- package/.claude/skills/components/input-error.md +3 -3
- package/.claude/skills/components/input-label.md +7 -8
- package/.claude/skills/components/input-number.md +17 -17
- package/.claude/skills/components/input-select.md +153 -0
- package/.claude/skills/components/input-text.md +220 -0
- package/.claude/skills/components/input-textarea.md +147 -0
- package/.claude/skills/components/select-menu.md +4 -4
- package/.claude/skills/components/toggle-switch.md +143 -0
- package/.claude/skills/composable-zod-validation.md +1 -1
- package/.claude/skills/css-nesting-conventions.md +22 -1
- package/.claude/skills/icon-sets.md +1 -1
- package/.claude/skills/icon-sizing.md +1 -1
- package/.claude/skills/index.md +5 -5
- package/.claude/skills/storybook-add-story.md +1 -1
- package/.claude/skills/theming-component-token-pattern.md +8 -8
- package/.claude/skills/theming-form-geometry-tokens.md +1 -1
- package/.vscode/srcdev-component-input-select.code-snippets +20 -14
- package/.vscode/srcdev-component-input-text.code-snippets +46 -40
- package/.vscode/srcdev-component-input-textarea.code-snippets +19 -14
- package/.vscode/srcdev-component-toggle-switch.code-snippets +19 -29
- package/app/assets/styles/setup/04.elements/forms/00.element-defaults.css +2 -2
- package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
- package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +2 -2
- package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +4 -4
- package/app/components/02.molecules/progress-tracker/stories/ProgressTracker.stories.ts +4 -4
- package/app/components/05.forms/form-errors/CONSUMER-STYLING.md +1 -1
- package/app/components/05.forms/form-field/CONSUMER-STYLING.md +2 -2
- package/app/components/05.forms/input-button/stories/InputButton.stories.ts +3 -3
- package/app/components/05.forms/input-description/CONSUMER-STYLING.md +6 -6
- package/app/components/05.forms/input-label/CONSUMER-STYLING.md +7 -7
- package/app/components/05.forms/input-number/CONSUMER-STYLING.md +9 -5
- package/app/components/05.forms/input-number/InputNumber.vue +2 -2
- package/app/components/05.forms/input-select/CONSUMER-STYLING.md +80 -10
- package/app/components/05.forms/input-select/InputSelect.vue +198 -0
- package/app/components/05.forms/input-select/InputSelectField.vue +130 -0
- package/app/components/05.forms/input-select/stories/InputSelect.stories.ts +184 -0
- package/app/components/05.forms/input-select/stories/InputSelectField.stories.ts +187 -0
- package/app/components/05.forms/input-select/tests/{InputSelectCore.spec.ts → InputSelect.spec.ts} +75 -12
- package/app/components/05.forms/input-select/tests/InputSelectField.spec.ts +121 -0
- package/app/components/05.forms/input-text/CONSUMER-STYLING.md +85 -15
- package/app/components/05.forms/input-text/{InputPasswordWithLabel.vue → InputPasswordField.vue} +16 -19
- package/app/components/05.forms/input-text/{InputTextCore.vue → InputText.vue} +42 -78
- package/app/components/05.forms/input-text/{InputTextAsNumberWithLabel.vue → InputTextAsNumberField.vue} +66 -62
- package/app/components/05.forms/input-text/InputTextField.vue +168 -0
- package/app/components/05.forms/input-text/stories/InputPasswordField.stories.ts +163 -0
- package/app/components/05.forms/input-text/stories/InputText.stories.ts +194 -0
- package/app/components/05.forms/input-text/stories/InputTextAsNumberField.stories.ts +182 -0
- package/app/components/05.forms/input-text/stories/InputTextField.stories.ts +206 -0
- package/app/components/05.forms/input-text/tests/{InputPasswordWithLabel.spec.ts → InputPasswordField.spec.ts} +42 -3
- package/app/components/05.forms/input-text/tests/InputText.spec.ts +166 -0
- package/app/components/05.forms/input-text/tests/InputTextAsNumberField.spec.ts +135 -0
- package/app/components/05.forms/input-text/tests/InputTextField.spec.ts +130 -0
- package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +94 -12
- package/app/components/05.forms/input-textarea/InputTextarea.vue +165 -0
- package/app/components/05.forms/input-textarea/InputTextareaField.vue +159 -0
- package/app/components/05.forms/input-textarea/stories/InputTextarea.stories.ts +198 -0
- package/app/components/05.forms/input-textarea/stories/InputTextareaField.stories.ts +161 -0
- package/app/components/05.forms/input-textarea/tests/InputTextarea.spec.ts +149 -0
- package/app/components/05.forms/input-textarea/tests/InputTextareaField.spec.ts +122 -0
- package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +13 -13
- package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +6 -6
- package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +30 -32
- package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +71 -50
- package/app/components/05.forms/toggle-switch/{ToggleSwitchCore.vue → ToggleSwitch.vue} +58 -73
- package/app/components/05.forms/toggle-switch/{ToggleSwitchWithLabel.vue → ToggleSwitchField.vue} +65 -19
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitch.stories.ts +148 -0
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchField.stories.ts +176 -0
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitch.spec.ts +145 -0
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitchField.spec.ts +155 -0
- package/package.json +1 -1
- package/.claude/skills/components/input-select-core.md +0 -151
- package/.claude/skills/components/input-text-core.md +0 -204
- package/.claude/skills/components/input-textarea-core.md +0 -154
- package/.claude/skills/components/toggle-switch-core.md +0 -169
- package/app/components/05.forms/input-select/InputSelectCore.vue +0 -188
- package/app/components/05.forms/input-select/InputSelectWithLabel.vue +0 -118
- package/app/components/05.forms/input-select/stories/InputSelectCore.stories.ts +0 -69
- package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +0 -115
- package/app/components/05.forms/input-select/tests/InputSelectWithLabel.spec.ts +0 -87
- package/app/components/05.forms/input-text/InputTextWithLabel.vue +0 -154
- package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +0 -368
- package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +0 -480
- package/app/components/05.forms/input-text/stories/InputTextCore.stories.ts +0 -267
- package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +0 -319
- package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +0 -75
- package/app/components/05.forms/input-text/tests/InputTextCore.spec.ts +0 -60
- package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +0 -71
- package/app/components/05.forms/input-textarea/InputTextareaCore.vue +0 -159
- package/app/components/05.forms/input-textarea/InputTextareaWithLabel.vue +0 -136
- package/app/components/05.forms/input-textarea/stories/InputTextareaCore.stories.ts +0 -247
- package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +0 -458
- package/app/components/05.forms/input-textarea/tests/InputTextareaCore.spec.ts +0 -119
- package/app/components/05.forms/input-textarea/tests/InputTextareaWithLabel.spec.ts +0 -93
- package/app/components/05.forms/toggle-switch/ToggleSwitchWithLabelInline.vue +0 -81
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchCore.stories.ts +0 -251
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +0 -251
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +0 -283
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitchCore.spec.ts +0 -101
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitchWithLabel.spec.ts +0 -133
- package/app/components/05.forms/toggle-switch/tests/ToggleSwitchWithLabelInline.spec.ts +0 -66
|
@@ -181,7 +181,7 @@ Playwright `STORY_BASE` slug. The slug is derived by lowercasing and replacing s
|
|
|
181
181
|
| Title | STORY_BASE slug |
|
|
182
182
|
| --------------------------------------------- | ------------------------------------------- |
|
|
183
183
|
| `"Atoms/Text Blocks/HeroText"` | `atoms-text-blocks-herotext` |
|
|
184
|
-
| `"Components/Forms/Input Text/
|
|
184
|
+
| `"Components/Forms/Input Text/InputText"` | `components-forms-input-text-inputtext` |
|
|
185
185
|
|
|
186
186
|
## argTypes control types
|
|
187
187
|
|
|
@@ -25,7 +25,7 @@ overrides (2026-08-25):
|
|
|
25
25
|
signalled that to the consumer — the app's declaration became permanently dead, silently. A
|
|
26
26
|
`var()` with an undefined custom property and no fallback just resolves to the property's
|
|
27
27
|
initial value; there is no error, no warning, ever.
|
|
28
|
-
2. **Tokens that were "shared" only by accident.** `
|
|
28
|
+
2. **Tokens that were "shared" only by accident.** `InputText`, `InputSelect`,
|
|
29
29
|
`InputNumber` and the checkbox button all read the exact same `--theme-input-surface`, so a
|
|
30
30
|
consumer wanting to restyle just text inputs had no way to do that without also restyling every
|
|
31
31
|
other input type. The private `--_input-text-surface: var(--theme-input-surface);` indirection
|
|
@@ -208,27 +208,27 @@ consuming app having declared anything.
|
|
|
208
208
|
Pure token-rename pass, no visual/default changes (unlike `InputButton`'s redesign above).
|
|
209
209
|
Added Storybook stories for both (`InputCheckboxRadio`, `InputCheckboxRadioButton`) —
|
|
210
210
|
neither had one before.
|
|
211
|
-
- ✅ `
|
|
212
|
-
`CONSUMER-STYLING.md`. `
|
|
211
|
+
- ✅ `InputText`, `InputSelect`, `InputNumber` — migrated 2026-08-25, see their
|
|
212
|
+
`CONSUMER-STYLING.md`. `InputText`/`InputSelect` also had this exact problem's original
|
|
213
213
|
form: a private `--_input-text-*`/`--_input-select-*` naming scheme documented as a second
|
|
214
214
|
"local override path" alongside the global tokens, added 2026-08-22 (three days before this
|
|
215
215
|
pattern was formalised) as a workaround for a global-override-not-landing report that was never
|
|
216
216
|
root-caused. That private-var-as-override-point shape is exactly what this pattern replaces —
|
|
217
217
|
renamed public with real fallbacks, old two-path docs removed. `InputNumber` had no
|
|
218
218
|
component-scoped tokens at all before this (bare `--theme-input-*` throughout). Added a
|
|
219
|
-
Storybook story for `
|
|
220
|
-
`
|
|
219
|
+
Storybook story for `InputSelect` (didn't have one); `InputNumber` still doesn't.
|
|
220
|
+
`InputText`/`InputSelect`'s `.normal` variant also had hover and `:focus-visible` share
|
|
221
221
|
one token (literally the same rule content duplicated under two selectors) — split into
|
|
222
222
|
`--input-text-border-hover`/`--input-select-border-hover` alongside the existing `-border-focus`
|
|
223
223
|
pair, both still defaulting to `--theme-border-focus` so default rendering is unchanged, but
|
|
224
224
|
mouse and assistive-tech interaction can now be themed independently. `InputNumber` has no
|
|
225
225
|
hover state on its border at all (only a `:focus-visible` box-shadow toggle), so there was
|
|
226
226
|
nothing to split there.
|
|
227
|
-
- ✅ `
|
|
227
|
+
- ✅ `ToggleSwitch`, `TripleToggleSwitch`, `DisplayThemeSwitch` — migrated 2026-08-25, see
|
|
228
228
|
the first two's `CONSUMER-STYLING.md`. Correction to the two lines this replaces: they claimed
|
|
229
|
-
`
|
|
229
|
+
`ToggleSwitch` read a bare `--theme-toggle-symbol-color-*` — that token doesn't exist
|
|
230
230
|
anywhere in this codebase and never did; false memory from conflating it with the checkbox
|
|
231
|
-
fix. `
|
|
231
|
+
fix. `ToggleSwitch` itself turned out to be a plain Tier 2 case (real, live tokens, just no
|
|
232
232
|
component-scoped override point) plus five confirmed-dead private locals (declared, never read
|
|
233
233
|
anywhere in the file) removed outright. The real dead-token bug was in `TripleToggleSwitch`
|
|
234
234
|
(and duplicated in `DisplayThemeSwitch`'s own override): `--theme-form-radio-border`,
|
|
@@ -51,7 +51,7 @@ From `00.element-defaults.css` through `09.animation-motion.css`:
|
|
|
51
51
|
|
|
52
52
|
`00.element-defaults.css` is the one exception — it's not tokens, it's a real selector-based rule
|
|
53
53
|
(browser autofill background/text-colour reset via `input:autofill` etc.). It reads
|
|
54
|
-
`var(--theme-surface)` and the component-private `--_input-text-
|
|
54
|
+
`var(--theme-surface)` and the component-private `--_input-text-color`, so changing
|
|
55
55
|
`--theme-surface` (per `theming-partial-override.md`) changes autofill colours too — no separate
|
|
56
56
|
override needed there. If you need to change that rule's *behaviour* itself (not just its colour
|
|
57
57
|
inputs), you'd need a competing unlayered selector of your own targeting the same pseudo-classes,
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"SRCDEV
|
|
3
|
-
"description": "Basic
|
|
2
|
+
"SRCDEV InputSelect Basic": {
|
|
3
|
+
"description": "Basic InputSelect native select (no label/error wrapper)",
|
|
4
4
|
"scope": "vue,html",
|
|
5
5
|
"body": [
|
|
6
|
-
"<
|
|
6
|
+
"<InputSelect",
|
|
7
7
|
" id=\"$1fieldId\"",
|
|
8
|
-
"
|
|
9
|
-
" v-model=\"$
|
|
10
|
-
"
|
|
8
|
+
" v-model=\"$2fieldValue\"",
|
|
9
|
+
" v-model:field-data=\"$3fieldOptions\"",
|
|
10
|
+
" name=\"$4fieldName\"",
|
|
11
11
|
" placeholder=\"$5Choose an option\"",
|
|
12
12
|
"/>"
|
|
13
13
|
]
|
|
14
14
|
},
|
|
15
|
-
"SRCDEV
|
|
16
|
-
"description": "
|
|
15
|
+
"SRCDEV InputSelectField Basic": {
|
|
16
|
+
"description": "InputSelectField: labelled select with description and error support",
|
|
17
17
|
"scope": "vue,html",
|
|
18
18
|
"body": [
|
|
19
|
-
"<
|
|
19
|
+
"<InputSelectField",
|
|
20
20
|
" v-model=\"$1fieldValue\"",
|
|
21
21
|
" v-model:field-data=\"$2fieldOptions\"",
|
|
22
22
|
" name=\"$3fieldName\"",
|
|
@@ -24,17 +24,23 @@
|
|
|
24
24
|
" placeholder=\"$5Choose an option\"",
|
|
25
25
|
" :error-message=\"$6errors.fieldName\"",
|
|
26
26
|
" :field-has-error=\"!!$6errors.fieldName\"",
|
|
27
|
-
"
|
|
27
|
+
">",
|
|
28
|
+
" <template #descriptionText>$7</template>",
|
|
29
|
+
"</InputSelectField>"
|
|
28
30
|
]
|
|
29
31
|
},
|
|
30
32
|
"SRCDEV InputSelect CSS Override": {
|
|
31
|
-
"description": "CSS override scaffold for
|
|
33
|
+
"description": "CSS override scaffold for InputSelect tokens",
|
|
32
34
|
"scope": "css",
|
|
33
35
|
"body": [
|
|
34
36
|
".$1my-page {",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
37
|
+
" --input-select-surface: $2;",
|
|
38
|
+
" --input-select-text-color: $3;",
|
|
39
|
+
" --input-select-border: $4;",
|
|
40
|
+
" --input-select-border-focus: $5;",
|
|
41
|
+
"",
|
|
42
|
+
" .input-select-field[data-invalid] {",
|
|
43
|
+
" $0",
|
|
38
44
|
" }",
|
|
39
45
|
"}"
|
|
40
46
|
]
|
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
"SRCDEV
|
|
3
|
-
"description": "Basic
|
|
2
|
+
"SRCDEV InputText Basic": {
|
|
3
|
+
"description": "Basic InputText native input (no label/error wrapper)",
|
|
4
4
|
"scope": "vue,html",
|
|
5
5
|
"body": [
|
|
6
|
-
"<
|
|
6
|
+
"<InputText",
|
|
7
7
|
" id=\"$1fieldId\"",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
" v-model=\"$2fieldValue\"",
|
|
9
|
+
" name=\"$3fieldName\"",
|
|
10
10
|
" type=\"$4text\"",
|
|
11
|
-
" placeholder=\"$5Enter value
|
|
11
|
+
" placeholder=\"$5Enter value\"",
|
|
12
12
|
"/>"
|
|
13
13
|
]
|
|
14
14
|
},
|
|
15
|
-
"SRCDEV
|
|
16
|
-
"description": "
|
|
15
|
+
"SRCDEV InputText Date with min/max": {
|
|
16
|
+
"description": "InputText date input constrained to a min/max range (e.g. no dates in the past)",
|
|
17
17
|
"scope": "vue,html",
|
|
18
18
|
"body": [
|
|
19
|
-
"<
|
|
19
|
+
"<InputText",
|
|
20
20
|
" id=\"$1appointment-date\"",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
" v-model=\"$2appointmentDate\"",
|
|
22
|
+
" name=\"$3appointmentDate\"",
|
|
23
23
|
" type=\"date\"",
|
|
24
24
|
" :min=\"new Date().toISOString().split('T')[0]\"",
|
|
25
25
|
" max=\"$42027-12-31\"",
|
|
26
26
|
"/>"
|
|
27
27
|
]
|
|
28
28
|
},
|
|
29
|
-
"SRCDEV
|
|
30
|
-
"description": "
|
|
29
|
+
"SRCDEV InputTextField Basic": {
|
|
30
|
+
"description": "InputTextField: labelled text field with description and error support",
|
|
31
31
|
"scope": "vue,html",
|
|
32
32
|
"body": [
|
|
33
|
-
"<
|
|
33
|
+
"<InputTextField",
|
|
34
34
|
" v-model=\"$1fieldValue\"",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
35
|
+
" name=\"$2fieldName\"",
|
|
36
|
+
" type=\"${3|text,email,tel,url,date,number|}\"",
|
|
37
|
+
" label=\"$4Field label\"",
|
|
38
|
+
" autocomplete=\"$5\"",
|
|
39
39
|
" :error-message=\"$6errors.fieldName\"",
|
|
40
40
|
" :field-has-error=\"!!$6errors.fieldName\"",
|
|
41
|
-
"
|
|
41
|
+
">",
|
|
42
|
+
" <template #descriptionText>$7</template>",
|
|
43
|
+
"</InputTextField>"
|
|
42
44
|
]
|
|
43
45
|
},
|
|
44
|
-
"SRCDEV
|
|
45
|
-
"description": "
|
|
46
|
+
"SRCDEV InputTextField Date with min/max": {
|
|
47
|
+
"description": "InputTextField date field constrained to a min/max range",
|
|
46
48
|
"scope": "vue,html",
|
|
47
49
|
"body": [
|
|
48
|
-
"<
|
|
50
|
+
"<InputTextField",
|
|
49
51
|
" v-model=\"$1appointmentDate\"",
|
|
50
|
-
" id=\"$2appointment-date\"",
|
|
51
52
|
" name=\"$2appointmentDate\"",
|
|
52
53
|
" type=\"date\"",
|
|
53
54
|
" label=\"$3Appointment date\"",
|
|
@@ -58,24 +59,27 @@
|
|
|
58
59
|
"/>"
|
|
59
60
|
]
|
|
60
61
|
},
|
|
61
|
-
"SRCDEV
|
|
62
|
-
"description": "
|
|
62
|
+
"SRCDEV InputPasswordField": {
|
|
63
|
+
"description": "InputPasswordField with show/hide toggle",
|
|
63
64
|
"scope": "vue,html",
|
|
64
65
|
"body": [
|
|
65
|
-
"<
|
|
66
|
+
"<InputPasswordField",
|
|
66
67
|
" v-model=\"$1password\"",
|
|
67
68
|
" name=\"$2password\"",
|
|
68
69
|
" label=\"$3Password\"",
|
|
69
|
-
"
|
|
70
|
-
" :
|
|
70
|
+
" autocomplete=\"${4|current-password,new-password|}\"",
|
|
71
|
+
" :error-message=\"$5errors.password\"",
|
|
72
|
+
" :field-has-error=\"!!$5errors.password\"",
|
|
73
|
+
" show-password-text=\"$6Show password\"",
|
|
74
|
+
" hide-password-text=\"$7Hide password\"",
|
|
71
75
|
"/>"
|
|
72
76
|
]
|
|
73
77
|
},
|
|
74
|
-
"SRCDEV
|
|
75
|
-
"description": "
|
|
78
|
+
"SRCDEV InputTextAsNumberField": {
|
|
79
|
+
"description": "InputTextAsNumberField numeric stepper with min/max/step",
|
|
76
80
|
"scope": "vue,html",
|
|
77
81
|
"body": [
|
|
78
|
-
"<
|
|
82
|
+
"<InputTextAsNumberField",
|
|
79
83
|
" v-model=\"$1quantity\"",
|
|
80
84
|
" name=\"$2quantity\"",
|
|
81
85
|
" label=\"$3Quantity\"",
|
|
@@ -85,21 +89,23 @@
|
|
|
85
89
|
" :error-message=\"$7errors.quantity\"",
|
|
86
90
|
" :field-has-error=\"!!$7errors.quantity\"",
|
|
87
91
|
">",
|
|
88
|
-
" <template #left
|
|
89
|
-
" <template #right
|
|
90
|
-
"</
|
|
92
|
+
" <template #left><Icon name=\"mdi:minus\" /></template>",
|
|
93
|
+
" <template #right><Icon name=\"mdi:plus\" /></template>",
|
|
94
|
+
"</InputTextAsNumberField>"
|
|
91
95
|
]
|
|
92
96
|
},
|
|
93
97
|
"SRCDEV InputText CSS Override": {
|
|
94
|
-
"description": "CSS override scaffold for
|
|
98
|
+
"description": "CSS override scaffold for InputText tokens",
|
|
95
99
|
"scope": "css",
|
|
96
100
|
"body": [
|
|
97
101
|
".$1my-page {",
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
102
|
+
" --input-text-surface: $2;",
|
|
103
|
+
" --input-text-border: $3;",
|
|
104
|
+
" --input-text-border-focus: $4;",
|
|
105
|
+
" --input-text-color: $5;",
|
|
106
|
+
"",
|
|
107
|
+
" .input-text-field[data-invalid] {",
|
|
108
|
+
" $0",
|
|
103
109
|
" }",
|
|
104
110
|
"}"
|
|
105
111
|
]
|
|
@@ -1,38 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
-
"SRCDEV
|
|
3
|
-
"description": "Basic
|
|
2
|
+
"SRCDEV InputTextarea Basic": {
|
|
3
|
+
"description": "Basic InputTextarea native textarea (no label/error wrapper)",
|
|
4
4
|
"scope": "vue,html",
|
|
5
5
|
"body": [
|
|
6
|
-
"<
|
|
6
|
+
"<InputTextarea",
|
|
7
7
|
" id=\"$1fieldId\"",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
" v-model=\"$2fieldValue\"",
|
|
9
|
+
" name=\"$3fieldName\"",
|
|
10
10
|
" placeholder=\"$4Placeholder text\"",
|
|
11
11
|
"/>"
|
|
12
12
|
]
|
|
13
13
|
},
|
|
14
|
-
"SRCDEV
|
|
15
|
-
"description": "
|
|
14
|
+
"SRCDEV InputTextareaField Basic": {
|
|
15
|
+
"description": "InputTextareaField: labelled textarea with description and error support",
|
|
16
16
|
"scope": "vue,html",
|
|
17
17
|
"body": [
|
|
18
|
-
"<
|
|
18
|
+
"<InputTextareaField",
|
|
19
19
|
" v-model=\"$1fieldValue\"",
|
|
20
20
|
" name=\"$2fieldName\"",
|
|
21
21
|
" label=\"$3Field label\"",
|
|
22
|
-
"
|
|
22
|
+
" :maxlength=\"${4:1000}\"",
|
|
23
23
|
" :error-message=\"$5errors.fieldName\"",
|
|
24
24
|
" :field-has-error=\"!!$5errors.fieldName\"",
|
|
25
|
-
"
|
|
25
|
+
">",
|
|
26
|
+
" <template #descriptionText>$6</template>",
|
|
27
|
+
"</InputTextareaField>"
|
|
26
28
|
]
|
|
27
29
|
},
|
|
28
30
|
"SRCDEV InputTextarea CSS Override": {
|
|
29
|
-
"description": "CSS override scaffold for
|
|
31
|
+
"description": "CSS override scaffold for InputTextarea tokens",
|
|
30
32
|
"scope": "css",
|
|
31
33
|
"body": [
|
|
32
34
|
".$1my-page {",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
35
|
+
" --input-textarea-surface: $2;",
|
|
36
|
+
" --input-textarea-border: $3;",
|
|
37
|
+
" --input-textarea-max-height: ${4:20lh};",
|
|
38
|
+
"",
|
|
39
|
+
" .input-textarea-field[data-invalid] {",
|
|
40
|
+
" $0",
|
|
36
41
|
" }",
|
|
37
42
|
"}"
|
|
38
43
|
]
|
|
@@ -1,50 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
"SRCDEV
|
|
3
|
-
"description": "
|
|
2
|
+
"SRCDEV ToggleSwitch": {
|
|
3
|
+
"description": "ToggleSwitch: bare switch (pair with a label for=\"toggle-switch-{id}\", or use ToggleSwitchField)",
|
|
4
4
|
"scope": "vue,html",
|
|
5
5
|
"body": [
|
|
6
|
-
"<
|
|
7
|
-
"
|
|
8
|
-
" id=\"$
|
|
9
|
-
"
|
|
6
|
+
"<label for=\"toggle-switch-$1toggle-id\">$2Label</label>",
|
|
7
|
+
"<ToggleSwitch",
|
|
8
|
+
" id=\"$1toggle-id\"",
|
|
9
|
+
" v-model=\"$3modelValue\"",
|
|
10
|
+
" name=\"$4toggleName\"",
|
|
10
11
|
"/>"
|
|
11
12
|
]
|
|
12
13
|
},
|
|
13
|
-
"SRCDEV
|
|
14
|
-
"description": "
|
|
14
|
+
"SRCDEV ToggleSwitchField": {
|
|
15
|
+
"description": "ToggleSwitchField: labelled switch with description and error support",
|
|
15
16
|
"scope": "vue,html",
|
|
16
17
|
"body": [
|
|
17
|
-
"<
|
|
18
|
+
"<ToggleSwitchField",
|
|
18
19
|
" v-model=\"$1fieldValue\"",
|
|
19
20
|
" name=\"$2fieldName\"",
|
|
20
21
|
" label=\"$3Field label\"",
|
|
21
|
-
"
|
|
22
|
-
" :
|
|
22
|
+
" layout=\"${4|stacked,inline|}\"",
|
|
23
|
+
" :error-message=\"$5errors.fieldName\"",
|
|
24
|
+
" :field-has-error=\"!!$5errors.fieldName\"",
|
|
23
25
|
">",
|
|
24
|
-
" <template #descriptionText>$
|
|
25
|
-
"</
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
"SRCDEV ToggleSwitchWithLabelInline": {
|
|
29
|
-
"description": "ToggleSwitchWithLabelInline: compact label + toggle switch side by side, no error support",
|
|
30
|
-
"scope": "vue,html",
|
|
31
|
-
"body": [
|
|
32
|
-
"<ToggleSwitchWithLabelInline",
|
|
33
|
-
" v-model=\"$1fieldValue\"",
|
|
34
|
-
" name=\"$2fieldName\"",
|
|
35
|
-
" label=\"$3Field label\"",
|
|
36
|
-
"/>"
|
|
26
|
+
" <template #descriptionText>$6Help text</template>",
|
|
27
|
+
"</ToggleSwitchField>"
|
|
37
28
|
]
|
|
38
29
|
},
|
|
39
30
|
"SRCDEV ToggleSwitch CSS Override": {
|
|
40
|
-
"description": "CSS override scaffold for
|
|
31
|
+
"description": "CSS override scaffold for ToggleSwitch tokens",
|
|
41
32
|
"scope": "css",
|
|
42
33
|
"body": [
|
|
43
34
|
".$1my-page {",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
" }",
|
|
35
|
+
" --toggle-switch-surface: $2;",
|
|
36
|
+
" --toggle-switch-symbol-surface-on: $3;",
|
|
37
|
+
" --input-toggle-symbol-size: ${4:2.4rem};",
|
|
48
38
|
"}"
|
|
49
39
|
]
|
|
50
40
|
}
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
input:-webkit-autofill-and-obscured {
|
|
12
12
|
background-color: var(--theme-surface) !important;
|
|
13
13
|
background-image: none !important;
|
|
14
|
-
color: var(--
|
|
14
|
+
color: var(--input-text-color, var(--theme-input-text-color-normal)) !important;
|
|
15
15
|
-webkit-box-shadow: 0 0 0rem 1000px var(--theme-surface) inset;
|
|
16
|
-
-webkit-text-fill-color: var(--
|
|
16
|
+
-webkit-text-fill-color: var(--input-text-color, var(--theme-input-text-color-normal));
|
|
17
17
|
transition: background-color 5000s ease-in-out 0s;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
box alone — .input-button keeps box-sizing: content-box (changing that risks shifting
|
|
18
18
|
icon-only's aspect-ratio: 1 sizing), so its own padding-block and border have to be
|
|
19
19
|
subtracted back out here, unlike --input-min-height itself which happens to need no such
|
|
20
|
-
adjustment (
|
|
20
|
+
adjustment (InputText has zero padding-block and no full border in its resting state).
|
|
21
21
|
This is a floor, not a fixed height — icon-only/pill buttons or longer button-text can
|
|
22
22
|
still grow past it. Textareas are the deliberate exception to this alignment entirely. */
|
|
23
23
|
--button-min-height: calc(
|
|
@@ -86,7 +86,7 @@ For a single "special" button or input, wrap just the control so the glow become
|
|
|
86
86
|
No changes to the control are needed:
|
|
87
87
|
|
|
88
88
|
- `InputButton`'s border already defaults to its own surface colour, so it shows no edge of its own.
|
|
89
|
-
- `
|
|
89
|
+
- `InputText` needs `--input-text-border: transparent`.
|
|
90
90
|
- On the `GlowingBorder`: radius is the control's radius plus the glow width, surface
|
|
91
91
|
`transparent`, overflow `visible` (so the control's hover and focus outlines aren't clipped),
|
|
92
92
|
and an inline or shrink-to-fit display so it hugs the control.
|
|
@@ -97,7 +97,7 @@ No changes to the control are needed:
|
|
|
97
97
|
</GlowingBorder>
|
|
98
98
|
|
|
99
99
|
<GlowingBorder variant="vivid" style-class-passthrough="special-input">
|
|
100
|
-
<
|
|
100
|
+
<InputText id="email" v-model="email" type="email" name="email"></InputText>
|
|
101
101
|
</GlowingBorder>
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryFn } from "@nuxtjs/storybook";
|
|
2
2
|
import { computed, ref } from "vue";
|
|
3
3
|
import StorybookComponent from "../GlowingBorder.vue";
|
|
4
|
-
import
|
|
4
|
+
import InputText from "../../../../05.forms/input-text/InputText.vue";
|
|
5
5
|
import InputButton from "../../../../05.forms/input-button/InputButton.vue";
|
|
6
6
|
import CanvasSwitcher from "../../../canvas-switcher/CanvasSwitcher.vue";
|
|
7
7
|
import type { MediaCanvas } from "~/types/components";
|
|
@@ -194,7 +194,7 @@ CustomTokens.args = {
|
|
|
194
194
|
};
|
|
195
195
|
|
|
196
196
|
export const HighlightedControls: StoryFn<StoryArgs> = (args) => ({
|
|
197
|
-
components: { StorybookComponent,
|
|
197
|
+
components: { StorybookComponent, InputText, InputButton },
|
|
198
198
|
setup() {
|
|
199
199
|
const { args: storyArgs, stageStyle } = useStorySetup(args);
|
|
200
200
|
const glowStyle = (controlRadius: string) =>
|
|
@@ -224,13 +224,13 @@ export const HighlightedControls: StoryFn<StoryArgs> = (args) => ({
|
|
|
224
224
|
<div style="display: grid; gap: 8px; inline-size: min(100%, 40rem);">
|
|
225
225
|
<label for="highlighted-email">Early-access email</label>
|
|
226
226
|
<StorybookComponent :variant="args.variant" :style="inputGlowStyle">
|
|
227
|
-
<
|
|
227
|
+
<InputText
|
|
228
228
|
id="highlighted-email"
|
|
229
229
|
v-model="email"
|
|
230
230
|
type="email"
|
|
231
231
|
name="highlighted-email"
|
|
232
232
|
placeholder="eg. jane@example.com"
|
|
233
|
-
></
|
|
233
|
+
></InputText>
|
|
234
234
|
</StorybookComponent>
|
|
235
235
|
</div>
|
|
236
236
|
</div>
|
|
@@ -2,7 +2,7 @@ import { computed, reactive, ref } from "vue";
|
|
|
2
2
|
import ProgressTracker from "../ProgressTracker.vue";
|
|
3
3
|
import CanvasSwitcher from "../../../01.atoms/canvas-switcher/CanvasSwitcher.vue";
|
|
4
4
|
import InputButton from "../../../05.forms/input-button/InputButton.vue";
|
|
5
|
-
import
|
|
5
|
+
import InputTextField from "../../../05.forms/input-text/InputTextField.vue";
|
|
6
6
|
import type { Meta, StoryObj } from "@nuxtjs/storybook";
|
|
7
7
|
import type { MediaCanvas, ProgressTrackerStep } from "~/types/components";
|
|
8
8
|
|
|
@@ -217,7 +217,7 @@ export const Wizard: Story = {
|
|
|
217
217
|
name: "Wizard (parent-owned forms)",
|
|
218
218
|
args: { modelValue: 0, steps: wizardSteps },
|
|
219
219
|
render: (args) => ({
|
|
220
|
-
components: { ProgressTracker, InputButton,
|
|
220
|
+
components: { ProgressTracker, InputButton, InputTextField },
|
|
221
221
|
setup() {
|
|
222
222
|
const story = useStorySetup(args);
|
|
223
223
|
const form = reactive({ name: "", email: "" });
|
|
@@ -254,7 +254,7 @@ export const Wizard: Story = {
|
|
|
254
254
|
<ProgressTracker v-bind="componentArgs" v-model="args.modelValue" :steps="steps">
|
|
255
255
|
<template #step-0="{ headingId }">
|
|
256
256
|
<form :aria-labelledby="headingId" style="display: grid; gap: 1.6rem;" @submit.prevent="next('name')">
|
|
257
|
-
<
|
|
257
|
+
<InputTextField
|
|
258
258
|
v-model="form.name"
|
|
259
259
|
type="text"
|
|
260
260
|
name="wizard-name"
|
|
@@ -270,7 +270,7 @@ export const Wizard: Story = {
|
|
|
270
270
|
</template>
|
|
271
271
|
<template #step-1="{ headingId }">
|
|
272
272
|
<form :aria-labelledby="headingId" style="display: grid; gap: 1.6rem;" @submit.prevent="next('email')">
|
|
273
|
-
<
|
|
273
|
+
<InputTextField
|
|
274
274
|
v-model="form.email"
|
|
275
275
|
type="email"
|
|
276
276
|
name="wizard-email"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# InputError — Consumer Styling Guide
|
|
2
2
|
|
|
3
3
|
`InputError` is the red error message strip rendered under a form control by every `*Field`
|
|
4
|
-
wrapper (`
|
|
4
|
+
wrapper (`InputTextField`, `InputNumberField`, `InputSelectField`, `SingleCheckbox`, ...).
|
|
5
5
|
It animates open (`grid-template-rows: 0fr → 1fr` plus opacity) when the field is in error.
|
|
6
6
|
|
|
7
7
|
## Public token API
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# FormField — Consumer Styling Guide
|
|
2
2
|
|
|
3
3
|
`FormField` is a layout wrapper for one form control (typically an `*Field` component such as
|
|
4
|
-
`
|
|
4
|
+
`InputTextField` or `InputNumberField`). It caps the field's width, centres it, optionally
|
|
5
5
|
insets it from its container's edges with a gutter, and applies vertical spacing between fields.
|
|
6
6
|
|
|
7
7
|
## Public token API
|
|
@@ -65,7 +65,7 @@ Set the tokens above on an element you own (a page or section class, or a class
|
|
|
65
65
|
|
|
66
66
|
```vue
|
|
67
67
|
<FormField width="wide" style="--form-field-background-color: var(--slate-01);">
|
|
68
|
-
<
|
|
68
|
+
<InputTextField ... />
|
|
69
69
|
</FormField>
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryFn } from "@nuxtjs/storybook";
|
|
2
2
|
import { ref } from "vue";
|
|
3
3
|
import StorybookComponent from "../InputButton.vue";
|
|
4
|
-
import
|
|
4
|
+
import InputText from "../../input-text/InputText.vue";
|
|
5
5
|
|
|
6
6
|
interface InputButtonStoryArgs {
|
|
7
7
|
type: "submit" | "button" | "reset";
|
|
@@ -314,11 +314,11 @@ NuxtIconOnlyComponent.args = {
|
|
|
314
314
|
// most common "usual suspect" pairing (e.g. newsletter signup, search bar). Textareas are the
|
|
315
315
|
// deliberate exception to this alignment and aren't part of this story.
|
|
316
316
|
const InlineTemplate: StoryFn = () => ({
|
|
317
|
-
components: { StorybookComponent,
|
|
317
|
+
components: { StorybookComponent, InputText },
|
|
318
318
|
template: `
|
|
319
319
|
<div style="margin: 36px; max-width: 480px;">
|
|
320
320
|
<div style="display: flex; align-items: flex-start; gap: 0.8rem;">
|
|
321
|
-
<
|
|
321
|
+
<InputText
|
|
322
322
|
id="inline-email"
|
|
323
323
|
name="email"
|
|
324
324
|
type="email"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# InputDescription — Consumer Styling Guide
|
|
2
2
|
|
|
3
3
|
`InputDescription` is the help text rendered between the label and the control by every `*Field`
|
|
4
|
-
wrapper (`
|
|
5
|
-
`
|
|
4
|
+
wrapper (`InputTextField`, `InputNumberField`, `InputSelectField`,
|
|
5
|
+
`InputTextareaField`, `InputRangeField`, `InputTextAsNumberField`, `SingleCheckbox`,
|
|
6
6
|
`MultipleCheckboxes`, `MultipleRadiobuttons`) when you pass it a `descriptionText` or
|
|
7
7
|
`descriptionHtml` slot. With neither slot it renders nothing.
|
|
8
8
|
|
|
@@ -84,9 +84,9 @@ description. Keep these blocks **unlayered** (no `@layer ...` wrapper) so they b
|
|
|
84
84
|
```vue
|
|
85
85
|
<template>
|
|
86
86
|
<div class="contact-page-content">
|
|
87
|
-
<
|
|
87
|
+
<InputTextField v-model="email" name="email" label="Email">
|
|
88
88
|
<template #descriptionText>We'll only use this for your booking confirmation</template>
|
|
89
|
-
</
|
|
89
|
+
</InputTextField>
|
|
90
90
|
</div>
|
|
91
91
|
</template>
|
|
92
92
|
|
|
@@ -108,9 +108,9 @@ The wrappers don't forward `style-class-passthrough` to the description, but a p
|
|
|
108
108
|
the wrapper itself lands on its root element, which is an ancestor of the description:
|
|
109
109
|
|
|
110
110
|
```vue
|
|
111
|
-
<
|
|
111
|
+
<InputTextField class="email-field" v-model="email" name="email" label="Email">
|
|
112
112
|
<template #descriptionText>We'll only use this for your booking confirmation</template>
|
|
113
|
-
</
|
|
113
|
+
</InputTextField>
|
|
114
114
|
|
|
115
115
|
<style>
|
|
116
116
|
.email-field {
|