Skip to content

Commit c9f1d74

Browse files
committed
Apply useSlot to Avatar and pass className prop to the root
1 parent ecfe5c0 commit c9f1d74

File tree

2 files changed

+56
-25
lines changed

2 files changed

+56
-25
lines changed

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

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import * as React from 'react';
22
import PropTypes from 'prop-types';
3+
import clsx from 'clsx';
34
import { unstable_composeClasses as composeClasses } from '@mui/base';
4-
import { useSlotProps } from '@mui/base/utils';
55
import { OverridableComponent } from '@mui/types';
66
import { unstable_capitalize as capitalize } from '@mui/utils';
77
import { useThemeProps } from '../styles';
8+
import useSlot from '../utils/useSlot';
89
import styled from '../styles/styled';
910
import Person from '../internal/svg-icons/Person';
1011
import { getAvatarUtilityClass } from './avatarClasses';
@@ -149,6 +150,7 @@ const Avatar = React.forwardRef(function Avatar(inProps, ref) {
149150
color: colorProp = 'neutral',
150151
component = 'div',
151152
componentsProps = {},
153+
className,
152154
size: sizeProp = 'md',
153155
variant: variantProp = 'soft',
154156
imgProps,
@@ -186,50 +188,47 @@ const Avatar = React.forwardRef(function Avatar(inProps, ref) {
186188
const hasImgNotFailing = hasImg && loaded !== 'error';
187189

188190
const classes = useUtilityClasses(ownerState);
191+
const externalForwardedProps = { ...other, component, componentsProps };
189192

190-
const imageProps = useSlotProps({
191-
elementType: AvatarImg,
192-
externalSlotProps: componentsProps.img,
193+
const [SlotRoot, rootProps] = useSlot('root', {
194+
ref,
195+
className: clsx(classes.root, className),
196+
elementType: AvatarRoot,
197+
externalForwardedProps,
193198
ownerState,
199+
});
200+
201+
const [SlotImg, imageProps] = useSlot('img', {
194202
additionalProps: {
195203
alt,
196204
src,
197205
srcSet,
198206
...imgProps,
199207
},
200208
className: classes.img,
209+
elementType: AvatarImg,
210+
externalForwardedProps,
211+
ownerState,
201212
});
202213

203-
const fallbackProps = useSlotProps({
214+
const [SlotFallback, fallbackProps] = useSlot('fallback', {
215+
className: classes.fallback,
204216
elementType: AvatarFallback,
205-
externalSlotProps: componentsProps.fallback,
217+
externalForwardedProps,
206218
ownerState,
207-
className: classes.fallback,
208219
});
209220

210221
if (hasImgNotFailing) {
211-
children = <AvatarImg {...imageProps} />;
222+
children = <SlotImg {...imageProps} />;
212223
} else if (childrenProp != null) {
213224
children = childrenProp;
214225
} else if (hasImg && alt) {
215226
children = alt[0];
216227
} else {
217-
children = <AvatarFallback {...fallbackProps} />;
228+
children = <SlotFallback {...fallbackProps} />;
218229
}
219230

220-
const rootProps = useSlotProps({
221-
elementType: AvatarRoot,
222-
externalSlotProps: componentsProps.root,
223-
ownerState,
224-
externalForwardedProps: other,
225-
additionalProps: {
226-
ref,
227-
as: component,
228-
},
229-
className: classes.root,
230-
});
231-
232-
return <AvatarRoot {...rootProps}>{children}</AvatarRoot>;
231+
return <SlotRoot {...rootProps}>{children}</SlotRoot>;
233232
}) as OverridableComponent<AvatarTypeMap>;
234233

235234
Avatar.propTypes /* remove-proptypes */ = {
@@ -247,6 +246,10 @@ Avatar.propTypes /* remove-proptypes */ = {
247246
* This can be an element, or just a string.
248247
*/
249248
children: PropTypes.node,
249+
/**
250+
* @ignore
251+
*/
252+
className: PropTypes.string,
250253
/**
251254
* The color of the component. It supports those theme colors that make sense for this component.
252255
* @default 'neutral'
@@ -260,6 +263,14 @@ Avatar.propTypes /* remove-proptypes */ = {
260263
* Either a string to use a HTML element or a component.
261264
*/
262265
component: PropTypes.elementType,
266+
/**
267+
* Replace the default slots.
268+
*/
269+
components: PropTypes.shape({
270+
fallback: PropTypes.elementType,
271+
img: PropTypes.elementType,
272+
root: PropTypes.elementType,
273+
}),
263274
/**
264275
* The props used for each slot inside the component.
265276
* @default {}

packages/mui-joy/src/Avatar/AvatarProps.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,21 @@ export interface AvatarPropsVariantOverrides {}
1010
export interface AvatarPropsSizeOverrides {}
1111

1212
interface ComponentsProps {
13-
root?: SlotComponentProps<'div', { sx?: SxProps }, AvatarOwnerState>;
14-
img?: SlotComponentProps<'img', { sx?: SxProps }, AvatarOwnerState>;
15-
fallback?: SlotComponentProps<'svg', { sx?: SxProps }, AvatarOwnerState>;
13+
root?: SlotComponentProps<
14+
'div',
15+
{ component?: React.ElementType; sx?: SxProps },
16+
AvatarOwnerState
17+
>;
18+
img?: SlotComponentProps<
19+
'img',
20+
{ component?: React.ElementType; sx?: SxProps },
21+
AvatarOwnerState
22+
>;
23+
fallback?: SlotComponentProps<
24+
'svg',
25+
{ component?: React.ElementType; sx?: SxProps },
26+
AvatarOwnerState
27+
>;
1628
}
1729

1830
export interface AvatarTypeMap<P = {}, D extends React.ElementType = 'div'> {
@@ -27,6 +39,14 @@ export interface AvatarTypeMap<P = {}, D extends React.ElementType = 'div'> {
2739
* This can be an element, or just a string.
2840
*/
2941
children?: React.ReactNode;
42+
/**
43+
* Replace the default slots.
44+
*/
45+
components?: {
46+
root?: React.ElementType;
47+
img?: React.ElementType;
48+
fallback?: React.ElementType;
49+
};
3050
/**
3151
* The props used for each slot inside the component.
3252
* @default {}

0 commit comments

Comments
 (0)