diff --git a/.changeset/warm-cars-fry.md b/.changeset/warm-cars-fry.md new file mode 100644 index 00000000000..3b7b73358f6 --- /dev/null +++ b/.changeset/warm-cars-fry.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': patch +--- + +Added `onBlur` prop to numerical steppers (`Spinner` component of `TextField`) to remove multi focus issue in `TextField`. diff --git a/polaris-react/src/components/TextField/TextField.stories.tsx b/polaris-react/src/components/TextField/TextField.stories.tsx index c819fd2185c..d37c07ee3e8 100644 --- a/polaris-react/src/components/TextField/TextField.stories.tsx +++ b/polaris-react/src/components/TextField/TextField.stories.tsx @@ -34,17 +34,28 @@ export function Default() { export function Number() { const [value, setValue] = useState('1'); + const [value1, setValue1] = useState('1'); const handleChange = useCallback((newValue) => setValue(newValue), []); + const handleChange1 = useCallback((newValue) => setValue1(newValue), []); return ( - + + + + ); } diff --git a/polaris-react/src/components/TextField/TextField.tsx b/polaris-react/src/components/TextField/TextField.tsx index 1389b80b1eb..26dafe9934f 100644 --- a/polaris-react/src/components/TextField/TextField.tsx +++ b/polaris-react/src/components/TextField/TextField.tsx @@ -407,6 +407,7 @@ export function TextField({ onMouseDown={handleButtonPress} onMouseUp={handleButtonRelease} ref={spinnerRef} + onBlur={handleOnBlur} /> ) : null; @@ -477,14 +478,6 @@ export function TextField({ } }; - const handleOnBlur = (event: React.FocusEvent) => { - setFocus(false); - - if (onBlur) { - onBlur(event); - } - }; - const input = createElement(multiline ? 'textarea' : 'input', { name, id, @@ -636,6 +629,14 @@ export function TextField({ event.preventDefault(); } + function handleOnBlur(event: React.FocusEvent) { + setFocus(false); + + if (onBlur) { + onBlur(event); + } + } + function isInput(target: HTMLElement | EventTarget) { return ( target instanceof HTMLElement && diff --git a/polaris-react/src/components/TextField/components/Spinner/Spinner.tsx b/polaris-react/src/components/TextField/components/Spinner/Spinner.tsx index 39c9c92d8aa..ec8e38f220f 100644 --- a/polaris-react/src/components/TextField/components/Spinner/Spinner.tsx +++ b/polaris-react/src/components/TextField/components/Spinner/Spinner.tsx @@ -11,10 +11,11 @@ export interface SpinnerProps { onClick?(event: React.MouseEvent): void; onMouseDown(onChange: HandleStepFn): void; onMouseUp(): void; + onBlur(event: React.FocusEvent): void; } export const Spinner = React.forwardRef( - function Spinner({onChange, onClick, onMouseDown, onMouseUp}, ref) { + function Spinner({onChange, onClick, onMouseDown, onMouseUp, onBlur}, ref) { function handleStep(step: number) { return () => onChange(step); } @@ -35,6 +36,7 @@ export const Spinner = React.forwardRef( onClick={handleStep(1)} onMouseDown={handleMouseDown(handleStep(1))} onMouseUp={onMouseUp} + onBlur={onBlur} >
@@ -47,6 +49,7 @@ export const Spinner = React.forwardRef( onClick={handleStep(-1)} onMouseDown={handleMouseDown(handleStep(-1))} onMouseUp={onMouseUp} + onBlur={onBlur} >
diff --git a/polaris-react/src/components/TextField/components/Spinner/tests/Spinner.test.tsx b/polaris-react/src/components/TextField/components/Spinner/tests/Spinner.test.tsx index 4edddf3afe8..4f02bf3357f 100644 --- a/polaris-react/src/components/TextField/components/Spinner/tests/Spinner.test.tsx +++ b/polaris-react/src/components/TextField/components/Spinner/tests/Spinner.test.tsx @@ -4,11 +4,18 @@ import {mountWithApp} from 'tests/utilities'; import {Spinner} from '../Spinner'; describe('', () => { + const defaultProps = { + onChange: noop, + onMouseDown: noop, + onMouseUp: noop, + onBlur: noop, + }; + describe('onChange', () => { it('adds a change callback', () => { const spy = jest.fn(); const spinner = mountWithApp( - , + , ); spinner.find('div', {role: 'button'})!.trigger('onClick'); @@ -19,14 +26,7 @@ describe('', () => { describe('onClick', () => { it('adds a click callback', () => { const spy = jest.fn(); - const spinner = mountWithApp( - , - ); + const spinner = mountWithApp(); spinner.find('div', {className: 'Spinner'})!.trigger('onClick'); expect(spy).toHaveBeenCalledTimes(1); }); @@ -40,9 +40,9 @@ describe('', () => { const changeSpy = jest.fn(); const spinner = mountWithApp( , ); @@ -61,9 +61,9 @@ describe('', () => { const changeSpy = jest.fn(); const spinner = mountWithApp( , ); @@ -80,7 +80,7 @@ describe('', () => { it('adds a mouse up callback', () => { const spy = jest.fn(); const spinner = mountWithApp( - , + , ); spinner.find('div', {role: 'button'})!.trigger('onMouseUp'); @@ -88,6 +88,17 @@ describe('', () => { expect(spy).toHaveBeenCalledTimes(1); }); }); + + describe('onBlur()', () => { + it('is called when the stepper is blurred', () => { + const onBlurSpy = jest.fn(); + const spinner = mountWithApp( + , + ); + spinner.find('div', {role: 'button'})!.trigger('onBlur'); + expect(onBlurSpy).toHaveBeenCalledTimes(1); + }); + }); }); function noop() {}