Skip to content

Commit

Permalink
[Avatar] Migrate AvatarGroup to emotion (#24452)
Browse files Browse the repository at this point in the history
  • Loading branch information
praveenkumar-kalidass committed Jan 19, 2021
1 parent 5941485 commit 0edc67f
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 32 deletions.
3 changes: 2 additions & 1 deletion docs/pages/api-docs/avatar-group.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"default": "'medium'"
},
"sx": { "type": { "name": "object" } },
"variant": {
"type": {
"name": "union",
Expand All @@ -25,5 +26,5 @@
"filename": "/packages/material-ui/src/AvatarGroup/AvatarGroup.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/avatars/\">Avatars</a></li></ul>",
"styledComponent": false
"styledComponent": true
}
1 change: 1 addition & 0 deletions docs/translations/api-docs/avatar-group/avatar-group.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> 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 <a href=\"/system/basics/#the-sx-prop\">`sx` page</a> for more details.",
"variant": "The variant to use."
},
"classDescriptions": {
Expand Down
7 changes: 6 additions & 1 deletion packages/material-ui/src/AvatarGroup/AvatarGroup.d.ts
Original file line number Diff line number Diff line change
@@ -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>;
Expand Down Expand Up @@ -29,6 +30,10 @@ export interface AvatarGroupProps extends StandardProps<React.HTMLAttributes<HTM
* @default 'medium'
*/
spacing?: 'small' | 'medium' | number;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
/**
* The variant to use.
* @default 'circular'
Expand Down
98 changes: 81 additions & 17 deletions packages/material-ui/src/AvatarGroup/AvatarGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,81 @@ 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 avatarGroupClasses, { getAvatarGroupUtilityClass } from './avatarGroupClasses';

const SPACINGS = {
small: -16,
medium: null,
};

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
display: 'flex',
flexDirection: 'row-reverse',
const overridesResolver = (props, styles) => {
return deepmerge(styles.root || {}, {
[`& .${avatarGroupClasses.avatar}`]: styles.avatar,
});
};

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 avatar elements. */
avatar: {
)(({ theme }) => ({
[`& .MuiAvatar-root`]: {
border: `2px solid ${theme.palette.background.default}`,
boxSizing: 'content-box',
marginLeft: -8,
'&:last-child': {
marginLeft: 0,
},
},
});
/* Styles applied to the root element. */
display: 'flex',
flexDirection: 'row-reverse',
}));

const AvatarGroupAvatar = experimentalStyled(
Avatar,
{},
{
name: 'MuiAvatarGroup',
slot: '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',
Expand All @@ -40,6 +85,15 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
} = props;
const clampedMax = max < 2 ? 2 : max;

const styleProps = {
...other,
max,
spacing,
variant,
};

const classes = useUtilityClasses(styleProps);

const children = React.Children.toArray(childrenProp).filter((child) => {
if (process.env.NODE_ENV !== 'production') {
if (isFragment(child)) {
Expand All @@ -60,17 +114,23 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
const marginLeft = spacing && SPACINGS[spacing] !== undefined ? SPACINGS[spacing] : -spacing;

return (
<div className={clsx(classes.root, className)} ref={ref} {...other}>
<AvatarGroupRoot
styleProps={styleProps}
className={clsx(classes.root, className)}
ref={ref}
{...other}
>
{extraAvatars ? (
<Avatar
<AvatarGroupAvatar
styleProps={styleProps}
className={classes.avatar}
style={{
marginLeft,
}}
variant={variant}
>
+{extraAvatars}
</Avatar>
</AvatarGroupAvatar>
) : null}
{children
.slice(0, children.length - extraAvatars)
Expand All @@ -85,7 +145,7 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
variant: child.props.variant || variant,
});
})}
</div>
</AvatarGroupRoot>
);
});

Expand Down Expand Up @@ -125,6 +185,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'
Expand All @@ -135,4 +199,4 @@ AvatarGroup.propTypes = {
]),
};

export default withStyles(styles, { name: 'MuiAvatarGroup' })(AvatarGroup);
export default AvatarGroup;
30 changes: 17 additions & 13 deletions packages/material-ui/src/AvatarGroup/AvatarGroup.test.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
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('<AvatarGroup />', () => {
const mount = createMount();
let classes;
const render = createClientRender();

before(() => {
classes = getClasses(<AvatarGroup />);
});

describeConformance(<AvatarGroup />, () => ({
classes,
inheritComponent: 'div',
mount,
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
}));
describeConformanceV5(
<AvatarGroup>
<div />
</AvatarGroup>,
() => ({
classes,
inheritComponent: 'div',
mount,
muiName: 'MuiAvatarGroup',
refInstanceof: window.HTMLDivElement,
testDeepOverrides: { slotName: 'avatar', slotClassName: classes.avatar },
testVariantProps: { max: 10, spacing: 'small', variant: 'square' },
skip: ['componentsProp'],
}),
);

it('should display all the avatars', () => {
const { container } = render(
Expand Down
10 changes: 10 additions & 0 deletions packages/material-ui/src/AvatarGroup/avatarGroupClasses.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface AvatarGroupClasses {
root: string;
avatar: string;
}

declare const avatarGroupClasses: AvatarGroupClasses;

export function getAvatarGroupUtilityClass(slot: string): string;

export default avatarGroupClasses;
9 changes: 9 additions & 0 deletions packages/material-ui/src/AvatarGroup/avatarGroupClasses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';

export function getAvatarGroupUtilityClass(slot) {
return generateUtilityClass('MuiAvatarGroup', slot);
}

const avatarGroupClasses = generateUtilityClasses('MuiAvatarGroup', ['root', 'avatar']);

export default avatarGroupClasses;
2 changes: 2 additions & 0 deletions packages/material-ui/src/AvatarGroup/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default } from './AvatarGroup';
export * from './AvatarGroup';
export { default as avatarGroupClasses } from './avatarGroupClasses';
export * from './avatarGroupClasses';
2 changes: 2 additions & 0 deletions packages/material-ui/src/AvatarGroup/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default } from './AvatarGroup';
export { default as avatarGroupClasses } from './avatarGroupClasses';
export * from './avatarGroupClasses';

0 comments on commit 0edc67f

Please sign in to comment.