Skip to content

Commit 74386e8

Browse files
fix(number-field): sp-number-field UI fixes for validation and width (#5408)
* docs(number-field): add number-field validation icon stories - removes hardcoded styles for widths Co-authored-by: Casey Eickhoff <[email protected]> * fix(number-field): implements spacing for validation icons Co-authored-by: Casey Eickhoff <[email protected]> * fix(numberfield): defines stepper width * chore: add changeset * chore: the teeniest tiniest lint fix * docs(number-field): add number-field validation icon stories - removes hardcoded styles for widths Co-authored-by: Casey Eickhoff <[email protected]> * fix(number-field): implements spacing for validation icons Co-authored-by: Casey Eickhoff <[email protected]> * fix(numberfield): defines stepper width * chore: add changeset * docs(numberfield): update readme Co-authored-by: Casey Eickhoff <[email protected]> * fix(numberfield): lint fix Co-authored-by: Casey Eickhoff <[email protected]> * chore(numberfield): removes textfield from changeset * chore: update golden hash --------- Co-authored-by: Casey Eickhoff <[email protected]>
1 parent 53f3769 commit 74386e8

File tree

5 files changed

+170
-11
lines changed

5 files changed

+170
-11
lines changed

.changeset/silly-rooms-talk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@spectrum-web-components/number-field': patch
3+
---
4+
5+
The changes included resolve UI issues with number-field by proxy of textfield. The validation icons in number-field no longer overlap the infield buttons. The width of the number-field now calculates accurately and can be modified via `--mod-stepper-width` token as it was before.

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ parameters:
1414
# 3. Commit this change to the PR branch where the changes exist.
1515
current_golden_images_hash:
1616
type: string
17-
default: 5ef901ef13226904d71cae8cbfdefa37286212ef
17+
default: 728676ad885db988eb369dac901e9904bf6b79d2
1818
wireit_cache_name:
1919
type: string
2020
default: wireit

packages/number-field/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,15 @@ The `<sp-number-field>` component doesn't manage a default value by itself. This
267267
});
268268
});
269269
</script>
270+
271+
## States
272+
273+
Use the `required` attribute to indicate a number field value is required. Dictate the validity or invalidity state of the text entry with the `valid` or `invalid` attributes.
274+
275+
```html
276+
<sp-field-label for="number-1" required>Count</sp-field-label>
277+
<sp-number-field id="number-1" valid value="12343"></sp-number-field>
278+
<br />
279+
<sp-field-label for="number-2" required>Size</sp-field-label>
280+
<sp-number-field id="number-2" invalid value="15212"></sp-number-field>
281+
```

packages/number-field/src/number-field.css

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020 Adobe. All rights reserved.
2+
Copyright 2025 Adobe. All rights reserved.
33
This file is licensed to you under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License. You may obtain a copy
55
of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -13,6 +13,98 @@ governing permissions and limitations under the License.
1313
@import url('./spectrum-number-field.css');
1414
@import url('./number-field-overrides.css');
1515

16+
/* sets the missing variables for the width calcs for each size- found in spectrum-number-field.css */
17+
:host,
18+
:host([size='m']) {
19+
--spectrum-stepper-button-width: var(
20+
--mod-stepper-button-width,
21+
var(--spectrum-in-field-button-width-stacked-medium)
22+
);
23+
--spectrum-stepper-height: var(
24+
--mod-stepper-height,
25+
var(--spectrum-component-height-100)
26+
);
27+
}
28+
29+
:host([size='s']) {
30+
--spectrum-stepper-button-width: var(
31+
--mod-stepper-button-width,
32+
var(--spectrum-in-field-button-width-stacked-small)
33+
);
34+
--spectrum-stepper-height: var(
35+
--mod-stepper-height,
36+
var(--spectrum-component-height-75)
37+
);
38+
}
39+
40+
:host([size='l']) {
41+
--spectrum-stepper-button-width: var(
42+
--mod-stepper-button-width,
43+
var(--spectrum-in-field-button-width-stacked-large)
44+
);
45+
--spectrum-stepper-height: var(
46+
--mod-stepper-height,
47+
var(--spectrum-component-height-200)
48+
);
49+
}
50+
51+
:host([size='xl']) {
52+
--spectrum-stepper-button-width: var(
53+
--mod-stepper-button-width,
54+
var(--spectrum-in-field-button-width-stacked-extra-large)
55+
);
56+
--spectrum-stepper-height: var(
57+
--mod-stepper-height,
58+
var(--spectrum-component-height-300)
59+
);
60+
}
61+
62+
:host {
63+
/* TODO: added stepper-button-width multiplied by 2 just to give extra space to the input field.
64+
That "2" is a magic number and should be removed when we are able (possibly after S2 migration). */
65+
--spectrum-stepper-width: calc(
66+
var(--mod-stepper-height, var(--spectrum-stepper-height)) *
67+
var(
68+
--mod-stepper-min-width-multiplier,
69+
var(--spectrum-text-field-minimum-width-multiplier)
70+
) +
71+
var(
72+
--mod-stepper-button-width,
73+
var(--spectrum-stepper-button-width)
74+
) * 2 +
75+
var(
76+
--mod-stepper-border-width,
77+
var(--spectrum-stepper-border-width)
78+
) * 2
79+
);
80+
81+
/* resets the inline-size of sp-number-field to the newly defined stepper-width */
82+
inline-size: var(--mod-stepper-width, var(--spectrum-stepper-width));
83+
}
84+
85+
:host([hide-stepper]) {
86+
--spectrum-stepper-width: calc(
87+
var(--mod-stepper-height, var(--spectrum-stepper-height)) *
88+
var(
89+
--mod-stepper-min-width-multiplier,
90+
var(--spectrum-text-field-minimum-width-multiplier)
91+
) +
92+
var(
93+
--mod-stepper-button-width,
94+
var(--spectrum-stepper-button-width)
95+
) +
96+
var(
97+
--mod-stepper-border-width,
98+
var(--spectrum-stepper-border-width)
99+
) * 2
100+
);
101+
}
102+
103+
/* keeps the textfield 100% of the width of the sp-number-field so there isn't a gap between the containers */
104+
#textfield {
105+
inline-size: 100%;
106+
}
107+
16108
.input {
17109
font-variant-numeric: tabular-nums;
18110
}
@@ -59,3 +151,34 @@ governing permissions and limitations under the License.
59151
var(--spectrum-stepper-border-color-focus-hover)
60152
);
61153
}
154+
155+
/* visually places the validation icon inside the input field */
156+
:host([invalid]:not([hide-stepper])) #textfield .icon,
157+
:host([valid]:not([hide-stepper])) #textfield .icon {
158+
inset-inline-end: calc(
159+
var(--spectrum-stepper-button-width) +
160+
var(--spectrum-textfield-icon-spacing-inline-end-invalid)
161+
);
162+
}
163+
164+
/* includes the alert icon size in the input's padding similar to the valid variant */
165+
:host([invalid]) .input {
166+
padding-inline-end: calc(
167+
var(
168+
--mod-textfield-icon-spacing-inline-start-valid,
169+
var(--spectrum-textfield-icon-spacing-inline-start-valid)
170+
) +
171+
var(
172+
--mod-textfield-icon-size-valid,
173+
var(--spectrum-textfield-icon-size-valid)
174+
) +
175+
var(
176+
--mod-textfield-icon-spacing-inline-end-valid,
177+
var(--spectrum-textfield-icon-spacing-inline-end-valid)
178+
) -
179+
var(
180+
--mod-textfield-border-width,
181+
var(--spectrum-textfield-border-width)
182+
)
183+
);
184+
}

packages/number-field/stories/number-field.stories.ts

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export const Default = (args: StoryArgs = {}): TemplateResult => {
208208
onInput((event.target as NumberField).value)}
209209
@change=${(event: Event) =>
210210
onChange((event.target as NumberField).value)}
211-
style=${ifDefined(args.quiet ? undefined : 'width: 150px')}
211+
style=${ifDefined(args.quiet ? undefined : '')}
212212
></sp-number-field>
213213
`;
214214
};
@@ -239,7 +239,6 @@ export const decimals = (args: StoryArgs): TemplateResult => {
239239
</sp-field-label>
240240
<sp-number-field
241241
id="decimals"
242-
style="width: 200px"
243242
...=${spreadProps(args)}
244243
@change=${args.onChange}
245244
@input=${args.onInput}
@@ -268,7 +267,6 @@ export const germanDecimals = (args: StoryArgs): TemplateResult => {
268267
<sp-theme lang="de" dir="${currentDir}">
269268
<sp-number-field
270269
id="decimals"
271-
style="width: 200px"
272270
...=${spreadProps(args)}
273271
@change=${args.onChange}
274272
@input=${args.onInput}
@@ -291,7 +289,6 @@ export const percents = (args: StoryArgs = {}): TemplateResult => {
291289
<sp-field-label for="percents">Enter a percentage</sp-field-label>
292290
<sp-number-field
293291
id="percents"
294-
style="width: 200px"
295292
...=${spreadProps(args)}
296293
@change=${args.onChange}
297294
.formatOptions=${{
@@ -310,7 +307,6 @@ export const currency = (args: StoryArgs = {}): TemplateResult => {
310307
return html`
311308
<sp-field-label for="currency">Enter a value in Euros</sp-field-label>
312309
<sp-number-field
313-
style="width: 200px"
314310
...=${spreadProps(args)}
315311
@change=${args.onChange}
316312
.formatOptions=${{
@@ -332,7 +328,6 @@ export const units = (args: StoryArgs): TemplateResult => {
332328
<sp-field-label for="units">Enter a lengths in inches</sp-field-label>
333329
<sp-number-field
334330
id="units"
335-
style="width: 200px"
336331
...=${spreadProps(args)}
337332
@change=${args.onChange}
338333
.formatOptions=${{
@@ -353,7 +348,6 @@ export const pixels = (args: StoryArgs): TemplateResult => {
353348
<sp-field-label for="units">Enter a lengths in pixels</sp-field-label>
354349
<sp-number-field
355350
id="units"
356-
style="width: 200px"
357351
.formatOptions=${{
358352
style: 'unit',
359353
unit: 'px',
@@ -374,7 +368,6 @@ export const minMax = (args: StoryArgs): TemplateResult => html`
374368
</sp-field-label>
375369
<sp-number-field
376370
id="min-max"
377-
style="width: 200px"
378371
...=${spreadProps(args)}
379372
@change=${args.onChange}
380373
></sp-number-field>
@@ -455,6 +448,33 @@ readOnly.args = {
455448
value: '15',
456449
};
457450

451+
export const validationIcons = (args: StoryArgs): TemplateResult => {
452+
return html`
453+
<sp-field-label for="invalidHiddenStepper">
454+
Invalid Number Field without Stepper
455+
</sp-field-label>
456+
<sp-number-field
457+
invalid
458+
id="invalidHiddenStepper"
459+
...=${spreadProps(args)}
460+
invalid
461+
></sp-number-field>
462+
<sp-field-label for="validStepper">
463+
Valid Number Field with Stepper
464+
</sp-field-label>
465+
<sp-number-field id="validStepper" valid></sp-number-field>
466+
<sp-field-label for="invalidStepper">
467+
Invalid Number Field with Stepper
468+
</sp-field-label>
469+
<sp-number-field id="invalidStepper" invalid></sp-number-field>
470+
`;
471+
};
472+
validationIcons.args = {
473+
invalid: true,
474+
value: '15',
475+
hideStepper: true,
476+
};
477+
458478
export const ScrollingContainer = (args: StoryArgs = {}): TemplateResult => {
459479
const onChange =
460480
(args.onChange as (value: number) => void) ||
@@ -490,7 +510,6 @@ export const ScrollingContainer = (args: StoryArgs = {}): TemplateResult => {
490510
onInput((event.target as NumberField).value)}
491511
@change=${(event: Event) =>
492512
onChange((event.target as NumberField).value)}
493-
style="width: 150px"
494513
></sp-number-field>
495514
<p>
496515
This box should not scroll when the focus is inside the

0 commit comments

Comments
 (0)