Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/translations/api-docs/checkbox/checkbox.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"icon": { "description": "The icon to display when the component is unchecked." },
"id": { "description": "The id of the <code>input</code> element." },
"indeterminate": {
"description": "If <code>true</code>, the component appears indeterminate. This does not set the native input element to indeterminate due to inconsistent behavior across browsers. However, we set a <code>data-indeterminate</code> attribute on the <code>input</code>."
"description": "If <code>true</code>, the component appears indeterminate. This sets the native input element to indeterminate, and we also set a <code>data-indeterminate</code> attribute on the <code>input</code>."
},
"indeterminateIcon": {
"description": "The icon to display when the component is indeterminate."
Expand Down
5 changes: 2 additions & 3 deletions packages/mui-material/src/Checkbox/Checkbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ export interface CheckboxProps
id?: SwitchBaseProps['id'] | undefined;
/**
* If `true`, the component appears indeterminate.
* This does not set the native input element to indeterminate due
* to inconsistent behavior across browsers.
* However, we set a `data-indeterminate` attribute on the `input`.
* This sets the native input element to indeterminate,
* and we also set a `data-indeterminate` attribute on the `input`.
* @default false
*/
indeterminate?: boolean | undefined;
Expand Down
35 changes: 24 additions & 11 deletions packages/mui-material/src/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import memoTheme from '../utils/memoTheme';
import createSimplePaletteValueFilter from '../utils/createSimplePaletteValueFilter';
import { useDefaultProps } from '../DefaultPropsProvider';
import { mergeSlotProps } from '../utils';
import useEnhancedEffect from '../utils/useEnhancedEffect';
import useForkRef from '../utils/useForkRef';
import useSlot from '../utils/useSlot';

const useUtilityClasses = (ownerState) => {
Expand Down Expand Up @@ -150,7 +152,17 @@ const Checkbox = React.forwardRef(function Checkbox(inProps, ref) {

const classes = useUtilityClasses(ownerState);

const externalInputProps = slotProps.input;
const externalInputProps =
typeof slotProps.input === 'function' ? slotProps.input(ownerState) : slotProps.input;

const inputRef = React.useRef(null);
const handleInputRef = useForkRef(inputRef, externalInputProps?.ref);

useEnhancedEffect(() => {
if (inputRef.current) {
inputRef.current.indeterminate = indeterminate;
}
}, [indeterminate]);

const [RootSlot, rootSlotProps] = useSlot('root', {
ref,
Expand All @@ -176,15 +188,17 @@ const Checkbox = React.forwardRef(function Checkbox(inProps, ref) {
disableRipple: props.disableRipple,
slots,
slotProps: {
input: mergeSlotProps(
typeof externalInputProps === 'function'
? externalInputProps(ownerState)
: externalInputProps,
{
input: {
...mergeSlotProps(externalInputProps, {
'data-indeterminate': indeterminate,
'aria-checked': indeterminate ? 'mixed' : undefined,
},
),
// Activating a checkbox clears its native indeterminate state, restore it.
onChange: (event) => {
event.target.indeterminate = indeterminate;
},
}),
ref: handleInputRef,
},
},
},
});
Expand Down Expand Up @@ -249,9 +263,8 @@ Checkbox.propTypes /* remove-proptypes */ = {
id: PropTypes.string,
/**
* If `true`, the component appears indeterminate.
* This does not set the native input element to indeterminate due
* to inconsistent behavior across browsers.
* However, we set a `data-indeterminate` attribute on the `input`.
* This sets the native input element to indeterminate,
* and we also set a `data-indeterminate` attribute on the `input`.
* @default false
*/
indeterminate: PropTypes.bool,
Expand Down
19 changes: 19 additions & 0 deletions packages/mui-material/src/Checkbox/Checkbox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,25 @@ describe('<Checkbox />', () => {
render(<Checkbox />);
expect(screen.getByRole('checkbox')).not.to.have.attribute('aria-checked');
});

it('should set the indeterminate property on the input', () => {
render(<Checkbox indeterminate />);
expect(screen.getByRole('checkbox')).to.have.property('indeterminate', true);
});

it('should unset the indeterminate property on the input when no longer indeterminate', () => {
const { setProps } = render(<Checkbox indeterminate />);

setProps({ indeterminate: false });
expect(screen.getByRole('checkbox')).to.have.property('indeterminate', false);
});

it('should keep the indeterminate property on the input after a click', async () => {
const { user } = render(<Checkbox indeterminate />);

await user.click(screen.getByRole('checkbox'));
expect(screen.getByRole('checkbox')).to.have.property('indeterminate', true);
});
});

describe('prop: size', () => {
Expand Down
Loading