Skip to content

Commit

Permalink
feat(UserAvatar): add fallbackImgUrl prop (#1025)
Browse files Browse the repository at this point in the history
  • Loading branch information
DakEnviy authored Sep 22, 2023
1 parent dc8cdb3 commit 9a4bd59
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 25 deletions.
17 changes: 9 additions & 8 deletions src/components/UserAvatar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ Component for displaying user avatar.

### PropTypes

| Name | Type | Required | Default | Description |
| :-------- | :--------------- | :------- | :------ | :--------------------------------------------------------- |
| imgUrl | `string` | | | Link to image |
| size | `UserAvatarSize` | | 'm' | Component size. Possible values: `xs`, `s`, `m`, `l`, `xl` |
| srcSet | `string` | | | `srcSet` attribute of the image |
| sizes | `string` | | | `sizes` attribute of the image |
| title | `string` | | | Tooltip text on hover |
| className | `string` | | | Class name |
| Name | Type | Required | Default | Description |
| :------------- | :--------------- | :------- | :------ | :--------------------------------------------------------- |
| imgUrl | `string` | | | Link to image |
| fallbackImgUrl | `string` | | | Link to fallback image |
| size | `UserAvatarSize` | | 'm' | Component size. Possible values: `xs`, `s`, `m`, `l`, `xl` |
| srcSet | `string` | | | `srcSet` attribute of the image |
| sizes | `string` | | | `sizes` attribute of the image |
| title | `string` | | | Tooltip text on hover |
| className | `string` | | | Class name |
43 changes: 29 additions & 14 deletions src/components/UserAvatar/UserAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './UserAvatar.scss';

export interface UserAvatarProps {
imgUrl?: string;
fallbackImgUrl?: string;
size?: UserAvatarSize;
srcSet?: string;
sizes?: string;
Expand All @@ -21,20 +22,34 @@ export interface UserAvatarProps {
const b = block('user-avatar');

export const UserAvatar = React.forwardRef<HTMLDivElement, UserAvatarProps>(
({imgUrl, size = 'm', srcSet, sizes, title, className, onClick}, ref) => (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div title={title} className={b({size}, className)} onClick={onClick} ref={ref}>
<img
className={b('figure')}
width={SIZES[size]}
height={SIZES[size]}
src={imgUrl}
srcSet={srcSet}
sizes={sizes}
alt={''}
/>
</div>
),
({imgUrl, fallbackImgUrl, size = 'm', srcSet, sizes, title, className, onClick}, ref) => {
const [isErrored, setIsErrored] = React.useState(false);

const handleError = React.useCallback(() => {
setIsErrored(true);
}, []);

// Reset error if `imgUrl` was changed to check it again
React.useEffect(() => {
setIsErrored(false);
}, [imgUrl]);

return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div className={b({size}, className)} title={title} onClick={onClick} ref={ref}>
<img
className={b('figure')}
width={SIZES[size]}
height={SIZES[size]}
src={fallbackImgUrl && isErrored ? fallbackImgUrl : imgUrl}
srcSet={srcSet}
sizes={sizes}
alt=""
onError={handleError}
/>
</div>
);
},
);

UserAvatar.displayName = 'UserAvatar';
16 changes: 13 additions & 3 deletions src/components/UserAvatar/__stories__/UserAvatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

import {faker} from '@faker-js/faker/locale/en';
import {useArgs} from '@storybook/client-api';
import type {ComponentStory, Meta, StoryFn} from '@storybook/react';
import type {Meta, StoryFn} from '@storybook/react';

import {UserAvatar} from '../UserAvatar';
import type {UserAvatarProps} from '../UserAvatar';
Expand Down Expand Up @@ -42,7 +42,7 @@ const randomAvatars = faker.helpers
}),
{},
);
export const WithSrcSet: ComponentStory<typeof UserAvatar> = (args) => {
export const WithSrcSet: StoryFn<UserAvatarProps> = (args) => {
const [, setArgs] = useArgs();

React.useEffect(() => {
Expand All @@ -54,6 +54,16 @@ export const WithSrcSet: ComponentStory<typeof UserAvatar> = (args) => {
return <UserAvatar {...args} />;
};
WithSrcSet.args = {
imgUrl: faker.image.cats(),
imgUrl: faker.image.urlLoremFlickr({category: 'cats'}),
size: 'xl',
};

export const WithFallback: StoryFn<UserAvatarProps> = (args) => {
return <UserAvatar {...args} />;
};
WithFallback.args = {
// Invalid image link
imgUrl: imgUrl + '1',
fallbackImgUrl: imgUrl,
size: 'xl',
};

0 comments on commit 9a4bd59

Please sign in to comment.