Skip to content

Commit 5355b64

Browse files
authored
Merge pull request #2684 from innovaccer/develop
Develop
2 parents 4ffeeef + 18f697f commit 5355b64

File tree

33 files changed

+1057
-306
lines changed

33 files changed

+1057
-306
lines changed

core/common.type.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export type TextColor =
9191
| 'accent4-shadow'
9292
| 'inverse-shadow';
9393

94-
export type AvatarSize = 'regular' | 'tiny';
94+
export type AvatarSize = 'regular' | 'tiny' | 'micro';
9595

9696
export type AvatarShape = 'round' | 'square';
9797

core/components/atoms/avatar/Avatar.tsx

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import { AccentAppearance, AvatarSize, AvatarShape } from '@/common.type';
77
import AvatarIcon from './avatarIcon';
88
import AvatarImage from './avatarImage';
99
import AvatarProvider from './AvatarProvider';
10+
import { iconAppearanceMapper } from './constants';
1011
import styles from '@css/components/avatar.module.css';
12+
import { IconAppearance } from 'types';
1113

1214
type TPresence = 'active' | 'away';
1315

@@ -117,8 +119,9 @@ export const Avatar = (props: AvatarProps) => {
117119
appearance || colors[(initials.charCodeAt(0) + (initials.charCodeAt(1) || 0)) % 8] || DefaultAppearance;
118120

119121
const darkAppearance = ['secondary', 'success', 'warning', 'accent1', 'accent4'];
120-
const showPresence = presence && !disabled && shape === 'round' && (presence === 'active' || presence === 'away');
121-
const showStatus = status && size === 'regular' && shape === 'round';
122+
const showPresence =
123+
presence && !disabled && size !== 'micro' && shape === 'round' && (presence === 'active' || presence === 'away');
124+
const showStatus = status && size !== 'micro' && size === 'regular' && shape === 'round';
122125

123126
const AvatarClassNames = classNames(
124127
{
@@ -140,11 +143,7 @@ export const Avatar = (props: AvatarProps) => {
140143

141144
const TextClassNames = classNames({
142145
[styles[`Avatar-content--${size}`]]: size,
143-
[styles['Avatar-content']]: darkAppearance.includes(AvatarAppearance),
144-
});
145-
146-
const IconClassNames = classNames({
147-
[styles['Avatar-content']]: darkAppearance.includes(AvatarAppearance),
146+
[styles[`Avatar-content--${AvatarAppearance}`]]: AvatarAppearance,
148147
});
149148

150149
const presenceClassNames = classNames({
@@ -165,6 +164,19 @@ export const Avatar = (props: AvatarProps) => {
165164
darkAppearance,
166165
};
167166

167+
const renderFallbackIcon = () => {
168+
const iconName = shape === 'square' ? 'groups' : 'person';
169+
const iconAppearance = iconAppearanceMapper[AvatarAppearance] || 'inverse';
170+
return (
171+
<Icon
172+
data-test="DesignSystem-Avatar--Icon"
173+
name={iconName}
174+
size={size === 'regular' ? 20 : 16}
175+
appearance={iconAppearance as IconAppearance}
176+
/>
177+
);
178+
};
179+
168180
const renderAvatar = () => {
169181
if (children && typeof children !== 'string') {
170182
return (
@@ -191,20 +203,14 @@ export const Avatar = (props: AvatarProps) => {
191203
className={AvatarClassNames}
192204
tabIndex={tabIndex || disabled ? -1 : 0}
193205
>
194-
{initials && (
195-
<Text weight="medium" appearance={'white'} className={TextClassNames}>
196-
{initials}
197-
</Text>
198-
)}
199-
{!initials && (
200-
<Icon
201-
data-test="DesignSystem-Avatar--Icon"
202-
name="person"
203-
size={size === 'regular' ? 20 : 16}
204-
appearance={'white'}
205-
className={IconClassNames}
206-
/>
207-
)}
206+
<>
207+
{initials && (
208+
<Text weight="medium" className={TextClassNames}>
209+
{initials}
210+
</Text>
211+
)}
212+
{!initials && renderFallbackIcon()}
213+
</>
208214
</span>
209215
</span>
210216
);

core/components/atoms/avatar/__stories__/variants/Size.story.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ export const size = () => {
2020
<Avatar appearance="accent4" firstName="John" lastName="Doe" shape="square" size="tiny" />
2121
</div>
2222
</Column>
23+
<Column>
24+
<Text weight="strong">Micro</Text>
25+
<div className="d-flex mt-7">
26+
<Avatar firstName="John" lastName="Doe" size="micro" className="mr-8" />
27+
<Avatar appearance="accent4" firstName="John" lastName="Doe" shape="square" size="micro" />
28+
</div>
29+
</Column>
2330
</Row>
2431
</div>
2532
);

core/components/atoms/avatar/__tests__/Avatar.test.tsx

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const appearances: AccentAppearance[] = [
1515
'accent4',
1616
];
1717

18-
const sizes: AvatarSize[] = ['regular', 'tiny'];
18+
const sizes: AvatarSize[] = ['regular', 'tiny', 'micro'];
1919

2020
const shapes: AvatarShape[] = ['round', 'square'];
2121
const booleanValues = [true, false];
@@ -134,14 +134,14 @@ describe('Avatar component with prop:appearance', () => {
134134
});
135135

136136
describe('Avatar component accessibility', () => {
137-
it('should have the Avatar-content class when appearance is secondary', () => {
137+
it('should have the Avatar-content--secondary class when appearance is secondary', () => {
138138
const { getByTestId } = render(<Avatar appearance="secondary">Design</Avatar>);
139-
expect(getByTestId('DesignSystem-Text')).toHaveClass('Avatar-content');
139+
expect(getByTestId('DesignSystem-Text')).toHaveClass('Avatar-content--secondary');
140140
});
141141

142-
it('should not have the Avatar-content class when appearance is primary', () => {
142+
it('should have the Avatar-content--primary class when appearance is primary', () => {
143143
const { getByTestId } = render(<Avatar appearance="primary">Design</Avatar>);
144-
expect(getByTestId('DesignSystem-Text')).not.toHaveClass('Avatar-content');
144+
expect(getByTestId('DesignSystem-Text')).toHaveClass('Avatar-content--primary');
145145
});
146146
});
147147

@@ -316,3 +316,94 @@ describe('Avatar component with prop:status', () => {
316316
expect(statusElement).toHaveStyle('box-shadow: 0 0 0 var(--spacing-05) red');
317317
});
318318
});
319+
320+
describe('Avatar component with prop:shape square fallback icon', () => {
321+
it('should render groups icon when shape is square and no initials', () => {
322+
const { getByTestId } = render(<Avatar shape="square" />);
323+
const icon = getByTestId('DesignSystem-Avatar--Icon');
324+
expect(icon).toBeInTheDocument();
325+
expect(icon.textContent).toBe('groups');
326+
});
327+
328+
it('should render person icon when shape is round and no initials', () => {
329+
const { getByTestId } = render(<Avatar shape="round" />);
330+
const icon = getByTestId('DesignSystem-Avatar--Icon');
331+
expect(icon).toBeInTheDocument();
332+
expect(icon.textContent).toBe('person');
333+
});
334+
335+
it('should render initials when shape is square and initials are provided', () => {
336+
const { getByTestId, queryByTestId } = render(<Avatar shape="square" firstName="John" lastName="Doe" />);
337+
expect(getByTestId('DesignSystem-Avatar').textContent).toMatch('JD');
338+
expect(queryByTestId('DesignSystem-Avatar--Icon')).not.toBeInTheDocument();
339+
});
340+
});
341+
342+
describe('Avatar component with prop:size micro and presence/status', () => {
343+
it('should not render presence when size is micro', () => {
344+
render(<Avatar firstName="John" lastName="Doe" presence="active" size="micro" />);
345+
const presenceEle = screen.queryByTestId('DesignSystem-Avatar--Presence');
346+
expect(presenceEle).not.toBeInTheDocument();
347+
});
348+
349+
it('should not render status when size is micro', () => {
350+
render(
351+
<Avatar firstName="John" lastName="Doe" status={statusComponent} size="micro">
352+
Design
353+
</Avatar>
354+
);
355+
const statusElement = screen.queryByTestId('DesignSystem-Avatar--Status');
356+
expect(statusElement).not.toBeInTheDocument();
357+
});
358+
359+
it('should render presence when size is regular', () => {
360+
const { getByTestId } = render(<Avatar firstName="John" lastName="Doe" presence="active" size="regular" />);
361+
const presenceEle = getByTestId('DesignSystem-Avatar--Presence');
362+
expect(presenceEle).toBeInTheDocument();
363+
});
364+
365+
it('should render status when size is regular', () => {
366+
const { getByTestId } = render(
367+
<Avatar status={statusComponent} size="regular">
368+
Design
369+
</Avatar>
370+
);
371+
const statusElement = getByTestId('DesignSystem-Avatar--Status');
372+
expect(statusElement).toBeInTheDocument();
373+
});
374+
});
375+
376+
describe('Avatar component with Avatar.Image child and appearance', () => {
377+
it('should apply appearance background when Avatar.Image is child', () => {
378+
const { getByTestId } = render(
379+
<Avatar appearance="primary" firstName="John" lastName="Doe">
380+
<Avatar.Image src="https://design.innovaccer.com/images/avatar2.jpeg" />
381+
</Avatar>
382+
);
383+
const avatarElement = getByTestId('DesignSystem-Avatar');
384+
expect(avatarElement).toHaveClass('Avatar--primary');
385+
});
386+
387+
it('should apply appearance background when Avatar.Icon is child', () => {
388+
const { getByTestId } = render(
389+
<Avatar appearance="primary" firstName="John" lastName="Doe">
390+
<Avatar.Icon name="person" />
391+
</Avatar>
392+
);
393+
const avatarElement = getByTestId('DesignSystem-Avatar');
394+
expect(avatarElement).toHaveClass('Avatar--primary');
395+
});
396+
397+
it('should apply appearance background when only initials are provided', () => {
398+
const { getByTestId } = render(<Avatar appearance="primary" firstName="John" lastName="Doe" />);
399+
const avatarElement = getByTestId('DesignSystem-Avatar');
400+
expect(avatarElement).toHaveClass('Avatar--primary');
401+
});
402+
});
403+
404+
describe('Avatar component with prop:size micro', () => {
405+
it('should have the Avatar--micro class when size is micro', () => {
406+
const { getByTestId } = render(<Avatar size="micro">Design</Avatar>);
407+
expect(getByTestId('DesignSystem-Avatar')).toHaveClass('Avatar--micro');
408+
});
409+
});

0 commit comments

Comments
 (0)