diff --git a/packages/mui-material/src/Select/Select.test.js b/packages/mui-material/src/Select/Select.test.js
index 100b69b1ca4a9f..8452ede6fbdc3a 100644
--- a/packages/mui-material/src/Select/Select.test.js
+++ b/packages/mui-material/src/Select/Select.test.js
@@ -152,6 +152,36 @@ describe('', () => {
expect(options[1]).to.have.attribute('data-value', '20');
});
+ it('should select an option when the space key is pressed', () => {
+ const handleChange = spy();
+ const handleKeyDown = spy();
+ const { getAllByRole, getByRole } = render(
+ ,
+ );
+
+ const trigger = getByRole('combobox');
+ fireEvent.mouseDown(trigger);
+
+ const options = getAllByRole('option');
+ fireEvent.keyDown(options[0], { key: 'ArrowDown' });
+ fireEvent.keyDown(options[1], { key: 'ArrowDown' });
+ fireEvent.keyDown(options[2], { key: ' ' });
+
+ expect(handleChange.callCount).to.equal(1);
+ expect(handleKeyDown.callCount).to.equal(3);
+ expect(handleChange.firstCall.args[0].target.value).to.equal('2');
+ });
+
[' ', 'ArrowUp', 'ArrowDown', 'Enter'].forEach((key) => {
it(`should open menu when pressed ${key} key on select`, async () => {
render(
diff --git a/packages/mui-material/src/Select/SelectInput.js b/packages/mui-material/src/Select/SelectInput.js
index a1acee8485330f..2af01b392cbccf 100644
--- a/packages/mui-material/src/Select/SelectInput.js
+++ b/packages/mui-material/src/Select/SelectInput.js
@@ -258,6 +258,21 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
}
};
+ const clonedOnChange = (event, newValue, child) => {
+ // Redefine target to allow name and value to be read.
+ // This allows seamless integration with the most popular form libraries.
+ // https://github.com/mui/material-ui/issues/13485#issuecomment-676048492
+ // Clone the event to not override `target` of the original event.
+ const nativeEvent = event.nativeEvent || event;
+ const clonedEvent = new nativeEvent.constructor(nativeEvent.type, nativeEvent);
+
+ Object.defineProperty(clonedEvent, 'target', {
+ writable: true,
+ value: { value: newValue, name },
+ });
+ onChange(clonedEvent, child);
+ };
+
const handleItemClick = (child) => (event) => {
let newValue;
@@ -286,18 +301,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
setValueState(newValue);
if (onChange) {
- // Redefine target to allow name and value to be read.
- // This allows seamless integration with the most popular form libraries.
- // https://github.com/mui/material-ui/issues/13485#issuecomment-676048492
- // Clone the event to not override `target` of the original event.
- const nativeEvent = event.nativeEvent || event;
- const clonedEvent = new nativeEvent.constructor(nativeEvent.type, nativeEvent);
-
- Object.defineProperty(clonedEvent, 'target', {
- writable: true,
- value: { value: newValue, name },
- });
- onChange(clonedEvent, child);
+ clonedOnChange(event, newValue, child);
}
}
@@ -324,6 +328,22 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
}
};
+ const handleItemKeyDown = (child) => (event) => {
+ if (event.key === ' ') {
+ const newValue = child.props.value;
+ if (newValue !== value) {
+ setValueState(newValue);
+
+ if (onChange) {
+ clonedOnChange(event, newValue, child);
+ }
+ }
+ update(false, event);
+ }
+
+ child?.props?.onKeyDown?.(event);
+ };
+
const open = displayNode !== null && openState;
const handleBlur = (event) => {
@@ -408,6 +428,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
child.props.onKeyUp(event);
}
},
+ onKeyDown: handleItemKeyDown(child),
role: 'option',
selected,
value: undefined, // The value is most likely not a valid HTML attribute.