Skip to content

Commit

Permalink
feat(Avatar): add withImageBorder property (#2138)
Browse files Browse the repository at this point in the history
  • Loading branch information
DakEnviy authored Feb 26, 2025
1 parent eb2144c commit 81a3380
Show file tree
Hide file tree
Showing 14 changed files with 56 additions and 49 deletions.
6 changes: 6 additions & 0 deletions src/components/Avatar/Avatar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,16 @@ $block: '.#{variables.$ns}avatar';
}

&__image {
box-sizing: border-box;
display: block;
width: 100%;
height: 100%;
border-radius: inherit;
object-fit: cover;

&_with-border {
border: 1px solid var(--g-color-line-generic);
}
}

&__icon {
Expand Down
27 changes: 5 additions & 22 deletions src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import * as React from 'react';

import {block} from '../utils/cn';
import {filterDOMProps} from '../utils/filterDOMProps';

import {AvatarIcon} from './AvatarIcon';
import {AvatarImage} from './AvatarImage';
import {AvatarText} from './AvatarText';
import {DEFAULT_AVATAR_SIZE} from './constants';
import {DEFAULT_AVATAR_SIZE, bAvatar} from './constants';
import type {AvatarProps} from './types/main';

import './Avatar.scss';

const b = block('avatar');

export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
const {
size = DEFAULT_AVATAR_SIZE,
Expand All @@ -32,46 +29,32 @@ export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>((props, ref)
if ('imgUrl' in props && props.imgUrl) {
return (
<AvatarImage
className={b('image')}
imgUrl={props.imgUrl}
fallbackImgUrl={props.fallbackImgUrl}
sizes={props.sizes}
srcSet={props.srcSet}
alt={props.alt || title}
loading={props.loading}
withImageBorder={props.withImageBorder}
size={size}
/>
);
}

if ('icon' in props && props.icon) {
return (
<AvatarIcon
className={b('icon')}
icon={props.icon}
color={props.color}
size={size}
/>
);
return <AvatarIcon icon={props.icon} color={props.color} size={size} />;
}

if ('text' in props && props.text) {
return (
<AvatarText
className={b('text')}
text={props.text}
color={props.color}
size={size}
/>
);
return <AvatarText text={props.text} color={props.color} size={size} />;
}

return null;
};

return (
<div
className={b({size, theme, view, 'with-border': Boolean(borderColor)}, className)}
className={bAvatar({size, theme, view, 'with-border': Boolean(borderColor)}, className)}
title={title}
role="img"
style={style}
Expand Down
5 changes: 3 additions & 2 deletions src/components/Avatar/AvatarIcon/AvatarIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Icon} from '../../Icon';
import {bAvatar} from '../constants';
import type {AvatarSize} from '../types/common';

import type {AvatarIconProps} from './types';
Expand All @@ -13,11 +14,11 @@ const avatarSizeToIconSize: Record<AvatarSize, number> = {
xl: 24,
};

export const AvatarIcon = ({icon, color, size, className}: AvatarIconProps) => {
export const AvatarIcon = ({icon, color, size}: AvatarIconProps) => {
const style = {color};

return (
<div style={style} className={className}>
<div className={bAvatar('icon')} style={style}>
<Icon data={icon} size={avatarSizeToIconSize[size]} />
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/components/Avatar/AvatarImage/AvatarImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import * as React from 'react';

import {AVATAR_SIZES} from '../constants';
import {AVATAR_SIZES, bAvatar} from '../constants';

import type {AvatarImageProps} from './types';

Expand All @@ -13,8 +13,8 @@ export const AvatarImage = ({
srcSet,
alt,
loading,
withImageBorder,
size,
className,
}: AvatarImageProps) => {
const [isErrored, setIsErrored] = React.useState(false);

Expand All @@ -29,7 +29,7 @@ export const AvatarImage = ({

return (
<img
className={className}
className={bAvatar('image', {'with-border': withImageBorder})}
loading={loading}
width={AVATAR_SIZES[size]}
height={AVATAR_SIZES[size]}
Expand Down
1 change: 1 addition & 0 deletions src/components/Avatar/AvatarImage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface AvatarImageProps extends AvatarCommonProps {
srcSet?: string;
alt?: string;
loading?: 'eager' | 'lazy';
withImageBorder?: boolean;
}
6 changes: 4 additions & 2 deletions src/components/Avatar/AvatarText/AvatarText.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {bAvatar} from '../constants';

import type {AvatarTextProps} from './types';
import {getAvatarDisplayText} from './utils';

export const AvatarText = ({text, color, size, className}: AvatarTextProps) => {
export const AvatarText = ({text, color, size}: AvatarTextProps) => {
const style = {color};
const displayText = getAvatarDisplayText(text, size);

return (
<div style={style} className={className}>
<div className={bAvatar('text')} style={style}>
{displayText}
</div>
);
Expand Down
17 changes: 9 additions & 8 deletions src/components/Avatar/README-ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,15 @@ LANDING_BLOCK-->

### Свойства изображений

| Имя | Описание | Тип | Значение по умолчанию |
| :------------- | :--------------------------------------------------- | :----------------: | :-------------------: |
| imgUrl | HTML-атрибут `src` для `img`. | `string` | |
| fallbackImgUrl | Резервное изображение, отображаемое в случае ошибки. | `string` | |
| sizes | HTML-атрибут `sizes` для `img`. | `string` | |
| srcSet | HTML-атрибут `srcSet` для `img`. | `string` | |
| alt | HTML-атрибут `alt` для `img`. | `string` | props.title |
| loading | HTML-атрибут `loading` для `img`. | `'eager'` `'lazy'` | |
| Имя | Описание | Тип | Значение по умолчанию |
| :-------------- | :--------------------------------------------------- | :----------------: | :-------------------: |
| imgUrl | HTML-атрибут `src` для `img`. | `string` | |
| fallbackImgUrl | Резервное изображение, отображаемое в случае ошибки. | `string` | |
| sizes | HTML-атрибут `sizes` для `img`. | `string` | |
| srcSet | HTML-атрибут `srcSet` для `img`. | `string` | |
| alt | HTML-атрибут `alt` для `img`. | `string` | props.title |
| loading | HTML-атрибут `loading` для `img`. | `'eager'` `'lazy'` | |
| withImageBorder | Добавляет обводку по умолчанию для изображения | `boolean` | |

### Свойства иконки

Expand Down
17 changes: 9 additions & 8 deletions src/components/Avatar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,15 @@ LANDING_BLOCK-->

### Image-specific

| Name | Description | Type | Default |
| :------------- | :---------------------------------------- | :----------------: | :---------: |
| imgUrl | `img` `src` HTML attribute | `string` | |
| fallbackImgUrl | Fallback image shown if an error occurred | `string` | |
| sizes | `img` `sizes` HTML attribute | `string` | |
| srcSet | `img` `srcSet` HTML attribute | `string` | |
| alt | `img` `alt` HTML attribute | `string` | props.title |
| loading | `img` `loading` HTML attribute | `'eager'` `'lazy'` | |
| Name | Description | Type | Default |
| :-------------- | :---------------------------------------- | :----------------: | :---------: |
| imgUrl | `img` `src` HTML attribute | `string` | |
| fallbackImgUrl | Fallback image shown if an error occurred | `string` | |
| sizes | `img` `sizes` HTML attribute | `string` | |
| srcSet | `img` `srcSet` HTML attribute | `string` | |
| alt | `img` `alt` HTML attribute | `string` | props.title |
| loading | `img` `loading` HTML attribute | `'eager'` `'lazy'` | |
| withImageBorder | Add default border for the image | `boolean` | |

### Icon-specific

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/components/Avatar/__tests__/Avatar.visual.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,12 @@ test.describe('Avatar', {tag: '@Avatar'}, () => {
themes: ['light'],
});
});

test('should render default border for the image if withImageBorder=true', async ({
mount,
expectScreenshot,
}) => {
const component = await mount(<TestAvatarWithImage withImageBorder />);
await expectScreenshot({component});
});
});
4 changes: 3 additions & 1 deletion src/components/Avatar/__tests__/helpersPlaywright.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {FaceRobot} from '@gravity-ui/icons';

import type {DistributiveOmit} from 'src/types/utils';

import {Avatar} from '../Avatar';
import type {AvatarProps} from '../types/main';

export type TestAvatarProps = Omit<AvatarProps, 'imgUrl' | 'icon' | 'text'>;
export type TestAvatarProps = DistributiveOmit<AvatarProps, 'imgUrl' | 'icon' | 'text'>;

export const TestAvatarWithImage = (props: TestAvatarProps) => {
return (
Expand Down
4 changes: 4 additions & 0 deletions src/components/Avatar/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {block} from '../utils/cn';

import type {AvatarSize} from './types/common';

export const AVATAR_SIZES: Record<AvatarSize, number> = {
Expand All @@ -11,3 +13,5 @@ export const AVATAR_SIZES: Record<AvatarSize, number> = {
};

export const DEFAULT_AVATAR_SIZE: AvatarSize = 'm';

export const bAvatar = block('avatar');
4 changes: 1 addition & 3 deletions src/components/Avatar/types/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type {DOMProps} from '../../types';

export type AvatarSize = '3xs' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl';

export interface AvatarCommonProps extends Pick<DOMProps, 'className'> {
export interface AvatarCommonProps {
size: AvatarSize;
}

0 comments on commit 81a3380

Please sign in to comment.