diff --git a/.changeset/violet-snails-obey.md b/.changeset/violet-snails-obey.md new file mode 100644 index 00000000000..2cb5ff48ec0 --- /dev/null +++ b/.changeset/violet-snails-obey.md @@ -0,0 +1,6 @@ +--- +'@spectrum-web-components/number-field': patch +'@spectrum-web-components/textfield': patch +--- + +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. diff --git a/packages/number-field/README.md b/packages/number-field/README.md index 03173de8e5e..ae64842e1dd 100644 --- a/packages/number-field/README.md +++ b/packages/number-field/README.md @@ -267,3 +267,15 @@ The `` component doesn't manage a default value by itself. This }); }); + +## States + +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. + +```html +Count + +
+Size + +``` diff --git a/packages/number-field/src/NumberField.ts b/packages/number-field/src/NumberField.ts index 44dbca28959..95d4be73afd 100644 --- a/packages/number-field/src/NumberField.ts +++ b/packages/number-field/src/NumberField.ts @@ -34,9 +34,9 @@ import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron200.js'; import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron50.js'; import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron75.js'; import '@spectrum-web-components/infield-button/sp-infield-button.js'; +import { isAndroid, isIOS, isIPhone } from '@spectrum-web-components/shared'; import { TextfieldBase } from '@spectrum-web-components/textfield'; import styles from './number-field.css.js'; -import { isAndroid, isIOS, isIPhone } from '@spectrum-web-components/shared'; export const FRAMES_PER_CHANGE = 5; // Debounce duration for inserting a `change` event after a batch of `wheel` originating `input` events. diff --git a/packages/number-field/src/number-field.css b/packages/number-field/src/number-field.css index 7e100e33c87..145d39beafb 100644 --- a/packages/number-field/src/number-field.css +++ b/packages/number-field/src/number-field.css @@ -10,11 +10,38 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ +@import url('@spectrum-web-components/infield-button/src/infield-button.css'); @import url('./spectrum-number-field.css'); @import url('./number-field-overrides.css'); +:host { + inline-size: var( + --mod-stepper-width, + calc( + var(--mod-stepper-height, var(--spectrum-stepper-height)) * + var( + --mod-stepper-min-width-multiplier, + var(--spectrum-text-field-minimum-width-multiplier) + ) + + var( + --mod-stepper-button-width, + var(--spectrum-stepper-button-width) + ) + + var( + --mod-stepper-border-width, + var(--spectrum-stepper-border-width) + ) * 2 + ) + ); +} + +#textfield { + inline-size: 100%; +} + .input { font-variant-numeric: tabular-nums; + line-height: var(--spectrum-textfield-height); } :host([readonly]) .buttons { @@ -53,9 +80,86 @@ governing permissions and limitations under the License. ); } +:host([invalid]:not([hide-stepper])) #textfield .icon { + --mod-textfield-icon-spacing-inline-end-invalid: calc( + var(--system-infield-button-top-width) + + var(--spectrum-textfield-icon-spacing-inline-end-invalid) + ); +} + +:host([valid]:not([hide-stepper])) #textfield .icon { + --mod-textfield-icon-spacing-inline-end-valid: calc( + var(--system-infield-button-top-width) + + var(--spectrum-textfield-icon-spacing-inline-end-valid) + ); +} + +:host(:not([hide-stepper])) #textfield { + --mod-stepper-width: calc( + var(--spectrum-stepper-height) * + var( + --mod-stepper-min-width-multiplier, + var(--spectrum-text-field-minimum-width-multiplier) + ) + var(--spectrum-stepper-button-width) * 2 + + var( + --mod-stepper-border-width, + var(--spectrum-stepper-border-width) + ) * 2 + ); +} + +:host([invalid]) .input { + padding-inline-end: calc( + var( + --mod-textfield-icon-spacing-inline-start-valid, + var(--spectrum-textfield-icon-spacing-inline-start-valid) + ) + + var( + --mod-textfield-icon-size-valid, + var(--spectrum-textfield-icon-size-valid) + ) + + var( + --mod-textfield-icon-spacing-inline-end-valid, + var(--spectrum-textfield-icon-spacing-inline-end-valid) + ) - + var( + --mod-textfield-border-width, + var(--spectrum-textfield-border-width) + ) + ); +} + :host([focused]:not([disabled])) #textfield:hover { --mod-stepper-buttons-border-color-focus-hover: var( --mod-stepper-border-color-focus-hover, var(--spectrum-stepper-border-color-focus-hover) ); } + +:host([invalid]:not([hide-stepper])) #textfield .icon { + --mod-textfield-icon-spacing-inline-end-invalid: calc( + var(--spectrum-infield-button-width) + + var(--spectrum-textfield-icon-spacing-inline-end-invalid) + ); +} + +:host([valid]:not([hide-stepper])) #textfield .icon { + --mod-textfield-icon-spacing-inline-end-valid: calc( + var(--spectrum-infield-button-width) + + var(--spectrum-textfield-icon-spacing-inline-end-valid) + ); +} + +:host(:not([hide-stepper])) { + --mod-stepper-width: calc( + var(--spectrum-textfield-height) * + var( + --mod-stepper-min-width-multiplier, + var(--spectrum-text-field-minimum-width-multiplier) + ) + var(--spectrum-infield-button-width) * 2 + + var( + --mod-stepper-border-width, + var(--spectrum-stepper-border-width) + ) * 2 + ); +} diff --git a/packages/number-field/stories/number-field.stories.ts b/packages/number-field/stories/number-field.stories.ts index b7aeda32f97..4b71829beb1 100644 --- a/packages/number-field/stories/number-field.stories.ts +++ b/packages/number-field/stories/number-field.stories.ts @@ -13,10 +13,11 @@ governing permissions and limitations under the License. import { html, TemplateResult } from '@spectrum-web-components/base'; import { ifDefined } from '@spectrum-web-components/base/src/directives.js'; -import '@spectrum-web-components/number-field/sp-number-field.js'; import '@spectrum-web-components/field-label/sp-field-label.js'; -import { spreadProps } from '../../../test/lit-helpers.js'; +import '@spectrum-web-components/number-field/sp-number-field.js'; +import '@spectrum-web-components/slider/sp-slider.js'; import { NumberField } from '@spectrum-web-components/number-field/src/NumberField.js'; +import { spreadProps } from '../../../test/lit-helpers.js'; export default { title: 'Number Field', @@ -208,7 +209,7 @@ export const Default = (args: StoryArgs = {}): TemplateResult => { onInput((event.target as NumberField).value)} @change=${(event: Event) => onChange((event.target as NumberField).value)} - style=${ifDefined(args.quiet ? undefined : 'width: 150px')} + style=${ifDefined(args.quiet ? undefined : '')} >
`; }; @@ -239,7 +240,6 @@ export const decimals = (args: StoryArgs): TemplateResult => { { { Enter a percentage { return html` Enter a value in Euros { Enter a lengths in inches { Enter a lengths in pixels html` @@ -454,6 +448,31 @@ readOnly.args = { readonly: true, value: '15', }; +export const validationIcons = (args: StoryArgs): TemplateResult => { + return html` + + Invalid Number Field without Stepper + + + + Valid Number Field with Stepper + + + + Invalid Number Field with Stepper + + + `; +}; +validationIcons.args = { + invalid: true, + value: '15', + hideStepper: true, +}; export const ScrollingContainer = (args: StoryArgs = {}): TemplateResult => { const onChange = @@ -490,7 +509,6 @@ export const ScrollingContainer = (args: StoryArgs = {}): TemplateResult => { onInput((event.target as NumberField).value)} @change=${(event: Event) => onChange((event.target as NumberField).value)} - style="width: 150px" >

This box should not scroll when the focus is inside the diff --git a/packages/textfield/src/spectrum-config.js b/packages/textfield/src/spectrum-config.js index fec9c085e58..f856845db03 100644 --- a/packages/textfield/src/spectrum-config.js +++ b/packages/textfield/src/spectrum-config.js @@ -45,84 +45,6 @@ export default { }, // Default to `size='m'` without needing the attribute converter.classToHost('spectrum-Textfield--sizeM'), - { - find: [builder.class('spectrum-Textfield--sizeS')], - replace: [ - { - replace: builder.id('textfield'), - }, - { - replace: builder.attribute('size', 's'), - }, - ], - }, - { - find: [builder.class('spectrum-Textfield--sizeL')], - replace: [ - { - replace: builder.id('textfield'), - }, - { - replace: builder.attribute('size', 'l'), - }, - ], - }, - { - find: [builder.class('spectrum-Textfield--sizeXL')], - replace: [ - { - replace: builder.id('textfield'), - }, - { - replace: builder.attribute('size', 'xl'), - }, - ], - }, - { - // .spectrum-Textfield--quiet:after - find: [ - builder.class('spectrum-Textfield--quiet'), - builder.pseudoElement('after'), - ], - // :host([quiet]) #textfield:after { - replace: [ - { - replace: builder.attribute('quiet'), - }, - { - replace: builder.id('textfield'), - }, - { - replace: builder.pseudoElement('after'), - }, - ], - }, - { - // .spectrum-Textfield--quiet.is-keyboardFocused:after - find: [ - builder.class('spectrum-Textfield--quiet'), - builder.class('is-keyboardFocused'), - builder.pseudoElement('after'), - ], - // :host([quiet][focused]) #textfield:after - replace: [ - { - replace: builder.attribute('quiet'), - }, - { - replace: builder.attribute('focused'), - }, - { - replace: builder.combinator(' '), - }, - { - replace: builder.id('textfield'), - }, - { - replace: builder.pseudoElement('after'), - }, - ], - }, ...converter.enumerateAttributes( [ ['spectrum-Textfield--sizeS', 's'], diff --git a/packages/textfield/src/spectrum-textfield.css b/packages/textfield/src/spectrum-textfield.css index 040f93e0fe5..8d5ac6ac94a 100644 --- a/packages/textfield/src/spectrum-textfield.css +++ b/packages/textfield/src/spectrum-textfield.css @@ -71,7 +71,7 @@ governing permissions and limitations under the License. --spectrum-text-area-min-block-size-quiet: var(--spectrum-component-height-100); } -:host([size='s']) #textfield { +:host([size='s']) { --spectrum-textfield-height: var(--spectrum-component-height-75); --spectrum-textfield-label-spacing-block-quiet: var(--spectrum-field-label-to-component-quiet-small); --spectrum-textfield-label-spacing-inline-side-label: var(--spectrum-spacing-100); @@ -91,7 +91,7 @@ governing permissions and limitations under the License. --spectrum-text-area-min-block-size-quiet: var(--spectrum-component-height-75); } -:host([size='l']) #textfield { +:host([size='l']) { --spectrum-textfield-height: var(--spectrum-component-height-200); --spectrum-textfield-label-spacing-block-quiet: var(--spectrum-field-label-to-component-quiet-large); --spectrum-textfield-label-spacing-inline-side-label: var(--spectrum-spacing-200); @@ -111,7 +111,7 @@ governing permissions and limitations under the License. --spectrum-text-area-min-block-size-quiet: var(--spectrum-component-height-200); } -:host([size='xl']) #textfield { +:host([size='xl']) { --spectrum-textfield-height: var(--spectrum-component-height-300); --spectrum-textfield-label-spacing-block-quiet: var(--spectrum-field-label-to-component-quiet-extra-large); --spectrum-textfield-label-spacing-inline-side-label: var(--spectrum-spacing-200); @@ -506,7 +506,7 @@ governing permissions and limitations under the License. overflow-y: hidden; } -:host([quiet]) #textfield:after { +:host([quiet]):after { content: ''; pointer-events: none; inline-size: 100%; @@ -516,7 +516,7 @@ governing permissions and limitations under the License. inset-inline-start: 0; } -:host([quiet][focused]) #textfield:after { +:host([quiet][focused]):after { background-color: var(--highcontrast-textfield-focus-indicator-color, var(--mod-textfield-focus-indicator-color, var(--spectrum-textfield-focus-indicator-color))); } diff --git a/packages/textfield/src/textfield-overrides.css b/packages/textfield/src/textfield-overrides.css index 21159535aec..98c8b6fddc4 100644 --- a/packages/textfield/src/textfield-overrides.css +++ b/packages/textfield/src/textfield-overrides.css @@ -40,19 +40,19 @@ governing permissions and limitations under the License. ); } -:host([size='s']) #textfield#textfield { +:host([size='s']) #textfield { --spectrum-textfield-icon-spacing-block-invalid: var( --system-textfield-size-s-icon-spacing-block-invalid ); } -:host([size='l']) #textfield#textfield { +:host([size='l']) #textfield { --spectrum-textfield-icon-spacing-block-invalid: var( --system-textfield-size-l-icon-spacing-block-invalid ); } -:host([size='xl']) #textfield#textfield { +:host([size='xl']) #textfield { --spectrum-textfield-icon-spacing-block-invalid: var( --system-textfield-size-xl-icon-spacing-block-invalid ); diff --git a/packages/textfield/src/textfield.css b/packages/textfield/src/textfield.css index db556748a82..aaab2f38bab 100644 --- a/packages/textfield/src/textfield.css +++ b/packages/textfield/src/textfield.css @@ -32,6 +32,8 @@ governing permissions and limitations under the License. } #textfield { + --spectrum-textfield-input-line-height: var(--spectrum-textfield-height); + inline-size: 100%; } @@ -41,7 +43,10 @@ textarea { } .input { - min-inline-size: var(--spectrum-textfield-min-width); + min-inline-size: var( + --mod-textfield-min-width, + var(--spectrum-textfield-width) + ); } :host([focused]) .input {