diff --git a/docs/pages/api-docs/avatar-group.json b/docs/pages/api-docs/avatar-group.json index f267333fde1d97..a82432ee0a6a33 100644 --- a/docs/pages/api-docs/avatar-group.json +++ b/docs/pages/api-docs/avatar-group.json @@ -10,6 +10,7 @@ }, "default": "'medium'" }, + "sx": { "type": { "name": "object" } }, "variant": { "type": { "name": "union", @@ -25,5 +26,5 @@ "filename": "/packages/material-ui/src/AvatarGroup/AvatarGroup.js", "inheritance": null, "demos": "", - "styledComponent": false + "styledComponent": true } diff --git a/docs/translations/api-docs/avatar-group/avatar-group.json b/docs/translations/api-docs/avatar-group/avatar-group.json index 0fc78564fc67ce..cf50f9faa15e67 100644 --- a/docs/translations/api-docs/avatar-group/avatar-group.json +++ b/docs/translations/api-docs/avatar-group/avatar-group.json @@ -5,6 +5,7 @@ "classes": "Override or extend the styles applied to the component. See CSS API below for more details.", "max": "Max avatars to show before +x.", "spacing": "Spacing between avatars.", + "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.", "variant": "The variant to use." }, "classDescriptions": { diff --git a/packages/material-ui/src/AvatarGroup/AvatarGroup.d.ts b/packages/material-ui/src/AvatarGroup/AvatarGroup.d.ts index 2a71f2b4319026..ad82cb1e187772 100644 --- a/packages/material-ui/src/AvatarGroup/AvatarGroup.d.ts +++ b/packages/material-ui/src/AvatarGroup/AvatarGroup.d.ts @@ -1,6 +1,7 @@ import * as React from 'react'; -import { InternalStandardProps as StandardProps } from '@material-ui/core'; +import { InternalStandardProps as StandardProps, Theme } from '@material-ui/core'; import { OverridableStringUnion } from '@material-ui/types'; +import { SxProps } from '@material-ui/system'; export interface AvatarGroupPropsVariantOverrides {} export type AvatarGroupVariantDefaults = Record<'circular' | 'rounded' | 'square', true>; @@ -29,6 +30,10 @@ export interface AvatarGroupProps extends StandardProps; /** * The variant to use. * @default 'circular' diff --git a/packages/material-ui/src/AvatarGroup/AvatarGroup.js b/packages/material-ui/src/AvatarGroup/AvatarGroup.js index 7597deb044bb50..4b49b1099c4ac0 100644 --- a/packages/material-ui/src/AvatarGroup/AvatarGroup.js +++ b/packages/material-ui/src/AvatarGroup/AvatarGroup.js @@ -2,36 +2,74 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { isFragment } from 'react-is'; import clsx from 'clsx'; -import { chainPropTypes } from '@material-ui/utils'; -import { withStyles } from '../styles'; +import { chainPropTypes, deepmerge } from '@material-ui/utils'; +import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled'; +import experimentalStyled from '../styles/experimentalStyled'; +import useThemeProps from '../styles/useThemeProps'; import Avatar from '../Avatar'; +import { getAvatarGroupUtilityClass } from './avatarGroupClasses'; const SPACINGS = { small: -16, medium: null, }; -export const styles = (theme) => ({ +const overridesResolver = (props, styles) => { + return deepmerge(styles.root || {}, {}); +}; + +const useUtilityClasses = (styleProps) => { + const { classes } = styleProps; + + const slots = { + root: ['root'], + avatar: ['avatar'], + }; + + return composeClasses(slots, getAvatarGroupUtilityClass, classes); +}; + +const AvatarGroupRoot = experimentalStyled( + 'div', + {}, + { + name: 'MuiAvatarGroup', + slot: 'Root', + overridesResolver, + } +)({ /* Styles applied to the root element. */ - root: { - display: 'flex', - flexDirection: 'row-reverse', + display: 'flex', + flexDirection: 'row-reverse', +}); + +/* Styles applied to the avatar elements. */ +const AvatarGroupAvatar = experimentalStyled( + Avatar, + {}, + { + name: 'MuiAvatarGroup', + slot: 'Avatar', }, - /* Styles applied to the avatar elements. */ - avatar: { +)( + ({ theme }) => ({ border: `2px solid ${theme.palette.background.default}`, boxSizing: 'content-box', marginLeft: -8, '&:last-child': { marginLeft: 0, }, - }, -}); + }) +); + +const AvatarGroup = React.forwardRef(function AvatarGroup(inProps, ref) { + const props = useThemeProps({ + props: inProps, + name: 'MuiAvatarGroup', + }); -const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) { const { children: childrenProp, - classes, className, max = 5, spacing = 'medium', @@ -40,6 +78,8 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) { } = props; const clampedMax = max < 2 ? 2 : max; + const classes = useUtilityClasses(props); + const children = React.Children.toArray(childrenProp).filter((child) => { if (process.env.NODE_ENV !== 'production') { if (isFragment(child)) { @@ -60,9 +100,9 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) { const marginLeft = spacing && SPACINGS[spacing] !== undefined ? SPACINGS[spacing] : -spacing; return ( -
+ {extraAvatars ? ( - +{extraAvatars} - + ) : null} {children .slice(0, children.length - extraAvatars) @@ -85,7 +125,7 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) { variant: child.props.variant || variant, }); })} -
+ ); }); @@ -125,6 +165,10 @@ AvatarGroup.propTypes = { * @default 'medium' */ spacing: PropTypes.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.number]), + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.object, /** * The variant to use. * @default 'circular' @@ -135,4 +179,4 @@ AvatarGroup.propTypes = { ]), }; -export default withStyles(styles, { name: 'MuiAvatarGroup' })(AvatarGroup); +export default AvatarGroup; diff --git a/packages/material-ui/src/AvatarGroup/AvatarGroup.test.js b/packages/material-ui/src/AvatarGroup/AvatarGroup.test.js index 7e5e1e9af1a155..c719b46329db41 100644 --- a/packages/material-ui/src/AvatarGroup/AvatarGroup.test.js +++ b/packages/material-ui/src/AvatarGroup/AvatarGroup.test.js @@ -1,24 +1,21 @@ import * as React from 'react'; import { expect } from 'chai'; -import { getClasses, createMount, describeConformance, createClientRender } from 'test/utils'; +import { createMount, describeConformanceV5, createClientRender } from 'test/utils'; import Avatar from '@material-ui/core/Avatar'; +import classes from './avatarGroupClasses'; import AvatarGroup from './AvatarGroup'; describe('', () => { const mount = createMount(); - let classes; const render = createClientRender(); - before(() => { - classes = getClasses(); - }); - - describeConformance(, () => ({ + describeConformanceV5(, () => ({ classes, inheritComponent: 'div', mount, + muiName: 'MuiAvatarGroup', refInstanceof: window.HTMLDivElement, - skip: ['componentProp'], + skip: ['componentsProp'], })); it('should display all the avatars', () => { diff --git a/packages/material-ui/src/AvatarGroup/avatarGroupClasses.d.ts b/packages/material-ui/src/AvatarGroup/avatarGroupClasses.d.ts new file mode 100644 index 00000000000000..94056d92ac61c4 --- /dev/null +++ b/packages/material-ui/src/AvatarGroup/avatarGroupClasses.d.ts @@ -0,0 +1,10 @@ +export interface AvatarGroupClasses { + root: string, + avatar: string, +} + +declare const avatarGroupClasses: AvatarGroupClasses; + +export function getAvatarGroupUtilityClass(slot: string): string; + +export default avatarGroupClasses; diff --git a/packages/material-ui/src/AvatarGroup/avatarGroupClasses.js b/packages/material-ui/src/AvatarGroup/avatarGroupClasses.js new file mode 100644 index 00000000000000..0277a4d423f516 --- /dev/null +++ b/packages/material-ui/src/AvatarGroup/avatarGroupClasses.js @@ -0,0 +1,12 @@ +import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled'; + +export function getAvatarGroupUtilityClass(slot) { + return generateUtilityClass('MuiAvatarGroup', slot); +} + +const avatarGroupClasses = generateUtilityClasses('MuiAvatarGroup', [ + 'root', + 'avatar', +]); + +export default avatarGroupClasses; diff --git a/packages/material-ui/src/AvatarGroup/index.d.ts b/packages/material-ui/src/AvatarGroup/index.d.ts index a691e2cb2eff92..90c212c73f297a 100644 --- a/packages/material-ui/src/AvatarGroup/index.d.ts +++ b/packages/material-ui/src/AvatarGroup/index.d.ts @@ -1,2 +1,4 @@ export { default } from './AvatarGroup'; export * from './AvatarGroup'; +export { default as avatarGroupClasses } from './avatarGroupClasses'; +export * from './avatarGroupClasses'; \ No newline at end of file diff --git a/packages/material-ui/src/AvatarGroup/index.js b/packages/material-ui/src/AvatarGroup/index.js index 20c5443b297112..4b1648bd4782ef 100644 --- a/packages/material-ui/src/AvatarGroup/index.js +++ b/packages/material-ui/src/AvatarGroup/index.js @@ -1 +1,3 @@ export { default } from './AvatarGroup'; +export { default as avatarGroupClasses } from './avatarGroupClasses'; +export * from './avatarGroupClasses'; \ No newline at end of file