From 56c59c69db8b1ab84ea42b54eaa57b7893275787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dudak?= Date: Tue, 13 Dec 2022 15:19:11 +0100 Subject: [PATCH] [Button][base] Set active class when a subcomponent is clicked (#35410) --- .../src/ButtonUnstyled/useButton.test.tsx | 40 +++++++++++++++++++ .../mui-base/src/ButtonUnstyled/useButton.ts | 18 ++++----- .../src/ButtonUnstyled/useButton.types.ts | 1 - 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/packages/mui-base/src/ButtonUnstyled/useButton.test.tsx b/packages/mui-base/src/ButtonUnstyled/useButton.test.tsx index 18aebe3319c1ab..b3f066f44091ad 100644 --- a/packages/mui-base/src/ButtonUnstyled/useButton.test.tsx +++ b/packages/mui-base/src/ButtonUnstyled/useButton.test.tsx @@ -41,6 +41,46 @@ describe('useButton', () => { fireEvent.keyUp(button, { key: ' ' }); expect(button).not.to.have.class('active'); }); + + it('is set when clicked on an element inside the button', () => { + function TestComponent() { + const buttonRef = React.useRef(null); + const { active, getRootProps } = useButton({ ref: buttonRef }); + + return ( + + ); + } + + const { getByText, getByRole } = render(); + const span = getByText('Click here'); + const button = getByRole('button'); + fireEvent.mouseDown(span); + expect(button).to.have.class('active'); + }); + + it('is unset when mouse button is released above another element', () => { + function TestComponent() { + const buttonRef = React.useRef(null); + const { active, getRootProps } = useButton({ ref: buttonRef }); + + return ( +
+
+ ); + } + + const { getByRole, getByTestId } = render(); + const button = getByRole('button'); + const background = getByTestId('parent'); + fireEvent.mouseDown(button); + expect(button).to.have.class('active'); + fireEvent.mouseUp(background); + expect(button).not.to.have.class('active'); + }); }); describe('when using a span element', () => { diff --git a/packages/mui-base/src/ButtonUnstyled/useButton.ts b/packages/mui-base/src/ButtonUnstyled/useButton.ts index ec5e1cfea2cfc3..5ad1c81dc671a8 100644 --- a/packages/mui-base/src/ButtonUnstyled/useButton.ts +++ b/packages/mui-base/src/ButtonUnstyled/useButton.ts @@ -91,21 +91,20 @@ export default function useButton(parameters: UseButtonParameters) { }; const createHandleMouseDown = (otherHandlers: EventHandlers) => (event: React.MouseEvent) => { - if (event.target === event.currentTarget && !disabled) { + if (!disabled) { setActive(true); + document.addEventListener( + 'mouseup', + () => { + setActive(false); + }, + { once: true }, + ); } otherHandlers.onMouseDown?.(event); }; - const createHandleMouseUp = (otherHandlers: EventHandlers) => (event: React.MouseEvent) => { - if (event.target === event.currentTarget) { - setActive(false); - } - - otherHandlers.onMouseUp?.(event); - }; - const createHandleKeyDown = (otherHandlers: EventHandlers) => (event: React.KeyboardEvent) => { otherHandlers.onKeyDown?.(event); @@ -213,7 +212,6 @@ export default function useButton(parameters: UseButtonParameters) { onKeyUp: createHandleKeyUp(externalEventHandlers), onMouseDown: createHandleMouseDown(externalEventHandlers), onMouseLeave: createHandleMouseLeave(externalEventHandlers), - onMouseUp: createHandleMouseUp(externalEventHandlers), ref: handleRef, }; }; diff --git a/packages/mui-base/src/ButtonUnstyled/useButton.types.ts b/packages/mui-base/src/ButtonUnstyled/useButton.types.ts index 60dddbfe2d5b13..d2665a2ac3dd10 100644 --- a/packages/mui-base/src/ButtonUnstyled/useButton.types.ts +++ b/packages/mui-base/src/ButtonUnstyled/useButton.types.ts @@ -12,7 +12,6 @@ export interface UseButtonRootSlotOwnProps { onKeyUp: React.KeyboardEventHandler; onMouseDown: React.MouseEventHandler; onMouseLeave: React.MouseEventHandler; - onMouseUp: React.MouseEventHandler; ref: React.Ref; }