Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AvatarGroup] Add max avatar prop #19853

Merged
merged 7 commits into from
Mar 16, 2020
Merged
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
1 change: 1 addition & 0 deletions docs/pages/api-docs/avatar-group.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
|:-----|:-----|:--------|:------------|
| <span class="prop-name">children</span> | <span class="prop-type">node</span> | | The avatars to stack. |
| <span class="prop-name">classes</span> | <span class="prop-type">object</span> | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. |
| <span class="prop-name">max</span> | <span class="prop-type">number</span> | <span class="prop-default">5</span> | Max avatars to show before +x. |
| <span class="prop-name">spacing</span> | <span class="prop-type">'medium'<br>&#124;&nbsp;'small'<br>&#124;&nbsp;number</span> | <span class="prop-default">'medium'</span> | Spacing between avatars. |

The `ref` is forwarded to the root element.
Expand Down
7 changes: 2 additions & 5 deletions docs/src/pages/components/avatars/GroupAvatars.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import React from 'react';
import Avatar from '@material-ui/core/Avatar';
import AvatarGroup from '@material-ui/lab/AvatarGroup';
import Tooltip from '@material-ui/core/Tooltip';

export default function GroupAvatars() {
return (
<AvatarGroup>
<AvatarGroup max={3}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
<Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" />
<Tooltip title="Foo • Bar • Baz">
<Avatar>+3</Avatar>
</Tooltip>
<Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" />
</AvatarGroup>
);
}
7 changes: 2 additions & 5 deletions docs/src/pages/components/avatars/GroupAvatars.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import React from 'react';
import Avatar from '@material-ui/core/Avatar';
import AvatarGroup from '@material-ui/lab/AvatarGroup';
import Tooltip from '@material-ui/core/Tooltip';

export default function GroupAvatars() {
return (
<AvatarGroup>
<AvatarGroup max={3}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
<Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" />
<Tooltip title="Foo • Bar • Baz">
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
<Avatar>+3</Avatar>
</Tooltip>
<Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" />
</AvatarGroup>
);
}
4 changes: 4 additions & 0 deletions packages/material-ui-lab/src/AvatarGroup/AvatarGroup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export interface AvatarGroupProps
* The avatars to stack.
*/
children: React.ReactNode;
/**
* Max avatars to show before +x.
*/
max?: number;
/**
* Spacing between avatars.
*/
Expand Down
29 changes: 27 additions & 2 deletions packages/material-ui-lab/src/AvatarGroup/AvatarGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { isFragment } from 'react-is';
import clsx from 'clsx';
import { withStyles } from '@material-ui/core/styles';
import Avatar from '@material-ui/core/Avatar';

const SPACINGS = {
small: -16,
Expand All @@ -22,7 +23,14 @@ export const styles = theme => ({
});

const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
const { children: childrenProp, classes, className, spacing = 'medium', ...other } = props;
const {
children: childrenProp,
classes,
className,
spacing = 'medium',
max = 5,
...other
} = props;

const children = React.Children.toArray(childrenProp).filter(child => {
if (process.env.NODE_ENV !== 'production') {
Expand All @@ -39,9 +47,11 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
return React.isValidElement(child);
});

const extraAvatars = children.length > max ? children.length - max : 0;

return (
<div className={clsx(classes.root, className)} ref={ref} {...other}>
{children.map((child, index) => {
{children.slice(0, children.length - extraAvatars).map((child, index) => {
return React.cloneElement(child, {
className: clsx(child.props.className, classes.avatar),
style: {
Expand All @@ -51,6 +61,17 @@ const AvatarGroup = React.forwardRef(function AvatarGroup(props, ref) {
},
});
})}
{extraAvatars ? (
<Avatar
className={classes.avatar}
style={{
eps1lon marked this conversation as resolved.
Show resolved Hide resolved
zIndex: 0,
marginLeft: spacing && SPACINGS[spacing] !== undefined ? SPACINGS[spacing] : -spacing,
}}
>
+{extraAvatars}
</Avatar>
) : null}
</div>
);
});
Expand All @@ -73,6 +94,10 @@ AvatarGroup.propTypes = {
* @ignore
*/
className: PropTypes.string,
/**
* Max avatars to show before +x.
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
*/
max: PropTypes.number,
/**
* Spacing between avatars.
*/
Expand Down
16 changes: 16 additions & 0 deletions packages/material-ui-lab/src/AvatarGroup/AvatarGroup.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import * as React from 'react';
import { expect } from 'chai';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import describeConformance from '@material-ui/core/test-utils/describeConformance';
import { createClientRender } from 'test/utils/createClientRender';
import AvatarGroup from './AvatarGroup';
import { Avatar } from '@material-ui/core';

describe('<AvatarGroup />', () => {
let mount;
let classes;
const render = createClientRender();

before(() => {
mount = createMount({ strict: true });
Expand All @@ -23,4 +27,16 @@ describe('<AvatarGroup />', () => {
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
}));

it('should not display all the avatars', () => {
const { container } = render(
<AvatarGroup max={1}>
<Avatar src="broken-url" />
<Avatar src="broken-url" />
<Avatar src="broken-url" />
</AvatarGroup>,
);
expect(container.querySelectorAll('img').length).to.equal(1);
expect(container.textContent).to.equal('+2');
});
});