srcdev-nuxt-components 9.3.1 → 9.3.2
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/app/components/05.forms/input-select/CONSUMER-STYLING.md +42 -0
- package/app/components/05.forms/input-select/InputSelectCore.vue +21 -9
- package/app/components/05.forms/input-text/CONSUMER-STYLING.md +60 -0
- package/app/components/05.forms/input-text/InputTextCore.vue +17 -8
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# InputSelectCore — Consumer Styling Guide
|
|
2
|
+
|
|
3
|
+
## Two override paths
|
|
4
|
+
|
|
5
|
+
Same public/private split as `InputTextCore` (see that component's `CONSUMER-STYLING.md` for the
|
|
6
|
+
full rationale) — `.input-select-wrapper` now exposes local tokens, one indirection step below the
|
|
7
|
+
global `--theme-*` ones they default from:
|
|
8
|
+
|
|
9
|
+
```css
|
|
10
|
+
--_input-select-surface: var(--theme-input-surface);
|
|
11
|
+
--_input-select-surface-hover: var(--theme-input-surface-hover);
|
|
12
|
+
--_input-select-border: var(--theme-border);
|
|
13
|
+
--_input-select-border-focus: var(--theme-border-focus);
|
|
14
|
+
--_input-select-outline-color: var(--_input-select-border-focus);
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **Global override**: redeclare `--theme-input-surface` / `--theme-border` / `--theme-border-focus`
|
|
18
|
+
/ `--theme-input-surface-hover` wherever you'd normally set theme tokens.
|
|
19
|
+
- **Local override** (this component only, guaranteed to win):
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
.input-select-wrapper {
|
|
23
|
+
--_input-select-border: var(--slate-06);
|
|
24
|
+
--_input-select-border-focus: var(--slate-04);
|
|
25
|
+
--_input-select-surface: var(--slate-01);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Note on `--_input-select-outline-color`
|
|
30
|
+
|
|
31
|
+
Before 2026-08-22 this was referenced (on the open-picker outline) but never declared anywhere —
|
|
32
|
+
a dangling private token that silently resolved to the property's initial value (same failure mode
|
|
33
|
+
as the `--theme-button-surface` typo documented in the layer's `CLAUDE.md`, pitfall list). It's now
|
|
34
|
+
properly defined, defaulting to `--_input-select-border-focus`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Other tokens
|
|
39
|
+
|
|
40
|
+
Generic form-geometry tokens (`--input-padding-inline`, `--input-min-height`, `--input-font-size`,
|
|
41
|
+
`--form-element-border-width`, `--form-input-border-radius`, etc.) are shared across every
|
|
42
|
+
`05.forms` component and declared in `setup/04.elements/forms/*.css` — not component-local.
|
|
@@ -73,7 +73,17 @@ const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>;
|
|
|
73
73
|
<style lang="css">
|
|
74
74
|
@layer components {
|
|
75
75
|
.input-select-wrapper {
|
|
76
|
-
|
|
76
|
+
/* Local overrides, one indirection step below the global --theme-* tokens they default from —
|
|
77
|
+
a consumer can target `.input-select-wrapper { --_input-select-border: ...; }` directly for
|
|
78
|
+
a guaranteed-specific override, instead of relying solely on redefining the global token.
|
|
79
|
+
See CONSUMER-STYLING.md. */
|
|
80
|
+
--_input-select-surface: var(--theme-input-surface);
|
|
81
|
+
--_input-select-surface-hover: var(--theme-input-surface-hover);
|
|
82
|
+
--_input-select-border: var(--theme-border);
|
|
83
|
+
--_input-select-border-focus: var(--theme-border-focus);
|
|
84
|
+
--_input-select-outline-color: var(--_input-select-border-focus);
|
|
85
|
+
|
|
86
|
+
background-color: var(--_input-select-surface);
|
|
77
87
|
overflow: hidden;
|
|
78
88
|
|
|
79
89
|
z-index: 2;
|
|
@@ -81,31 +91,33 @@ const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>;
|
|
|
81
91
|
transition: all var(--theme-form-transition-duration) ease-in-out;
|
|
82
92
|
|
|
83
93
|
&.normal {
|
|
84
|
-
border: var(--form-element-border-width) solid var(--
|
|
94
|
+
border: var(--form-element-border-width) solid var(--_input-select-border);
|
|
85
95
|
border-radius: var(--form-input-border-radius);
|
|
86
96
|
outline: var(--form-element-outline-width) solid transparent;
|
|
87
97
|
}
|
|
88
98
|
|
|
89
99
|
&.underlined {
|
|
90
|
-
border-bottom: var(--form-element-border-bottom-width-underlined) solid var(--
|
|
91
|
-
background-color: var(--
|
|
100
|
+
border-bottom: var(--form-element-border-bottom-width-underlined) solid var(--_input-select-border);
|
|
101
|
+
background-color: var(--_input-select-surface);
|
|
92
102
|
}
|
|
93
103
|
|
|
94
104
|
&:has(select:focus-visible, :hover) {
|
|
95
|
-
outline: var(--form-element-outline-width-focus) solid var(--
|
|
105
|
+
outline: var(--form-element-outline-width-focus) solid var(--_input-select-border-focus);
|
|
96
106
|
outline-offset: var(--form-element-outline-offset-focus);
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
.input-select-core {
|
|
100
110
|
appearance: none;
|
|
101
111
|
background-color: transparent;
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: center;
|
|
102
114
|
|
|
103
115
|
/* For legacy support - eg, Safari */
|
|
104
116
|
/* &::after {
|
|
105
117
|
content: '';
|
|
106
118
|
width: 0.8em;
|
|
107
119
|
height: 0.5em;
|
|
108
|
-
background-color: var(--
|
|
120
|
+
background-color: var(--_input-select-border);
|
|
109
121
|
clip-path: polygon(100% 0%, 0 0%, 50% 100%);
|
|
110
122
|
} */
|
|
111
123
|
|
|
@@ -128,7 +140,7 @@ const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>;
|
|
|
128
140
|
|
|
129
141
|
&:open::picker(select) {
|
|
130
142
|
opacity: 1;
|
|
131
|
-
border: var(--form-element-border-width) solid var(--
|
|
143
|
+
border: var(--form-element-border-width) solid var(--_input-select-border);
|
|
132
144
|
outline: var(--form-element-outline-width) solid var(--_input-select-outline-color);
|
|
133
145
|
|
|
134
146
|
@starting-style {
|
|
@@ -145,7 +157,7 @@ const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>;
|
|
|
145
157
|
|
|
146
158
|
font-family: var(--font-family);
|
|
147
159
|
font-size: var(--input-font-size);
|
|
148
|
-
line-height: var(--input-element-line-height);
|
|
160
|
+
/* line-height: var(--input-element-line-height); */
|
|
149
161
|
padding-block: var(--input-padding-block);
|
|
150
162
|
padding-inline: var(--input-padding-inline);
|
|
151
163
|
min-height: var(--input-min-height);
|
|
@@ -156,7 +168,7 @@ const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>;
|
|
|
156
168
|
transition: all var(--theme-form-transition-duration) ease-in-out;
|
|
157
169
|
|
|
158
170
|
&:hover {
|
|
159
|
-
background-color: var(--
|
|
171
|
+
background-color: var(--_input-select-surface-hover);
|
|
160
172
|
}
|
|
161
173
|
|
|
162
174
|
.input-select-core-option-decorator-icon {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# InputTextCore — Consumer Styling Guide
|
|
2
|
+
|
|
3
|
+
## Two override paths
|
|
4
|
+
|
|
5
|
+
Before 2026-08-22, `.input-text-wrapper` read the global `--theme-*` tokens directly
|
|
6
|
+
(`--theme-input-surface`, `--theme-border`, `--theme-border-focus`, `--theme-input-surface-hover`).
|
|
7
|
+
Overriding those globally (e.g. in a consumer app's unlayered `:root` block) should always have
|
|
8
|
+
worked on pure CSS-cascade grounds — an unlayered `:root` declaration (specificity `0,1,0`) beats
|
|
9
|
+
the layer's own `:where(html, [data-theme], [data-invalid])` declaration (specificity `0`)
|
|
10
|
+
regardless of source/import order — but a consumer app hit a case where a global override wasn't
|
|
11
|
+
visibly landing and the root cause wasn't pinned down (see `nuxt-components`'s own git history
|
|
12
|
+
around the same date for a *different*, confirmed bug in a sibling app: wrapping consumer CSS in
|
|
13
|
+
`@layer consumer` broke in production because SSR-inlined per-chunk `<style>` tags fix layer
|
|
14
|
+
priority by first-reference document order, not the app's intended `@layer` statement order — sic
|
|
15
|
+
that isn't what was happening here, since the consumer app's CSS was already unlayered, but it's
|
|
16
|
+
the same class of "cascade behaves differently than a clean mental model predicts" issue).
|
|
17
|
+
|
|
18
|
+
Rather than leave global-token overrides as the only lever, `.input-text-wrapper` now also
|
|
19
|
+
exposes its own local tokens, one indirection step below the global ones:
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
--_input-text-surface: var(--theme-input-surface);
|
|
23
|
+
--_input-text-surface-hover: var(--theme-input-surface-hover);
|
|
24
|
+
--_input-text-border: var(--theme-border);
|
|
25
|
+
--_input-text-border-focus: var(--theme-border-focus);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- **Global override** (affects every themed component, not just this one): redeclare
|
|
29
|
+
`--theme-input-surface` / `--theme-border` / `--theme-border-focus` / `--theme-input-surface-hover`
|
|
30
|
+
at whatever scope you'd normally set theme tokens (`:root`, `[data-theme]`, a page wrapper).
|
|
31
|
+
- **Local override** (this component only, guaranteed to win — it's the last declaration before
|
|
32
|
+
the property that consumes it, no global-token indirection to reason about):
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
/* Unscoped consumer CSS, no :deep() needed */
|
|
36
|
+
.input-text-wrapper {
|
|
37
|
+
--_input-text-border: var(--slate-06);
|
|
38
|
+
--_input-text-border-focus: var(--slate-04);
|
|
39
|
+
--_input-text-surface: var(--slate-01);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Prefer the local override when you only want to change this one component's look, or when you've
|
|
44
|
+
hit a case (like the one above) where a global-token change isn't landing and you don't have time
|
|
45
|
+
to dig into why — the local path is a strictly simpler cascade to reason about.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Other tokens
|
|
50
|
+
|
|
51
|
+
- `--input-icon-slot-gap`, `--input-padding-inline`, `--input-padding-block`, `--input-min-height`,
|
|
52
|
+
`--input-font-size`, `--form-element-border-width`, `--form-input-border-radius`,
|
|
53
|
+
`--form-element-border-bottom-width-underlined`, `--form-element-outline-width(-focus)`,
|
|
54
|
+
`--form-element-outline-offset-focus` — all generic form-geometry tokens shared across every
|
|
55
|
+
`05.forms` component, declared in `setup/04.elements/forms/*.css`. Not component-local, so
|
|
56
|
+
overriding one affects every form element, not just `InputTextCore`.
|
|
57
|
+
- `--theme-input-text-color-normal`, `--theme-input-placeholder`,
|
|
58
|
+
`--theme-input-placeholder-font-size` — still read directly from the global theme tokens, no
|
|
59
|
+
local indirection yet. Follow the same pattern above (`--_input-text-*`) if a future consumer
|
|
60
|
+
needs a local override for these.
|
|
@@ -127,10 +127,19 @@ onMounted(() => {
|
|
|
127
127
|
<style lang="css">
|
|
128
128
|
@layer components {
|
|
129
129
|
.input-text-wrapper {
|
|
130
|
+
/* Local overrides, one indirection step below the global --theme-* tokens they default from
|
|
131
|
+
— a consumer can target `.input-text-wrapper { --_input-text-border: ...; }` directly for
|
|
132
|
+
a guaranteed-specific override, instead of relying solely on redefining the global token.
|
|
133
|
+
See CONSUMER-STYLING.md. */
|
|
134
|
+
--_input-text-surface: var(--theme-input-surface);
|
|
135
|
+
--_input-text-surface-hover: var(--theme-input-surface-hover);
|
|
136
|
+
--_input-text-border: var(--theme-border);
|
|
137
|
+
--_input-text-border-focus: var(--theme-border-focus);
|
|
138
|
+
|
|
130
139
|
display: flex;
|
|
131
140
|
align-items: center;
|
|
132
141
|
gap: var(--input-icon-slot-gap);
|
|
133
|
-
background-color: var(--
|
|
142
|
+
background-color: var(--_input-text-surface);
|
|
134
143
|
overflow: hidden;
|
|
135
144
|
transition: all var(--theme-form-transition-duration) ease-in-out;
|
|
136
145
|
|
|
@@ -138,25 +147,25 @@ onMounted(() => {
|
|
|
138
147
|
position: relative;
|
|
139
148
|
|
|
140
149
|
&.normal {
|
|
141
|
-
border: var(--form-element-border-width) solid var(--
|
|
150
|
+
border: var(--form-element-border-width) solid var(--_input-text-border);
|
|
142
151
|
border-radius: var(--form-input-border-radius);
|
|
143
152
|
outline: var(--form-element-outline-width) solid transparent;
|
|
144
153
|
|
|
145
154
|
padding-inline: var(--input-padding-inline);
|
|
146
155
|
|
|
147
156
|
&:has(input:is(:hover), button:is(:hover)) {
|
|
148
|
-
outline: var(--form-element-outline-width-focus) solid var(--
|
|
157
|
+
outline: var(--form-element-outline-width-focus) solid var(--_input-text-border-focus);
|
|
149
158
|
outline-offset: var(--form-element-outline-offset-focus);
|
|
150
159
|
}
|
|
151
160
|
|
|
152
161
|
&:has(input:focus-visible, button:focus-visible) {
|
|
153
|
-
outline: var(--form-element-outline-width-focus) solid var(--
|
|
162
|
+
outline: var(--form-element-outline-width-focus) solid var(--_input-text-border-focus);
|
|
154
163
|
outline-offset: var(--form-element-outline-offset-focus);
|
|
155
164
|
}
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
&.underlined {
|
|
159
|
-
border-bottom: var(--form-element-border-bottom-width-underlined) solid var(--
|
|
168
|
+
border-bottom: var(--form-element-border-bottom-width-underlined) solid var(--_input-text-border);
|
|
160
169
|
padding-inline: var(--input-padding-inline);
|
|
161
170
|
}
|
|
162
171
|
|
|
@@ -171,17 +180,17 @@ onMounted(() => {
|
|
|
171
180
|
box-sizing: content-box;
|
|
172
181
|
|
|
173
182
|
.input-button-core {
|
|
174
|
-
background-color: var(--
|
|
183
|
+
background-color: var(--_input-text-surface);
|
|
175
184
|
aspect-ratio: 1;
|
|
176
185
|
border-radius: 0;
|
|
177
186
|
width: var(--input-min-height);
|
|
178
187
|
|
|
179
188
|
&:hover {
|
|
180
|
-
background-color: var(--
|
|
189
|
+
background-color: var(--_input-text-surface-hover);
|
|
181
190
|
}
|
|
182
191
|
|
|
183
192
|
&:is(:focus-visible) {
|
|
184
|
-
outline: var(--form-element-outline-width-focus) solid var(--
|
|
193
|
+
outline: var(--form-element-outline-width-focus) solid var(--_input-text-border-focus);
|
|
185
194
|
outline-offset: -4px;
|
|
186
195
|
}
|
|
187
196
|
|