Skip to content

Commit

Permalink
feat(avatar): add status indicator support in avatar
Browse files Browse the repository at this point in the history
  • Loading branch information
anuradha9712 committed Dec 11, 2024
1 parent 0164f24 commit 5885784
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 1 deletion.
11 changes: 11 additions & 0 deletions core/components/atoms/avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export interface AvatarProps extends BaseProps {
* Show presence indicator for the `Avatar`
*/
presence?: TPresence;
/**
* Show status indicator for the `Avatar`
*/
status?: React.ReactNode;
/**
* Stroke color of `Presence indicator` & `Status indicator` in `Avatar`
*/
Expand All @@ -88,6 +92,7 @@ export const Avatar = (props: AvatarProps) => {
tooltipSuffix,
tabIndex,
presence,
status,
strokeColor,
role = 'presentation',
} = props;
Expand All @@ -112,6 +117,7 @@ export const Avatar = (props: AvatarProps) => {

const darkAppearance = ['secondary', 'success', 'warning', 'accent1', 'accent4'];
const showPresence = presence && !disabled && shape === 'round';
const showStatus = status && size === 'regular' && shape === 'round';

const AvatarClassNames = classNames(
{
Expand Down Expand Up @@ -215,6 +221,11 @@ export const Avatar = (props: AvatarProps) => {
{showPresence && (
<span data-test="DesignSystem-Avatar--Presence" className={presenceClassNames} style={borderStyle} />
)}
{showStatus && (
<span data-test="DesignSystem-Avatar--Status" className="Avatar-status" style={borderStyle}>
{status}
</span>
)}
</span>
);

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions core/components/atoms/avatar/__stories__/statusWithIcon.story.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import { Avatar, Icon, Tooltip } from '@/index';

// CSF format story
export const statusWithIcon = () => {
return (
<Avatar
lastName="Doe"
firstName="John"
appearance="primary"
status={
<Tooltip tooltip="Verified" position="top">
<Icon name="done" size={10} appearance="white" className="p-1 bg-success" />
</Tooltip>
}
/>
);
};

export default {
title: 'Components/Avatar/Avatar/Status/Status With Icon',
component: Avatar,
parameters: {
docs: {
docPage: {
title: 'Avatar',
},
},
},
};
31 changes: 31 additions & 0 deletions core/components/atoms/avatar/__stories__/statusWithImage.story.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react';
import { Avatar, Tooltip } from '@/index';
import StatusImage from './assets/status-image.png';

// CSF format story
export const statusWithImage = () => {
return (
<Avatar
firstName="Tom"
lastName="Yusuf"
appearance="accent1"
status={
<Tooltip tooltip="DND" position="top">
<img width="14px" alt="DND" src={StatusImage} />
</Tooltip>
}
/>
);
};

export default {
title: 'Components/Avatar/Avatar/Status/Status With Image',
component: Avatar,
parameters: {
docs: {
docPage: {
title: 'Avatar',
},
},
},
};
46 changes: 46 additions & 0 deletions core/components/atoms/avatar/__tests__/Avatar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const sizes: AvatarSize[] = ['regular', 'tiny'];
const shapes: AvatarShape[] = ['round', 'square'];
const booleanValues = [true, false];

const statusComponent = <div>status</div>;

describe('Avatar component', () => {
const mapper = {
appearance: valueHelper(appearances, { required: true, iterate: true }),
Expand Down Expand Up @@ -270,3 +272,47 @@ describe('Avatar component with prop:presence', () => {
expect(presenceEle).toHaveStyle('box-shadow: 0 0 0 var(--spacing-s) red');
});
});

describe('Avatar component with prop:status', () => {
it('should have the Avatar-status class when size is regular', () => {
const { getByTestId } = render(<Avatar status={statusComponent}>Design</Avatar>);
const statusElement = getByTestId('DesignSystem-Avatar--Status');
expect(statusElement).toBeInTheDocument();
expect(statusElement).toHaveClass('Avatar-status');
});

it('should not have the Avatar-status class when size is tiny', () => {
render(
<Avatar status={statusComponent} size="tiny">
Design
</Avatar>
);
const statusElement = screen.queryByText('DesignSystem-Avatar--Status');
expect(statusElement).not.toBeInTheDocument();
});

it('should have the Avatar-status class when shape is round', () => {
const { getByTestId } = render(<Avatar status={statusComponent}>Design</Avatar>);
const statusElement = getByTestId('DesignSystem-Avatar--Status');
expect(statusElement).toBeInTheDocument();
expect(statusElement).toHaveClass('Avatar-status');
});

it('should not have the Avatar-status class when shape is square', () => {
render(
<Avatar status={statusComponent} shape="square">
Design
</Avatar>
);
const statusElement = screen.queryByText('DesignSystem-Avatar--Status');
expect(statusElement).not.toBeInTheDocument();
});

it('status should have custom stroke color', () => {
const { getByTestId } = render(
<Avatar firstName="John" lastName="Doe" status={statusComponent} strokeColor="red" />
);
const statusElement = getByTestId('DesignSystem-Avatar--Status');
expect(statusElement).toHaveStyle('box-shadow: 0 0 0 var(--spacing-s) red');
});
});
14 changes: 14 additions & 0 deletions css/src/components/avatar.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,17 @@
.Avatar-presence--away {
background: var(--secondary-dark);
}

.Avatar-status {
top: calc(-1 * var(--spacing-s));
right: calc(-1 * var(--spacing-s));
width: var(--spacing-l);
height: var(--spacing-l);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
cursor: pointer;
overflow: hidden;
}
9 changes: 8 additions & 1 deletion figma/Avatar.figma.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Avatar } from '@/index';
import { Avatar, Icon, Tooltip } from '@/index';
import figma from '@figma/code-connect';

figma.connect(Avatar, 'https://www.figma.com/design/w8sqBtJpvq86D06UE7gN0T/MDS---Web?node-id=37-592', {
Expand Down Expand Up @@ -39,6 +39,13 @@ figma.connect(Avatar, 'https://www.figma.com/design/w8sqBtJpvq86D06UE7gN0T/MDS--
icon: figma.enum('Type', {
Icon: <Avatar.Icon name="person" />,
}),
status: figma.enum('Status', {
true: (
<Tooltip tooltip="done" position="top">
<Icon name="done" size={10} appearance="white" />
</Tooltip>
),
}),
},
example: ({ icon, image, ...rest }) => (
<Avatar {...rest} withTooltip={true}>
Expand Down

0 comments on commit 5885784

Please sign in to comment.