srcdev-nuxt-components 9.3.12 → 9.3.13
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/index.md +1 -0
- package/.claude/skills/theming-component-token-pattern.md +126 -0
- package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +10 -1
- package/app/components/02.molecules/input-copy/CONSUMER-STYLING.md +3 -3
- package/app/components/02.molecules/input-copy/InputCopy.vue +9 -3
- package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +3 -3
- package/app/components/02.molecules/pricing-card/PricingCard.vue +6 -3
- package/app/components/05.forms/input-button/CONSUMER-STYLING.md +117 -0
- package/app/components/05.forms/input-button/InputButtonCore.vue +83 -37
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
- package/app/components/05.forms/input-button/stories/InputButtonCore.stories.ts +35 -0
- package/app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md +68 -0
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +19 -9
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +8 -5
- package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioButton.stories.ts +93 -0
- package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioCore.stories.ts +75 -0
- package/app/components/05.forms/input-number/CONSUMER-STYLING.md +41 -0
- package/app/components/05.forms/input-number/InputNumberCore.vue +12 -6
- package/app/components/05.forms/input-select/CONSUMER-STYLING.md +35 -29
- package/app/components/05.forms/input-select/InputSelectCore.vue +32 -20
- package/app/components/05.forms/input-select/stories/InputSelectCore.stories.ts +69 -0
- package/app/components/05.forms/input-text/CONSUMER-STYLING.md +38 -48
- package/app/components/05.forms/input-text/InputTextCore.vue +35 -18
- package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +184 -0
- package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +125 -0
- package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +49 -0
- package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +23 -16
- package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +72 -0
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +42 -20
- package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts +63 -0
- package/app/components/display-theme-switch/DisplayThemeSwitch.vue +13 -6
- package/package.json +1 -1
|
@@ -96,17 +96,24 @@ const toggleSwitchValue = () => {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
.toggle-switch-wrapper {
|
|
99
|
-
--_icon-
|
|
100
|
-
|
|
99
|
+
/* --_icon-font-size, --_switch-padding, --_toggle-symbol-border-width are the only locals
|
|
100
|
+
actually read anywhere below — --_icon-on-opacity, --_icon-off-opacity,
|
|
101
|
+
--_symbol-background-color, --_symbol-margin-inline-start, --_symbol-checked-offset were
|
|
102
|
+
declared here but never referenced by any property in this file; removed as dead code
|
|
103
|
+
rather than migrated, since migrating an unread token would just create a new unread
|
|
104
|
+
public one. */
|
|
101
105
|
--_icon-font-size: 2.4rem;
|
|
102
|
-
--_symbol-background-color: var(--blue-10);
|
|
103
|
-
--_symbol-margin-inline-start: 0;
|
|
104
|
-
--_symbol-checked-offset: calc(var(--input-toggle-symbol-size) * 0.75);
|
|
105
|
-
|
|
106
|
-
/* New vars */
|
|
107
106
|
--_switch-padding: 0.2rem;
|
|
108
107
|
--_toggle-symbol-border-width: 0.1rem;
|
|
109
108
|
|
|
109
|
+
/* Public --toggle-switch-* tokens, inline-fallback to the shared --theme-* tokens (see
|
|
110
|
+
theming-component-token-pattern.md) — overriding one here doesn't touch every other
|
|
111
|
+
themed input/control that also reads --theme-checkbox-symbol-surface/--theme-border. */
|
|
112
|
+
--_surface: var(--toggle-switch-surface, var(--theme-checkbox-symbol-surface));
|
|
113
|
+
--_surface-hover: var(--toggle-switch-surface-hover, var(--theme-surface-subtle));
|
|
114
|
+
--_border: var(--toggle-switch-border, var(--theme-border));
|
|
115
|
+
--_border-focus: var(--toggle-switch-border-focus, var(--theme-border-focus));
|
|
116
|
+
|
|
110
117
|
display: flex;
|
|
111
118
|
flex-direction: column;
|
|
112
119
|
|
|
@@ -117,7 +124,7 @@ const toggleSwitchValue = () => {
|
|
|
117
124
|
|
|
118
125
|
&:focus-visible {
|
|
119
126
|
+ .symbol-wrapper {
|
|
120
|
-
outline: var(--form-element-outline-width-focus) solid var(--
|
|
127
|
+
outline: var(--form-element-outline-width-focus) solid var(--_border-focus);
|
|
121
128
|
outline-offset: var(--form-element-outline-offset-focus);
|
|
122
129
|
}
|
|
123
130
|
}
|
|
@@ -137,15 +144,15 @@ const toggleSwitchValue = () => {
|
|
|
137
144
|
outline var(--theme-form-transition-duration) linear;
|
|
138
145
|
|
|
139
146
|
/* UI */
|
|
140
|
-
background-color: var(--
|
|
141
|
-
border: var(--form-element-border-width) solid var(--
|
|
147
|
+
background-color: var(--_surface);
|
|
148
|
+
border: var(--form-element-border-width) solid var(--_border);
|
|
142
149
|
outline: var(--form-element-outline-width) solid transparent;
|
|
143
150
|
border-radius: 100vw;
|
|
144
151
|
width: 72px;
|
|
145
152
|
padding: calc(var(--input-toggle-wrapper-padding) + var(--input-toggle-symbol-outline-width));
|
|
146
153
|
|
|
147
154
|
&:hover {
|
|
148
|
-
background-color: var(--
|
|
155
|
+
background-color: var(--_surface-hover);
|
|
149
156
|
cursor: pointer;
|
|
150
157
|
}
|
|
151
158
|
|
|
@@ -163,16 +170,16 @@ const toggleSwitchValue = () => {
|
|
|
163
170
|
|
|
164
171
|
/* UI */
|
|
165
172
|
/* padding: calc(calc(var(--input-toggle-symbol-size) - var(--_icon-font-size)) / 2); */
|
|
166
|
-
border: var(--input-toggle-symbol-border-width) solid var(--theme-text);
|
|
173
|
+
border: var(--input-toggle-symbol-border-width) solid var(--toggle-switch-symbol-border, var(--theme-text));
|
|
167
174
|
outline: var(--input-toggle-symbol-outline-width) solid transparent;
|
|
168
175
|
border-radius: 100vw;
|
|
169
|
-
background-color: var(--theme-on-surface);
|
|
176
|
+
background-color: var(--toggle-switch-symbol-surface-off, var(--theme-on-surface));
|
|
170
177
|
transition:
|
|
171
178
|
translate 0.4s ease,
|
|
172
179
|
background-color 0.4s linear;
|
|
173
180
|
|
|
174
181
|
&.checked {
|
|
175
|
-
background-color: var(--theme-surface);
|
|
182
|
+
background-color: var(--toggle-switch-symbol-surface-on, var(--theme-surface));
|
|
176
183
|
/* left: calc(
|
|
177
184
|
100% - var(--input-toggle-symbol-size) - var(--_switch-padding) - (2 * var(--_toggle-symbol-border-width))
|
|
178
185
|
); */
|
|
@@ -202,11 +209,11 @@ const toggleSwitchValue = () => {
|
|
|
202
209
|
color var(--theme-form-transition-duration);
|
|
203
210
|
|
|
204
211
|
&.icon-on {
|
|
205
|
-
color: var(--theme-on-surface);
|
|
212
|
+
color: var(--toggle-switch-icon-on-color, var(--theme-on-surface));
|
|
206
213
|
}
|
|
207
214
|
|
|
208
215
|
&.icon-off {
|
|
209
|
-
color: var(--theme-surface);
|
|
216
|
+
color: var(--toggle-switch-icon-off-color, var(--theme-surface));
|
|
210
217
|
}
|
|
211
218
|
|
|
212
219
|
&.active {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# TripleToggleSwitchCore — Consumer Styling Guide
|
|
2
|
+
|
|
3
|
+
## Public token API
|
|
4
|
+
|
|
5
|
+
Every colour token below is `var(--triple-toggle-switch-*, {default})` — set the
|
|
6
|
+
`--triple-toggle-switch-*` name to override just this component; leave it unset and it inherits
|
|
7
|
+
the shared `--theme-*` token every other themed component also falls back to. See
|
|
8
|
+
`theming-component-token-pattern.md` for why this two-tier shape exists.
|
|
9
|
+
|
|
10
|
+
| Token | Falls back to | Controls |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `--triple-toggle-switch-surface` | `var(--theme-input-surface)` | Wrapper background |
|
|
13
|
+
| `--triple-toggle-switch-border` | `var(--theme-border)` | Wrapper border colour |
|
|
14
|
+
| `--triple-toggle-switch-ring-focus` | `var(--theme-ring)` | Wrapper outline colour on `:focus-visible` |
|
|
15
|
+
| `--triple-toggle-switch-marker-surface` | `var(--theme-input-surface)` | Selected-option marker background, when none of the `system`/`light`/`dark` `:has()` overrides below match |
|
|
16
|
+
| `--triple-toggle-switch-marker-border` | `light-dark(var(--slate-10), var(--slate-00))` | Selected-option marker border colour |
|
|
17
|
+
| `--triple-toggle-switch-option-border` | `light-dark(#00000025, #ffffff50)` | Each option's resting border colour |
|
|
18
|
+
| `--triple-toggle-switch-option-border-hover` | `light-dark(var(--slate-10), var(--slate-00))` | Each option's outline colour on hover |
|
|
19
|
+
| `--triple-toggle-switch-option-ring-focus` | `var(--theme-ring)` | Each option's outline colour on `:focus-visible` |
|
|
20
|
+
| `--triple-toggle-switch-option-icon-color` | `light-dark(var(--slate-10), var(--slate-03))` | Option icon colour, resting (shared by the `.system`/`.light`/`.dark` selectors — see note) |
|
|
21
|
+
| `--triple-toggle-switch-option-icon-color-active` | `var(--slate-00)` | Option icon colour, selected |
|
|
22
|
+
|
|
23
|
+
> **Two bugs fixed in this migration**:
|
|
24
|
+
>
|
|
25
|
+
> 1. `--triple-toggle-switch-marker-surface` replaces a reference to `--theme-form-checkbox-bg`, a
|
|
26
|
+
> token declared nowhere in this layer at all — an undefined `var()` with no fallback silently
|
|
27
|
+
> resolves to the property's initial value, so the marker had no visible background whenever
|
|
28
|
+
> none of the value-specific `:has()` overrides matched. Two more dead tokens
|
|
29
|
+
> (`--theme-form-radio-border`, `--theme-form-radio-outline`, both also undeclared anywhere)
|
|
30
|
+
> fed two further-unused private locals and were removed outright.
|
|
31
|
+
> 2. The `.system`/`.light`/`.dark` `:has(input[value="..."])` selectors and matching
|
|
32
|
+
> `.option-icon.system/.light/.dark` classes used to say `"auto"` instead of `"system"` — but
|
|
33
|
+
> the only known consumer, `DisplayThemeSwitch`, has only ever emitted `id`/`value: "system"`
|
|
34
|
+
> (matching `useSettingsStore`'s `colourScheme` type, which the presentational side has to
|
|
35
|
+
> track). `"auto"` never matched anything real, so the system option's green gradient marker
|
|
36
|
+
> had never actually fired. Renamed the selectors to `"system"` rather than the data, since the
|
|
37
|
+
> data value is a real external contract (`useSettingsStore.setColourScheme` applies it as a
|
|
38
|
+
> literal CSS class on `<html>` elsewhere in the app) and the selectors are this component's own
|
|
39
|
+
> presentational-only concern.
|
|
40
|
+
>
|
|
41
|
+
> **`.system`/`.light`/`.dark` selectors**: the component hardcodes these three option *values* as
|
|
42
|
+
> CSS class selectors rather than being value-agnostic — a legacy of its one real consumer,
|
|
43
|
+
> `DisplayThemeSwitch`'s light/dark/system theme picker. All three already shared identical colour
|
|
44
|
+
> values before this migration; only the repeated literal values became tokens here, the selectors
|
|
45
|
+
> themselves are otherwise unchanged (so anything already targeting them by their corrected names
|
|
46
|
+
> keeps working). Making the component genuinely value-agnostic would be a larger, separate change.
|
|
47
|
+
|
|
48
|
+
Geometry (`--_form-*` sizing locals, `--form-element-*`) is shared/component-internal and untouched
|
|
49
|
+
by this — see `theming-form-geometry-tokens.md` for the shared half.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Global theming — app-level CSS file
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
:where(html) {
|
|
57
|
+
--triple-toggle-switch-surface: var(--rose-09);
|
|
58
|
+
--triple-toggle-switch-option-ring-focus: var(--rose-04);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Per-instance overrides
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<TripleToggleSwitchCore
|
|
68
|
+
v-model="scheme"
|
|
69
|
+
v-model:field-data="options"
|
|
70
|
+
style="--triple-toggle-switch-marker-surface: var(--gold-06);"
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
@@ -98,9 +98,16 @@ onMounted(() => {
|
|
|
98
98
|
<style lang="css">
|
|
99
99
|
@layer components {
|
|
100
100
|
.triple-toggle-switch {
|
|
101
|
-
--
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
/* Public --triple-toggle-switch-* tokens, inline-fallback to the shared --theme-* tokens (see
|
|
102
|
+
theming-component-token-pattern.md). --_form-border-colour/--_form-outline-colour used to
|
|
103
|
+
sit here referencing --theme-form-radio-border/-outline — dead tokens, declared nowhere in
|
|
104
|
+
this layer at all (confirmed by grep), and --_form-border-colour/--_form-outline-colour
|
|
105
|
+
themselves were never read by any property below either, so removed outright rather than
|
|
106
|
+
migrated. --_marker-surface replaces the one dead reference that WAS actually read:
|
|
107
|
+
--_select-scheme-group-background-color used to default from --theme-form-checkbox-bg,
|
|
108
|
+
equally undeclared anywhere — real (if narrow) bug, since it only rendered visibly when
|
|
109
|
+
none of the auto/light/dark :has() overrides below matched. */
|
|
110
|
+
--_marker-surface: var(--triple-toggle-switch-marker-surface, var(--theme-input-surface));
|
|
104
111
|
|
|
105
112
|
--_form-border-radius: calc(
|
|
106
113
|
(var(--_scheme-icon-font-size) / 2) + var(--form-element-border-width) + var(--form-element-outline-width) +
|
|
@@ -111,13 +118,18 @@ onMounted(() => {
|
|
|
111
118
|
--_form-items-gap: 1rem;
|
|
112
119
|
--_form-padding: 0.6rem;
|
|
113
120
|
|
|
114
|
-
--_select-scheme-group-background-color: var(--
|
|
121
|
+
--_select-scheme-group-background-color: var(--_marker-surface);
|
|
115
122
|
--_select-scheme-group-background-image: none;
|
|
116
123
|
--_select-scheme-group-padding: 0.5rem;
|
|
117
124
|
--_scheme-icon-font-size: 2rem;
|
|
118
125
|
/* --_scheme-icon-colour: black; */
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
/* "system" not "auto" — matches useSettingsStore's actual colourScheme value/CSS class
|
|
128
|
+
("system" | "dark" | "light"), which DisplayThemeSwitch's real option data uses. Was
|
|
129
|
+
"auto" here, a name that never matched any real consumer's data, so this gradient never
|
|
130
|
+
fired in practice (confirmed by grep across the whole layer — nothing anywhere emits value
|
|
131
|
+
"auto"). Presentational-only rename; the store's own type/class-name contract is untouched. */
|
|
132
|
+
&:has(input[value="system"]:checked) {
|
|
121
133
|
--_select-scheme-group-background-color: transparent;
|
|
122
134
|
--_select-scheme-group-background-image: radial-gradient(
|
|
123
135
|
circle,
|
|
@@ -152,8 +164,8 @@ onMounted(() => {
|
|
|
152
164
|
grid-template-areas: "select-stack";
|
|
153
165
|
width: fit-content;
|
|
154
166
|
|
|
155
|
-
background-color: var(--theme-input-surface);
|
|
156
|
-
border: var(--form-element-border-width) solid var(--theme-border);
|
|
167
|
+
background-color: var(--triple-toggle-switch-surface, var(--theme-input-surface));
|
|
168
|
+
border: var(--form-element-border-width) solid var(--triple-toggle-switch-border, var(--theme-border));
|
|
157
169
|
outline: var(--form-element-outline-width) solid transparent;
|
|
158
170
|
border-radius: 100vw;
|
|
159
171
|
padding: var(--_form-padding);
|
|
@@ -161,7 +173,7 @@ onMounted(() => {
|
|
|
161
173
|
transition: all var(--theme-form-transition-duration) ease-in-out;
|
|
162
174
|
|
|
163
175
|
&:has(input:focus-visible) {
|
|
164
|
-
outline: var(--form-element-outline-width) solid var(--theme-ring);
|
|
176
|
+
outline: var(--form-element-outline-width) solid var(--triple-toggle-switch-ring-focus, var(--theme-ring));
|
|
165
177
|
outline-offset: 0.2rem;
|
|
166
178
|
}
|
|
167
179
|
|
|
@@ -178,7 +190,8 @@ onMounted(() => {
|
|
|
178
190
|
transition: all v-bind(stepAnimationDuration) ease-in-out;
|
|
179
191
|
background-color: var(--_select-scheme-group-background-color);
|
|
180
192
|
background-image: var(--_select-scheme-group-background-image);
|
|
181
|
-
border: var(--form-element-border-width) solid
|
|
193
|
+
border: var(--form-element-border-width) solid
|
|
194
|
+
var(--triple-toggle-switch-marker-border, light-dark(var(--slate-10), var(--slate-00)));
|
|
182
195
|
|
|
183
196
|
border-radius: 50%;
|
|
184
197
|
|
|
@@ -211,7 +224,8 @@ onMounted(() => {
|
|
|
211
224
|
grid-template-areas: "icon-stack";
|
|
212
225
|
place-content: center;
|
|
213
226
|
background: transparent;
|
|
214
|
-
border: var(--form-element-border-width) solid
|
|
227
|
+
border: var(--form-element-border-width) solid
|
|
228
|
+
var(--triple-toggle-switch-option-border, light-dark(#00000025, #ffffff50));
|
|
215
229
|
outline: var(--form-element-outline-width) solid transparent;
|
|
216
230
|
border-radius: 50%;
|
|
217
231
|
padding: var(--_select-scheme-group-padding);
|
|
@@ -220,39 +234,47 @@ onMounted(() => {
|
|
|
220
234
|
transition: all calc(var(--theme-form-transition-duration) / 3);
|
|
221
235
|
|
|
222
236
|
&:has(.option-icon:hover) {
|
|
223
|
-
outline: var(--form-element-outline-width) solid
|
|
237
|
+
outline: var(--form-element-outline-width) solid
|
|
238
|
+
var(--triple-toggle-switch-option-border-hover, light-dark(var(--slate-10), var(--slate-00)));
|
|
224
239
|
}
|
|
225
240
|
&:has(input:focus-visible) {
|
|
226
|
-
outline: var(--form-element-outline-width) solid var(--theme-ring);
|
|
241
|
+
outline: var(--form-element-outline-width) solid var(--triple-toggle-switch-option-ring-focus, var(--theme-ring));
|
|
227
242
|
outline-offset: 0.2rem;
|
|
228
243
|
}
|
|
229
244
|
|
|
245
|
+
/* .system/.light/.dark all share the exact same colour values today — kept as three
|
|
246
|
+
selectors (rather than collapsed to one) since DisplayThemeSwitch and any other
|
|
247
|
+
consumer may already target these class names directly; only the repeated literal
|
|
248
|
+
values became tokens. This class is bound to each option's `id` in the template
|
|
249
|
+
(:class="[option.id, ...]"), not a hardcoded literal — "auto" here never matched
|
|
250
|
+
anything real for the same reason the :has(input[value="auto"]) selector above didn't:
|
|
251
|
+
the only known consumer's data uses id "system". */
|
|
230
252
|
.option-icon {
|
|
231
253
|
grid-area: icon-stack;
|
|
232
254
|
display: block;
|
|
233
255
|
font-size: var(--_scheme-icon-font-size);
|
|
234
256
|
|
|
235
|
-
&.
|
|
236
|
-
color: light-dark(var(--slate-10), var(--slate-03));
|
|
257
|
+
&.system {
|
|
258
|
+
color: var(--triple-toggle-switch-option-icon-color, light-dark(var(--slate-10), var(--slate-03)));
|
|
237
259
|
|
|
238
260
|
&.active {
|
|
239
|
-
color: var(--slate-00);
|
|
261
|
+
color: var(--triple-toggle-switch-option-icon-color-active, var(--slate-00));
|
|
240
262
|
}
|
|
241
263
|
}
|
|
242
264
|
|
|
243
265
|
&.light {
|
|
244
|
-
color: light-dark(var(--slate-10), var(--slate-03));
|
|
266
|
+
color: var(--triple-toggle-switch-option-icon-color, light-dark(var(--slate-10), var(--slate-03)));
|
|
245
267
|
|
|
246
268
|
&.active {
|
|
247
|
-
color: var(--slate-00);
|
|
269
|
+
color: var(--triple-toggle-switch-option-icon-color-active, var(--slate-00));
|
|
248
270
|
}
|
|
249
271
|
}
|
|
250
272
|
|
|
251
273
|
&.dark {
|
|
252
|
-
color: light-dark(var(--slate-10), var(--slate-03));
|
|
274
|
+
color: var(--triple-toggle-switch-option-icon-color, light-dark(var(--slate-10), var(--slate-03)));
|
|
253
275
|
|
|
254
276
|
&.active {
|
|
255
|
-
color: var(--slate-00);
|
|
277
|
+
color: var(--triple-toggle-switch-option-icon-color-active, var(--slate-00));
|
|
256
278
|
}
|
|
257
279
|
}
|
|
258
280
|
|
|
@@ -271,7 +293,7 @@ onMounted(() => {
|
|
|
271
293
|
}
|
|
272
294
|
}
|
|
273
295
|
|
|
274
|
-
/* &:has(input[value="
|
|
296
|
+
/* &:has(input[value="system"]:checked) {
|
|
275
297
|
--_scheme-icon-colour: white;
|
|
276
298
|
}
|
|
277
299
|
|
package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryFn } from "@nuxtjs/storybook";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import StorybookComponent from "../TripleToggleSwitchCore.vue";
|
|
4
|
+
import type { IFormMultipleOptions } from "~/types/forms/types.forms.d";
|
|
5
|
+
|
|
6
|
+
interface TripleToggleSwitchCoreStoryArgs {
|
|
7
|
+
name: string;
|
|
8
|
+
stepAnimationDuration: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// TripleToggleSwitchCore hardcodes three option *values* as CSS selectors — "system", "light",
|
|
12
|
+
// "dark" — rather than being value-agnostic (see CONSUMER-STYLING.md). This story uses exactly
|
|
13
|
+
// those values so the gradient marker behind each option actually fires; any other value falls
|
|
14
|
+
// back to --triple-toggle-switch-marker-surface with no gradient. DisplayThemeSwitch is the
|
|
15
|
+
// real-world consumer (light/dark/system colour-scheme picker) — this story exercises the bare
|
|
16
|
+
// component the same way, without the store wiring DisplayThemeSwitch adds on top.
|
|
17
|
+
export default {
|
|
18
|
+
title: "Components/Forms/Triple Toggle Switch/TripleToggleSwitchCore",
|
|
19
|
+
component: StorybookComponent,
|
|
20
|
+
argTypes: {
|
|
21
|
+
name: { control: "text", table: { category: "Basic" } },
|
|
22
|
+
stepAnimationDuration: {
|
|
23
|
+
control: "text",
|
|
24
|
+
description: "CSS transition duration for the marker sliding between options",
|
|
25
|
+
table: { category: "Styling" },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
name: "colour-scheme",
|
|
30
|
+
stepAnimationDuration: "250ms",
|
|
31
|
+
},
|
|
32
|
+
} as Meta<TripleToggleSwitchCoreStoryArgs>;
|
|
33
|
+
|
|
34
|
+
const Template: StoryFn<TripleToggleSwitchCoreStoryArgs> = (args) => ({
|
|
35
|
+
components: { StorybookComponent },
|
|
36
|
+
setup() {
|
|
37
|
+
const modelValue = ref("system");
|
|
38
|
+
const fieldData = ref<IFormMultipleOptions>({
|
|
39
|
+
data: [
|
|
40
|
+
{ id: "system", name: args.name, value: "system", label: "System", icon: "material-symbols:night-sight-auto-sharp" },
|
|
41
|
+
{ id: "light", name: args.name, value: "light", label: "Light", icon: "radix-icons:sun" },
|
|
42
|
+
{ id: "dark", name: args.name, value: "dark", label: "Dark", icon: "radix-icons:moon" },
|
|
43
|
+
],
|
|
44
|
+
total: 3,
|
|
45
|
+
skip: 0,
|
|
46
|
+
limit: 3,
|
|
47
|
+
});
|
|
48
|
+
return { args, modelValue, fieldData };
|
|
49
|
+
},
|
|
50
|
+
template: `
|
|
51
|
+
<div style="margin: 36px;">
|
|
52
|
+
<StorybookComponent
|
|
53
|
+
v-model="modelValue"
|
|
54
|
+
v-model:field-data="fieldData"
|
|
55
|
+
:name="args.name"
|
|
56
|
+
:step-animation-duration="args.stepAnimationDuration"
|
|
57
|
+
/>
|
|
58
|
+
<div style="margin-top: 1.6rem; font-size: 1.4rem;">Current value: {{ modelValue }}</div>
|
|
59
|
+
</div>
|
|
60
|
+
`,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export const Default = Template.bind({});
|
|
@@ -62,9 +62,13 @@ watch(colorModeVal, (val) => {
|
|
|
62
62
|
@layer components {
|
|
63
63
|
.colour-scheme-select {
|
|
64
64
|
&.triple-toggle-switch {
|
|
65
|
-
--_form-border-colour
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
/* --_form-border-colour/--_form-outline-colour used to sit here referencing
|
|
66
|
+
--theme-form-radio-border/-outline — dead tokens declared nowhere in the layer, and
|
|
67
|
+
neither local var was itself ever read by any property below either; removed rather than
|
|
68
|
+
migrated. --_select-scheme-group-background-color below is repointed at the new public
|
|
69
|
+
--triple-toggle-switch-marker-surface token instead of the other dead reference it used
|
|
70
|
+
to carry (--theme-form-checkbox-bg) — see TripleToggleSwitchCore.vue and
|
|
71
|
+
theming-component-token-pattern.md. */
|
|
68
72
|
--_form-items-gap: 0.4rem;
|
|
69
73
|
--_form-padding: 0.4rem;
|
|
70
74
|
--_select-scheme-group-padding: 0.4rem;
|
|
@@ -77,10 +81,13 @@ watch(colorModeVal, (val) => {
|
|
|
77
81
|
--_scheme-icon-font-size: 1.6rem;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
|
-
--_select-scheme-group-background-color: var(--theme-
|
|
84
|
+
--_select-scheme-group-background-color: var(--triple-toggle-switch-marker-surface, var(--theme-input-surface));
|
|
81
85
|
--_select-scheme-group-background-image: none;
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
/* "system", matching sampleFieldData's actual id/value below — was "auto" here, which never
|
|
88
|
+
matched (this component's own data never used it), so this gradient never fired for the
|
|
89
|
+
system option in practice. */
|
|
90
|
+
&:has(input[value="system"]:checked) {
|
|
84
91
|
--_select-scheme-group-background-color: transparent;
|
|
85
92
|
--_select-scheme-group-background-image: radial-gradient(
|
|
86
93
|
circle,
|
|
@@ -149,7 +156,7 @@ watch(colorModeVal, (val) => {
|
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
.option-icon {
|
|
152
|
-
&.
|
|
159
|
+
&.system {
|
|
153
160
|
color: light-dark(var(--slate-10), var(--slate-03));
|
|
154
161
|
|
|
155
162
|
&.active {
|