diff --git a/packages/mui-joy/src/Autocomplete/Autocomplete.test.tsx b/packages/mui-joy/src/Autocomplete/Autocomplete.test.tsx index 2e0aca80fd9019..a01c424158df58 100644 --- a/packages/mui-joy/src/Autocomplete/Autocomplete.test.tsx +++ b/packages/mui-joy/src/Autocomplete/Autocomplete.test.tsx @@ -761,6 +761,15 @@ describe('Joy ', () => { }); }); + it('should open popup when clicked on the root element', () => { + const handleOpen = spy(); + render(); + + const root = document.querySelector(`.${classes.root}`)!; + fireEvent.click(root); + expect(handleOpen.callCount).to.equal(1); + }); + it('does not clear the textbox on Escape', () => { const handleChange = spy(); render( diff --git a/packages/mui-joy/src/Autocomplete/Autocomplete.tsx b/packages/mui-joy/src/Autocomplete/Autocomplete.tsx index 3dd22737ade04b..4a2610227091ce 100644 --- a/packages/mui-joy/src/Autocomplete/Autocomplete.tsx +++ b/packages/mui-joy/src/Autocomplete/Autocomplete.tsx @@ -381,6 +381,8 @@ const Autocomplete = React.forwardRef(function Autocomplete( unstable_isActiveElementInListbox: defaultIsActiveElementInListbox, }); + const { onMouseDown: handleInputMouseDown } = getInputProps(); + const { onClick: handleRootOnClick } = getRootProps(); const hasClearIcon = !disableClearable && !disabled && dirty && !readOnly; const hasPopupIcon = (!freeSolo || forcePopupIcon === true) && forcePopupIcon !== false; @@ -449,6 +451,16 @@ const Autocomplete = React.forwardRef(function Autocomplete( externalForwardedProps: other, ownerState, getSlotProps: getRootProps, + additionalProps: { + onClick: (event: React.MouseEvent) => { + if (handleRootOnClick) { + handleRootOnClick(event); + } + if (event.currentTarget === event.target && handleInputMouseDown) { + handleInputMouseDown(event as React.MouseEvent); + } + }, + }, }); const [SlotWrapper, wrapperProps] = useSlot('wrapper', { diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.js b/packages/mui-material/src/Autocomplete/Autocomplete.js index 539435fe2a190c..a59fee037dcf83 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.js @@ -472,6 +472,8 @@ const Autocomplete = React.forwardRef(function Autocomplete(inProps, ref) { const hasClearIcon = !disableClearable && !disabled && dirty && !readOnly; const hasPopupIcon = (!freeSolo || forcePopupIcon === true) && forcePopupIcon !== false; + const { onMouseDown: handleInputMouseDown } = getInputProps(); + // If you modify this, make sure to keep the `AutocompleteOwnerState` type in sync. const ownerState = { ...props, @@ -575,6 +577,11 @@ const Autocomplete = React.forwardRef(function Autocomplete(inProps, ref) { ref: setAnchorEl, className: classes.inputRoot, startAdornment, + onClick: (event) => { + if (event.target === event.currentTarget) { + handleInputMouseDown(event); + } + }, ...((hasClearIcon || hasPopupIcon) && { endAdornment: ( diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.test.js b/packages/mui-material/src/Autocomplete/Autocomplete.test.js index 21b3304c95b955..668a7fe5a3f748 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.test.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.test.js @@ -963,6 +963,23 @@ describe('', () => { }); }); + it('should open popup when clicked on the root element', () => { + const handleOpen = spy(); + const ref = React.createRef(); + render( + ( + + )} + />, + ); + + fireEvent.click(ref.current); + expect(handleOpen.callCount).to.equal(1); + }); + it('does not clear the textbox on Escape', () => { const handleChange = spy(); render(