Skip to content

Commit b2a9ab5

Browse files
committed
Apple useSlot to more components
1 parent 2ccbeba commit b2a9ab5

File tree

11 files changed

+199
-146
lines changed

11 files changed

+199
-146
lines changed

packages/mui-joy/src/Checkbox/Checkbox.tsx

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import PropTypes from 'prop-types';
33
import { OverridableComponent } from '@mui/types';
44
import { unstable_useId as useId, unstable_capitalize as capitalize } from '@mui/utils';
55
import { unstable_composeClasses as composeClasses } from '@mui/base';
6-
import { useSlotProps } from '@mui/base/utils';
76
import { useSwitch } from '@mui/base/SwitchUnstyled';
87
import { styled, useThemeProps } from '../styles';
8+
import useSlot from '../utils/useSlot';
99
import checkboxClasses, { getCheckboxUtilityClass } from './checkboxClasses';
1010
import { CheckboxOwnerState, CheckboxTypeMap } from './CheckboxProps';
1111
import CheckIcon from '../internal/svg-icons/Check';
@@ -188,8 +188,7 @@ const Checkbox = React.forwardRef(function Checkbox(inProps, ref) {
188188
uncheckedIcon,
189189
checkedIcon = defaultCheckedIcon,
190190
label,
191-
component,
192-
componentsProps = {},
191+
component = 'span',
193192
defaultChecked,
194193
disabled: disabledExternalProp,
195194
disableIcon = false,
@@ -261,38 +260,31 @@ const Checkbox = React.forwardRef(function Checkbox(inProps, ref) {
261260
};
262261

263262
const classes = useUtilityClasses(ownerState);
263+
const externalForwardedProps = { ...other, component };
264264

265-
const rootProps = useSlotProps({
265+
const [SlotRoot, rootProps] = useSlot('root', {
266+
ref,
267+
className: classes.root,
266268
elementType: CheckboxRoot,
267-
externalSlotProps: componentsProps.root,
268-
externalForwardedProps: other,
269+
externalForwardedProps,
269270
ownerState,
270-
additionalProps: {
271-
ref,
272-
as: component,
273-
},
274-
className: classes.root,
275271
});
276272

277-
const checkboxProps = useSlotProps({
273+
const [SlotCheckbox, checkboxProps] = useSlot('checkbox', {
274+
className: classes.checkbox,
278275
elementType: CheckboxCheckbox,
279-
externalSlotProps: componentsProps.checkbox,
276+
externalForwardedProps,
280277
ownerState,
281-
className: classes.checkbox,
282278
});
283279

284-
const actionProps = useSlotProps({
280+
const [SlotAction, actionProps] = useSlot('action', {
281+
className: classes.action,
285282
elementType: CheckboxAction,
286-
externalSlotProps: componentsProps.action,
283+
externalForwardedProps,
287284
ownerState,
288-
className: classes.action,
289285
});
290286

291-
const inputProps = useSlotProps({
292-
elementType: CheckboxInput,
293-
getSlotProps: getInputProps,
294-
externalSlotProps: componentsProps.input,
295-
ownerState,
287+
const [SlotInput, inputProps] = useSlot('input', {
296288
additionalProps: {
297289
id,
298290
name,
@@ -306,34 +298,38 @@ const Checkbox = React.forwardRef(function Checkbox(inProps, ref) {
306298
}),
307299
},
308300
className: classes.input,
301+
elementType: CheckboxInput,
302+
externalForwardedProps,
303+
getSlotProps: getInputProps,
304+
ownerState,
309305
});
310306

311-
const labelProps = useSlotProps({
312-
elementType: CheckboxLabel,
313-
externalSlotProps: componentsProps.label,
314-
ownerState,
307+
const [SlotLabel, labelProps] = useSlot('label', {
315308
additionalProps: {
316309
htmlFor: id,
317310
},
318311
className: classes.label,
312+
elementType: CheckboxLabel,
313+
externalForwardedProps,
314+
ownerState,
319315
});
320316

321317
return (
322-
<CheckboxRoot {...rootProps}>
323-
<CheckboxCheckbox {...checkboxProps}>
324-
<CheckboxAction {...actionProps}>
325-
<CheckboxInput {...inputProps} />
326-
</CheckboxAction>
318+
<SlotRoot {...rootProps}>
319+
<SlotCheckbox {...checkboxProps}>
320+
<SlotAction {...actionProps}>
321+
<SlotInput {...inputProps} />
322+
</SlotAction>
327323
{indeterminate && !checked && !disableIcon && indeterminateIcon}
328324
{checked && !disableIcon && checkedIcon}
329325
{!checked && !disableIcon && !indeterminate && uncheckedIcon}
330-
</CheckboxCheckbox>
326+
</SlotCheckbox>
331327
{label && (
332328
<TypographyContext.Provider value>
333-
<CheckboxLabel {...labelProps}>{label}</CheckboxLabel>
329+
<SlotLabel {...labelProps}>{label}</SlotLabel>
334330
</TypographyContext.Provider>
335331
)}
336-
</CheckboxRoot>
332+
</SlotRoot>
337333
);
338334
}) as OverridableComponent<CheckboxTypeMap>;
339335

@@ -376,7 +372,7 @@ Checkbox.propTypes /* remove-proptypes */ = {
376372
* The props used for each slot inside the component.
377373
* @default {}
378374
*/
379-
componentsProps: PropTypes.shape({
375+
slotProps: PropTypes.shape({
380376
action: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
381377
checkbox: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
382378
input: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

packages/mui-joy/src/Checkbox/CheckboxProps.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,35 @@ import { ColorPaletteProp, VariantProp, SxProps } from '../styles/types';
77
export type CheckboxSlot = 'root' | 'checkbox' | 'action' | 'input' | 'label';
88

99
export interface CheckboxPropsVariantOverrides {}
10-
1110
export interface CheckboxPropsColorOverrides {}
12-
1311
export interface CheckboxPropsSizeOverrides {}
1412

1513
interface ComponentsProps {
16-
root?: SlotComponentProps<'span', { sx?: SxProps }, CheckboxOwnerState>;
17-
checkbox?: SlotComponentProps<'span', { sx?: SxProps }, CheckboxOwnerState>;
18-
action?: SlotComponentProps<'span', { sx?: SxProps }, CheckboxOwnerState>;
19-
input?: SlotComponentProps<'input', { sx?: SxProps }, CheckboxOwnerState>;
20-
label?: SlotComponentProps<'label', { sx?: SxProps }, CheckboxOwnerState>;
14+
root?: SlotComponentProps<
15+
'span',
16+
{ component?: React.ElementType; sx?: SxProps },
17+
CheckboxOwnerState
18+
>;
19+
checkbox?: SlotComponentProps<
20+
'span',
21+
{ component?: React.ElementType; sx?: SxProps },
22+
CheckboxOwnerState
23+
>;
24+
action?: SlotComponentProps<
25+
'span',
26+
{ component?: React.ElementType; sx?: SxProps },
27+
CheckboxOwnerState
28+
>;
29+
input?: SlotComponentProps<
30+
'input',
31+
{ component?: React.ElementType; sx?: SxProps },
32+
CheckboxOwnerState
33+
>;
34+
label?: SlotComponentProps<
35+
'label',
36+
{ component?: React.ElementType; sx?: SxProps },
37+
CheckboxOwnerState
38+
>;
2139
}
2240

2341
export interface CheckboxTypeMap<P = {}, D extends React.ElementType = 'span'> {
@@ -32,11 +50,21 @@ export interface CheckboxTypeMap<P = {}, D extends React.ElementType = 'span'> {
3250
* Class name applied to the root element.
3351
*/
3452
className?: string;
53+
/**
54+
* Replace the default slots.
55+
*/
56+
slots?: {
57+
root?: React.ElementType;
58+
checkbox?: React.ElementType;
59+
action?: React.ElementType;
60+
input?: React.ElementType;
61+
label?: React.ElementType;
62+
};
3563
/**
3664
* The props used for each slot inside the component.
3765
* @default {}
3866
*/
39-
componentsProps?: ComponentsProps;
67+
slotProps?: ComponentsProps;
4068
/**
4169
* The color of the component. It supports those theme colors that make sense for this component.
4270
* @default 'neutral'

packages/mui-joy/src/Divider/Divider.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { unstable_capitalize as capitalize } from '@mui/utils';
55
import { OverridableComponent } from '@mui/types';
66
import composeClasses from '@mui/base/composeClasses';
77
import { styled, useThemeProps } from '../styles';
8+
import useSlot from '../utils/useSlot';
89
import { DividerOwnerState, DividerTypeMap } from './DividerProps';
910
import { getDividerUtilityClass } from './dividerClasses';
1011

@@ -117,24 +118,24 @@ const Divider = React.forwardRef(function Divider(inProps, ref) {
117118

118119
const classes = useUtilityClasses(ownerState);
119120

120-
return (
121-
<DividerRoot
122-
ref={ref}
123-
as={component}
124-
className={clsx(classes.root, className)}
125-
ownerState={ownerState}
126-
role={role}
127-
{...(role === 'separator' &&
121+
const [SlotRoot, rootProps] = useSlot('root', {
122+
additionalProps: {
123+
role,
124+
...(role === 'separator' &&
128125
orientation === 'vertical' && {
129126
// The implicit aria-orientation of separator is 'horizontal'
130127
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/separator_role
131128
'aria-orientation': 'vertical',
132-
})}
133-
{...other}
134-
>
135-
{children}
136-
</DividerRoot>
137-
);
129+
}),
130+
},
131+
ref,
132+
className: clsx(classes.root, className),
133+
elementType: DividerRoot,
134+
externalForwardedProps: { ...other, component },
135+
ownerState,
136+
});
137+
138+
return <SlotRoot {...rootProps}>{children}</SlotRoot>;
138139
}) as OverridableComponent<DividerTypeMap>;
139140

140141
Divider.propTypes /* remove-proptypes */ = {

packages/mui-joy/src/FormControl/FormControl.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { OverridableComponent } from '@mui/types';
55
import { unstable_useId as useId, unstable_capitalize as capitalize } from '@mui/utils';
66
import composeClasses from '@mui/base/composeClasses';
77
import { useThemeProps } from '../styles';
8+
import useSlot from '../utils/useSlot';
89
import styled from '../styles/styled';
910
import FormControlContext from './FormControlContext';
1011
import formControlClasses, { getFormControlUtilityClass } from './formControlClasses';
@@ -131,15 +132,17 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) {
131132
[color, disabled, error, helperText, id, registerEffect, required, size],
132133
);
133134

135+
const [SlotRoot, rootProps] = useSlot('root', {
136+
ref,
137+
className: clsx(classes.root, className),
138+
elementType: FormControlRoot,
139+
externalForwardedProps: { ...other, component },
140+
ownerState,
141+
});
142+
134143
return (
135144
<FormControlContext.Provider value={formControlContextValue}>
136-
<FormControlRoot
137-
as={component}
138-
ownerState={ownerState}
139-
className={clsx(classes.root, className)}
140-
ref={ref}
141-
{...other}
142-
/>
145+
<SlotRoot {...rootProps} />
143146
</FormControlContext.Provider>
144147
);
145148
}) as OverridableComponent<FormControlTypeMap>;

packages/mui-joy/src/FormHelperText/FormHelperText.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
33
import { OverridableComponent } from '@mui/types';
44
import { unstable_useForkRef as useForkRef } from '@mui/utils';
55
import composeClasses from '@mui/base/composeClasses';
6-
import { useSlotProps } from '@mui/base/utils';
76
import { styled, useThemeProps } from '../styles';
7+
import useSlot from '../utils/useSlot';
88
import { FormHelperTextProps, FormHelperTextTypeMap } from './FormHelperTextProps';
99
import { getFormHelperTextUtilityClass } from './formHelperTextClasses';
1010
import FormControlContext from '../FormControl/FormControlContext';
@@ -41,7 +41,7 @@ const FormHelperText = React.forwardRef(function FormHelperText(inProps, ref) {
4141
name: 'JoyFormHelperText',
4242
});
4343

44-
const { children, component, ...other } = props;
44+
const { children, component = 'p', ...other } = props;
4545
const rootRef = React.useRef<HTMLElement | null>(null);
4646
const handleRef = useForkRef(rootRef, ref);
4747
const formControl = React.useContext(FormControlContext);
@@ -60,20 +60,18 @@ const FormHelperText = React.forwardRef(function FormHelperText(inProps, ref) {
6060

6161
const classes = useUtilityClasses();
6262

63-
const rootProps = useSlotProps({
64-
elementType: FormHelperTextRoot,
65-
externalSlotProps: {},
66-
externalForwardedProps: other,
67-
ownerState,
63+
const [SlotRoot, rootProps] = useSlot('root', {
6864
additionalProps: {
69-
ref: handleRef,
70-
as: component,
7165
id: formControl?.['aria-describedby'],
7266
},
67+
ref: handleRef,
7368
className: classes.root,
69+
elementType: FormHelperTextRoot,
70+
externalForwardedProps: { ...other, component },
71+
ownerState,
7472
});
7573

76-
return <FormHelperTextRoot {...rootProps}>{children}</FormHelperTextRoot>;
74+
return <SlotRoot {...rootProps}>{children}</SlotRoot>;
7775
}) as OverridableComponent<FormHelperTextTypeMap>;
7876

7977
FormHelperText.propTypes /* remove-proptypes */ = {

0 commit comments

Comments
 (0)