Skip to content

Commit

Permalink
feat(avatar): add presence indicator support in avatar component
Browse files Browse the repository at this point in the history
  • Loading branch information
anuradha9712 authored and satyamyadav committed Dec 6, 2024
1 parent 5ce126a commit ce945f2
Show file tree
Hide file tree
Showing 10 changed files with 2,611 additions and 1,912 deletions.
45 changes: 36 additions & 9 deletions core/components/atoms/avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import AvatarIcon from './avatarIcon';
import AvatarImage from './avatarImage';
import AvatarProvider from './AvatarProvider';

type TPresence = 'active' | 'away';

export interface AvatarProps extends BaseProps {
/**
* Color of the `Avatar`
Expand Down Expand Up @@ -57,6 +59,14 @@ export interface AvatarProps extends BaseProps {
* Defines tabIndex of the `Avatar`
*/
tabIndex?: number;
/**
* Show presence indicator for the `Avatar`
*/
presence?: TPresence;
/**
* Stroke color of `Presence indicator` & `Status indicator` in `Avatar`
*/
strokeColor?: string;
}

const initialsLength = 2;
Expand All @@ -77,6 +87,8 @@ export const Avatar = (props: AvatarProps) => {
disabled,
tooltipSuffix,
tabIndex,
presence,
strokeColor,
role = 'presentation',
} = props;

Expand All @@ -99,6 +111,7 @@ export const Avatar = (props: AvatarProps) => {
appearance || colors[(initials.charCodeAt(0) + (initials.charCodeAt(1) || 0)) % 8] || DefaultAppearance;

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

const AvatarClassNames = classNames(
{
Expand Down Expand Up @@ -127,6 +140,16 @@ export const Avatar = (props: AvatarProps) => {
['Avatar-content']: darkAppearance.includes(AvatarAppearance),
});

const presenceClassNames = classNames({
['Avatar-presence']: presence,
['Avatar-presence--active']: presence === 'active',
['Avatar-presence--away']: presence === 'away',
});

const borderStyle = {
boxShadow: `0 0 0 var(--spacing-s) ${strokeColor}`,
};

const sharedProp = {
size,
firstName,
Expand Down Expand Up @@ -180,17 +203,20 @@ export const Avatar = (props: AvatarProps) => {
);
};

const renderTooltip = () => {
if (withTooltip && initials) {
return (
<Tooltip tooltip={getTooltipName()} position={tooltipPosition} triggerClass={'flex-grow-0'}>
const renderTooltip = () => (
<span className="position-relative d-inline-flex">
{withTooltip && initials ? (
<Tooltip tooltip={getTooltipName()} position={tooltipPosition} triggerClass="flex-grow-0">
{renderAvatar()}
</Tooltip>
);
}

return renderAvatar();
};
) : (
renderAvatar()
)}
{showPresence && (
<span data-test="DesignSystem-Avatar--Presence" className={presenceClassNames} style={borderStyle} />
)}
</span>
);

return renderTooltip();
};
Expand All @@ -205,6 +231,7 @@ Avatar.defaultProps = {
withTooltip: true,
size: 'regular',
shape: 'round',
strokeColor: 'var(--white)',
};

export default Avatar;
36 changes: 36 additions & 0 deletions core/components/atoms/avatar/__stories__/Presence.story.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import { Avatar, Row, Column, Text } from '@/index';

// CSF format story
export const presence = () => {
const weight = 'strong';

return (
<Row className="w-50">
<Column>
<Text weight={weight}>Active</Text>
<br />
<br />
<Avatar firstName="John" lastName="Doe" presence="active" />
</Column>
<Column>
<Text weight={weight}>Away</Text>
<br />
<br />
<Avatar firstName="John" lastName="Doe" presence="away" />
</Column>
</Row>
);
};

export default {
title: 'Components/Avatar/Avatar/Presence',
component: Avatar,
parameters: {
docs: {
docPage: {
title: 'Avatar',
},
},
},
};
41 changes: 40 additions & 1 deletion core/components/atoms/avatar/__tests__/Avatar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { fireEvent, render, screen } from '@testing-library/react';
import Avatar, { AvatarProps as Props } from '../Avatar';
import { AccentAppearance, AvatarShape, AvatarSize } from '@/common.type';
import { testHelper, filterUndefined, valueHelper, testMessageHelper } from '@/utils/testHelper';
Expand Down Expand Up @@ -231,3 +231,42 @@ describe('Avatar component with tooltip', () => {
expect(tooltip).toHaveTextContent('John Doe (Deactivated)');
});
});

describe('Avatar component with prop:presence', () => {
it('presence should be available for only round avatar', () => {
const { getByTestId } = render(<Avatar firstName="John" lastName="Doe" presence="active" shape="round" />);
const presenceEle = getByTestId('DesignSystem-Avatar--Presence');
expect(presenceEle).toBeInTheDocument();
expect(presenceEle).toHaveClass('Avatar-presence');
});

it('presence should not be available for square avatar', () => {
render(<Avatar firstName="John" lastName="Doe" presence="active" shape="square" />);
const presenceEle = screen.queryByText('DesignSystem-Avatar--Presence');
expect(presenceEle).not.toBeInTheDocument();
});

it('presence should not be available for disabled avatar', () => {
render(<Avatar firstName="John" lastName="Doe" presence="active" disabled={true} />);
const presenceEle = screen.queryByText('DesignSystem-Avatar--Presence');
expect(presenceEle).not.toBeInTheDocument();
});

it('presence should have active class for prop presence:active', () => {
const { getByTestId } = render(<Avatar firstName="John" lastName="Doe" presence="active" />);
const presenceEle = getByTestId('DesignSystem-Avatar--Presence');
expect(presenceEle).toHaveClass('Avatar-presence--active');
});

it('presence should have active class for prop presence:away', () => {
const { getByTestId } = render(<Avatar firstName="John" lastName="Doe" presence="away" />);
const presenceEle = getByTestId('DesignSystem-Avatar--Presence');
expect(presenceEle).toHaveClass('Avatar-presence--away');
});

it('presence should have custom stroke color', () => {
const { getByTestId } = render(<Avatar firstName="John" lastName="Doe" presence="away" strokeColor="red" />);
const presenceEle = getByTestId('DesignSystem-Avatar--Presence');
expect(presenceEle).toHaveStyle('box-shadow: 0 0 0 var(--spacing-s) red');
});
});
Loading

0 comments on commit ce945f2

Please sign in to comment.