diff --git a/CODEOWNERS b/CODEOWNERS index 6b38e9a92a..77ad81ab60 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,6 +2,7 @@ /src/components/ActionTooltip @amje /src/components/Alert @IsaevAlexandr /src/components/ArrowToggle @Marginy605 +/src/components/Avatar @DakEnviy #/src/components/Breadcrumbs /src/components/Button @amje /src/components/Card @Lunory @@ -30,8 +31,7 @@ /src/components/Radio @zamkovskaya /src/components/RadioButton @zamkovskaya /src/components/RadioGroup @zamkovskaya -/src/components/User @DaffPunks -/src/components/UserAvatar @DaffPunks +/src/components/User @DakEnviy /src/components/Select @korvin89 /src/components/Sheet @mournfulCoroner /src/components/Skeleton @SeqviriouM diff --git a/package.json b/package.json index ac8e8e4f94..a35fc6bad2 100644 --- a/package.json +++ b/package.json @@ -78,8 +78,8 @@ "playwright:install": "playwright install --with-deps", "playwright": "playwright test --config=playwright/playwright.config.ts", "playwright:update": "npm run playwright -- -u", - "playwright:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.39.0-jammy /bin/bash -c 'npm ci && npx playwright install && npm run playwright'", - "playwright:docker:update": " docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.39.0-jammy /bin/bash -c 'npm ci && npx playwright install && npm run playwright:update'" + "playwright:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.38.1-jammy /bin/bash -c 'npm ci && npm run playwright'", + "playwright:docker:update": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.38.1-jammy /bin/bash -c 'npm ci && npm run playwright:update'" }, "dependencies": { "@bem-react/classname": "^1.6.0", diff --git a/playwright/core/index.tsx b/playwright/core/index.tsx index 8b35c20c20..12e3170401 100644 --- a/playwright/core/index.tsx +++ b/playwright/core/index.tsx @@ -3,17 +3,17 @@ import React from 'react'; import type {JsonObject} from '@playwright/experimental-ct-core/types/component'; import {ComponentFixtures, MountOptions, test as base} from '@playwright/experimental-ct-react'; -type MountFixtures = { +type CustomFixtures = { mount: ComponentFixtures['mount']; }; -export const test = base.extend({ +export const test = base.extend({ mount: async ({mount: baseMount}, use) => { const mount = async ( component: JSX.Element, options?: MountOptions | undefined, ) => { - return await baseMount( + return baseMount(
{component}
, diff --git a/src/components/Avatar/Avatar.scss b/src/components/Avatar/Avatar.scss new file mode 100644 index 0000000000..d6e8b065c0 --- /dev/null +++ b/src/components/Avatar/Avatar.scss @@ -0,0 +1,136 @@ +@use '../variables'; + +$block: '.#{variables.$ns-new}avatar'; + +#{$block} { + --_--size: 32px; + --_--background-color: var(--g-color-base-misc-light); + --_--border-color: currentColor; + --_--color: var(--g-color-text-misc); + --_--font-size: var(--g-text-body-1-font-size); + --_--line-height: var(--g-text-body-1-line-height); + + overflow: hidden; + display: inline-flex; + justify-content: center; + align-items: center; + width: var(--g-avatar-size, var(--_--size)); + height: var(--g-avatar-size, var(--_--size)); + border-radius: 50%; + background-color: var(--g-avatar-background-color, var(--_--background-color)); + + &__image { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + } + + &__icon { + color: var(--g-avatar-color, var(--_--color)); + + & > svg { + display: block; + } + } + + &__text { + color: var(--g-avatar-color, var(--_--color)); + font-size: var(--g-avatar-font-size, var(--_--font-size)); + line-height: var(--g-avatar-line-height, var(--_--line-height)); + font-weight: 500; + } + + &_with-border, + &_view_outlined { + position: relative; + + &::before, + &::after { + content: ''; + z-index: 1; + position: absolute; + inset: 0; + border-radius: 50%; + } + + &::before { + border: 3px solid var(--g-color-base-background); + } + + &::after { + border: 2px solid var(--g-avatar-border-color, var(--_--border-color)); + } + } + + &_size { + &_xs { + --_--size: 24px; + } + + &_s { + --_--size: 28px; + } + + &_m { + --_--size: 32px; + } + + &_l { + --_--size: 42px; + } + + &_xl { + --_--size: 50px; + } + + &_xs, + &_s { + --_--font-size: var(--g-text-caption-1-font-size); + --_--line-height: var(--g-text-caption-1-line-height); + } + + &_m, + &_l { + --_--font-size: var(--g-text-body-1-font-size); + --_--line-height: var(--g-text-body-1-line-height); + } + + &_xl { + --_--font-size: var(--g-text-body-2-font-size); + --_--line-height: var(--g-text-body-2-line-height); + } + } + + &_theme { + &_normal { + &#{$block}_view { + &_filled { + --_--background-color: var(--g-color-base-misc-light); + --_--color: var(--g-color-text-misc); + } + + &_outlined { + --_--background-color: var(--g-color-base-background); + --_--border-color: var(--g-color-text-misc); + --_--color: var(--g-color-text-misc); + } + } + } + + &_brand { + &#{$block}_view { + &_filled { + --_--background-color: var(--g-color-base-brand); + --_--color: var(--g-color-text-brand-contrast); + } + + &_outlined { + --_--background-color: var(--g-color-base-background); + --_--border-color: var(--g-color-text-brand); + --_--color: var(--g-color-text-brand); + } + } + } + } +} diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx new file mode 100644 index 0000000000..b32d3e6345 --- /dev/null +++ b/src/components/Avatar/Avatar.tsx @@ -0,0 +1,91 @@ +import React from 'react'; + +import {blockNew} from '../utils/cn'; + +import {AvatarIcon} from './AvatarIcon'; +import {AvatarImage} from './AvatarImage'; +import {AvatarText} from './AvatarText'; +import type {AvatarProps} from './types/main'; + +import './Avatar.scss'; + +const b = blockNew('avatar'); + +export const Avatar = React.forwardRef((props, ref) => { + const { + size = 'm', + theme = 'normal', + view = 'filled', + backgroundColor, + borderColor, + title, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledby, + className, + style: styleProp, + qa, + } = props; + + const style = React.useMemo( + () => ({backgroundColor, color: borderColor, ...styleProp}), + [backgroundColor, borderColor, styleProp], + ); + + const renderContent = () => { + if ('imgUrl' in props && props.imgUrl) { + return ( + + ); + } + + if ('icon' in props && props.icon) { + return ( + + ); + } + + if ('text' in props && props.text) { + return ( + + ); + } + + return null; + }; + + return ( +
+ {renderContent()} +
+ ); +}); + +Avatar.displayName = 'Avatar'; diff --git a/src/components/Avatar/AvatarIcon/AvatarIcon.tsx b/src/components/Avatar/AvatarIcon/AvatarIcon.tsx new file mode 100644 index 0000000000..f3cd33d9d6 --- /dev/null +++ b/src/components/Avatar/AvatarIcon/AvatarIcon.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import {Icon} from '../../Icon'; +import type {AvatarSize} from '../types/common'; + +import type {AvatarIconProps} from './types'; + +const avatarSizeToIconSize: Record = { + xs: 14, + s: 16, + m: 16, + l: 20, + xl: 24, +}; + +export const AvatarIcon = ({icon, color, size, className}: AvatarIconProps) => { + const style = React.useMemo(() => ({color}), [color]); + + return ( +
+ +
+ ); +}; diff --git a/src/components/Avatar/AvatarIcon/index.ts b/src/components/Avatar/AvatarIcon/index.ts new file mode 100644 index 0000000000..9cb755cdfc --- /dev/null +++ b/src/components/Avatar/AvatarIcon/index.ts @@ -0,0 +1,2 @@ +export type {AvatarIconProps} from './types'; +export {AvatarIcon} from './AvatarIcon'; diff --git a/src/components/Avatar/AvatarIcon/types.ts b/src/components/Avatar/AvatarIcon/types.ts new file mode 100644 index 0000000000..fa8213b1ec --- /dev/null +++ b/src/components/Avatar/AvatarIcon/types.ts @@ -0,0 +1,7 @@ +import type {IconData} from '../../Icon'; +import type {AvatarCommonProps} from '../types/common'; + +export interface AvatarIconProps extends AvatarCommonProps { + icon: IconData; + color?: string; +} diff --git a/src/components/Avatar/AvatarImage/AvatarImage.tsx b/src/components/Avatar/AvatarImage/AvatarImage.tsx new file mode 100644 index 0000000000..303686b7cd --- /dev/null +++ b/src/components/Avatar/AvatarImage/AvatarImage.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +import {AVATAR_SIZES} from '../constants'; + +import type {AvatarImageProps} from './types'; + +export const AvatarImage = ({ + imgUrl, + fallbackImgUrl, + sizes, + srcSet, + alt, + loading, + size, + className, +}: AvatarImageProps) => { + 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 ( + {alt} + ); +}; diff --git a/src/components/Avatar/AvatarImage/index.ts b/src/components/Avatar/AvatarImage/index.ts new file mode 100644 index 0000000000..210d9ea26b --- /dev/null +++ b/src/components/Avatar/AvatarImage/index.ts @@ -0,0 +1,2 @@ +export type {AvatarImageProps} from './types'; +export {AvatarImage} from './AvatarImage'; diff --git a/src/components/Avatar/AvatarImage/types.ts b/src/components/Avatar/AvatarImage/types.ts new file mode 100644 index 0000000000..f0bc72d0cb --- /dev/null +++ b/src/components/Avatar/AvatarImage/types.ts @@ -0,0 +1,10 @@ +import type {AvatarCommonProps} from '../types/common'; + +export interface AvatarImageProps extends AvatarCommonProps { + imgUrl: string; + fallbackImgUrl?: string; + sizes?: string; + srcSet?: string; + alt?: string; + loading?: 'eager' | 'lazy'; +} diff --git a/src/components/Avatar/AvatarText/AvatarText.tsx b/src/components/Avatar/AvatarText/AvatarText.tsx new file mode 100644 index 0000000000..fb491afc27 --- /dev/null +++ b/src/components/Avatar/AvatarText/AvatarText.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import type {AvatarTextProps} from './types'; +import {getAvatarDisplayText} from './utils'; + +export const AvatarText = ({text, color, className}: AvatarTextProps) => { + const style = React.useMemo(() => ({color}), [color]); + const displayText = React.useMemo(() => getAvatarDisplayText(text), [text]); + + return ( +
+ {displayText} +
+ ); +}; diff --git a/src/components/Avatar/AvatarText/index.ts b/src/components/Avatar/AvatarText/index.ts new file mode 100644 index 0000000000..e1daf58bce --- /dev/null +++ b/src/components/Avatar/AvatarText/index.ts @@ -0,0 +1,3 @@ +export type {AvatarTextProps} from './types'; +export {getAvatarDisplayText} from './utils'; +export {AvatarText} from './AvatarText'; diff --git a/src/components/Avatar/AvatarText/types.ts b/src/components/Avatar/AvatarText/types.ts new file mode 100644 index 0000000000..8b8cf06208 --- /dev/null +++ b/src/components/Avatar/AvatarText/types.ts @@ -0,0 +1,6 @@ +import type {AvatarCommonProps} from '../types/common'; + +export interface AvatarTextProps extends AvatarCommonProps { + text: string; + color?: string; +} diff --git a/src/components/Avatar/AvatarText/utils.ts b/src/components/Avatar/AvatarText/utils.ts new file mode 100644 index 0000000000..97e3e504fb --- /dev/null +++ b/src/components/Avatar/AvatarText/utils.ts @@ -0,0 +1,7 @@ +export const getAvatarDisplayText = (text: string) => { + const words = text.split(' '); + const result = + words.length > 1 ? [words[0][0], words[1][0]].filter(Boolean).join('') : text.slice(0, 2); + + return result.toUpperCase(); +}; diff --git a/src/components/Avatar/README.md b/src/components/Avatar/README.md new file mode 100644 index 0000000000..9a47370830 --- /dev/null +++ b/src/components/Avatar/README.md @@ -0,0 +1,217 @@ + + +# Avatar + + + +```tsx +import {Avatar} from '@gravity-ui/uikit'; +``` + +The component intended to render avatars. It has three basic types of avatars: image, icon and text (initials). All of these types have special props to configure behaviour and appearance. + +## Types + +### Image + +This component can be used to render avatars using images. Provide the image via `imgUrl` property. + + + +Also, you can provide `srcSet` property to load images of different sizes. + + + +Avatar component has `fallbackImgUrl` property which allows you to provide the image that is shown when an image loading error occurs via the link `imgUrl` (CSP error or no original image). + + + +### Icon + +This component can be used to render avatars using icons. Provide the icon via `icon` property like in `Icon` component. + + + +### Text + +This component can be used to render avatars using text. Provide the text via `text` property. The text renders like initials (2 first letters of words) or just 2 first letters of a single word. + + + +## Appearance + +### Theme and view + +The Avatar component has predefined themes (`normal`, `brand`) and views (`filled`, `outlined`) + +Default theme: `normal` +Default view: `filled` + + + +### Custom colors + +Also, you can provide custom colors via props `backgroundColor`, `borderColor` and `color` (works only for icon and text avatars). These colors have a higher priority than the colors from the theme. + + + +### Size + +To control the size of the `Avatar` use the `size` property. The default size is `m`. Possible values: `xs`, `s`, `m`, `l`, `xl`. + + + +## Properties + +### Common + +| Name | Description | Type | Default | +| :-------------- | :-------------------------------------- | :-----------------------------: | :------: | +| size | Avatar size | `'xs'` `'s'` `'m'` `'l'` `'xl'` | `m` | +| theme | Avatar theme | `'normal'` `'brand'` | `normal` | +| view | Avatar view | `'filled'` `'outlined'` | `filled` | +| backgroundColor | Custom background color | `string` | | +| borderColor | Custom border color | `string` | | +| title | HTML `title` attributes | `string` | | +| aria-label | `aria-label` for avatar block | `string` | | +| aria-labelledby | `aria-labelledby` for avatar block | `string` | | +| className | Custom CSS class for root element | `string` | | +| qa | HTML `data-qa` attribute, used in tests | `string` | | + +### Image-specific + +| Name | Description | Type | Default | +| :------------- | :-------------------------------------- | :----------------: | :---------: | +| imgUrl | HTML img `src` attribute | `string` | | +| fallbackImgUrl | Fallback image, shown if error happened | `string` | | +| sizes | HTML img `sizes` attribute | `string` | | +| srcSet | HTML img `srcSet` attribute | `string` | | +| alt | HTML img `alt` attribute | `string` | props.title | +| loading | HTML img `loading` attribute | `'eager'` `'lazy'` | | + +### Icon-specific + +| Name | Description | Type | Default | +| :---- | :----------------- | :--------: | :-----: | +| icon | Source of SVG icon | `IconData` | | +| color | Custom icon color | `string` | | + +### Text-specific + +| Name | Description | Type | Default | +| :---- | :---------------- | :------: | :-----: | +| text | Avatar text | `string` | | +| color | Custom text color | `string` | | + +## CSS API + +| Name | Description | +| :---------------------------- | :---------------------- | +| `--g-avatar-size` | Size (width and height) | +| `--g-avatar-background-color` | Background color | +| `--g-avatar-border-color` | Border color | +| `--g-avatar-color` | Icon and text color | +| `--g-avatar-font-size` | Text font size | +| `--g-avatar-line-height` | Text line height | diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-chromium-linux.png new file mode 100644 index 0000000000..d849f90c6b Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-webkit-linux.png new file mode 100644 index 0000000000..0c343c9af8 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Icon-1-webkit-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-chromium-linux.png new file mode 100644 index 0000000000..8a7a8b192f Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-webkit-linux.png new file mode 100644 index 0000000000..603f4ccf56 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Image-1-webkit-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-ImageFallback-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-ImageFallback-1-chromium-linux.png new file mode 100644 index 0000000000..8a7a8b192f Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-ImageFallback-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-chromium-linux.png new file mode 100644 index 0000000000..d30c0c0f02 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-webkit-linux.png new file mode 100644 index 0000000000..969abb6b18 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Showcase-1-webkit-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-chromium-linux.png new file mode 100644 index 0000000000..e662f2dc70 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-webkit-linux.png new file mode 100644 index 0000000000..15f6aba578 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-Text-1-webkit-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-chromium-linux.png new file mode 100644 index 0000000000..85aaad554b Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-webkit-linux.png new file mode 100644 index 0000000000..00e4d243d7 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-TextInitials-1-webkit-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-chromium-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-chromium-linux.png new file mode 100644 index 0000000000..d279870575 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-chromium-linux.png differ diff --git a/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-webkit-linux.png b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-webkit-linux.png new file mode 100644 index 0000000000..f7f0b7ce61 Binary files /dev/null and b/src/components/Avatar/__snapshots__/Avatar.visual.test.tsx-snapshots/Avatar-render-story-WithBorder-1-webkit-linux.png differ diff --git a/src/components/Avatar/__stories__/Avatar.stories.tsx b/src/components/Avatar/__stories__/Avatar.stories.tsx new file mode 100644 index 0000000000..ef07ef382f --- /dev/null +++ b/src/components/Avatar/__stories__/Avatar.stories.tsx @@ -0,0 +1,249 @@ +import React from 'react'; + +import {faker} from '@faker-js/faker/locale/en'; +import {FaceRobot} from '@gravity-ui/icons'; +import {useArgs} from '@storybook/client-api'; +import type {Meta, StoryFn, StoryObj} from '@storybook/react'; + +import {Showcase} from '../../../demo/Showcase'; +import {ShowcaseItem} from '../../../demo/ShowcaseItem'; +import {Avatar} from '../Avatar'; + +import {getAvatarSrcSet} from './utils/getAvatarSrcSet'; + +const meta: Meta = { + title: 'Components/Data Display/Avatar', + component: Avatar, +}; + +export default meta; + +type Story = StoryObj; +type StoryFunc = StoryFn; + +const imgUrl = + 'data:image/png;base64,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'; + +const randomAvatars = faker.helpers + .uniqueArray(() => faker.number.int({min: 20, max: 500}), 30) + .reduce( + (sizes, num) => ({ + ...sizes, + [num]: faker.image.urlLoremFlickr({ + category: 'cats', + width: num, + height: Math.round((num / 640) * 480), + }), + }), + {}, + ); + +const imageProps = { + imgUrl, +}; + +const iconProps = { + backgroundColor: 'var(--g-color-base-brand)', + icon: FaceRobot, + color: 'var(--g-color-text-brand-contrast)', +}; + +const textProps = { + backgroundColor: 'var(--g-color-base-generic-medium)', + text: 'Charles Darwin', + color: 'var(--g-color-text-primary)', +}; + +const BORDER_COLOR = 'var(--g-color-line-misc)'; + +export const Image: Story = { + args: { + imgUrl, + }, +}; + +export const ImageSrcSet: StoryFunc = (args) => { + const [, setArgs] = useArgs(); + + React.useEffect(() => { + if (args.size) { + setArgs({srcSet: getAvatarSrcSet(args.size, randomAvatars)}); + } + }, [args.size, setArgs]); + + return ; +}; + +ImageSrcSet.args = { + imgUrl: faker.image.urlLoremFlickr({category: 'cats'}), + size: 'xl', +}; + +export const ImageFallback: Story = { + args: { + imgUrl: 'random_link', + fallbackImgUrl: imgUrl, + }, +}; + +export const Icon: Story = { + args: { + theme: 'brand', + icon: FaceRobot, + }, +}; + +export const Text: Story = { + args: { + theme: 'brand', + text: 'UI', + }, +}; + +export const TextInitials: Story = { + args: { + theme: 'brand', + text: 'Charles Darwin', + }, +}; + +export const WithBorder: Story = { + args: { + imgUrl, + borderColor: 'var(--g-color-line-misc)', + }, +}; + +export const AvatarShowcase: Story = { + name: 'Showcase', + render: () => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); + }, +}; diff --git a/src/components/UserAvatar/__stories__/getAvatarSrcSet.ts b/src/components/Avatar/__stories__/utils/getAvatarSrcSet.ts similarity index 71% rename from src/components/UserAvatar/__stories__/getAvatarSrcSet.ts rename to src/components/Avatar/__stories__/utils/getAvatarSrcSet.ts index 83549be241..78766fa85a 100644 --- a/src/components/UserAvatar/__stories__/getAvatarSrcSet.ts +++ b/src/components/Avatar/__stories__/utils/getAvatarSrcSet.ts @@ -1,19 +1,19 @@ -import {SIZES} from '../constants'; -import type {UserAvatarSize} from '../types'; +import {AVATAR_SIZES} from '../../constants'; +import type {AvatarSize} from '../../types/common'; import {getClosestNumber} from './getClosestNumber'; import {getSrcSet} from './getSrcSet'; import type {SrcSetType} from './types'; -export function getAvatarSrcSet( - size: UserAvatarSize, +export const getAvatarSrcSet = ( + size: AvatarSize, sizes: Record, {multipliers = [1, 2, 3, 4]} = {}, -) { +) => { const availableSizes = Object.keys(sizes) - .map((size) => Number(size)) + .map((item) => Number(item)) .sort((a, b) => a - b); - const baseSize = SIZES[size]; + const baseSize = AVATAR_SIZES[size]; const srcSet = multipliers.map((multiplier) => { const targetSize = multiplier * baseSize; const appropriateSize = getClosestNumber(targetSize, availableSizes); @@ -22,4 +22,4 @@ export function getAvatarSrcSet( }); return getSrcSet(srcSet as SrcSetType); -} +}; diff --git a/src/components/UserAvatar/__stories__/getClosestNumber.ts b/src/components/Avatar/__stories__/utils/getClosestNumber.ts similarity index 86% rename from src/components/UserAvatar/__stories__/getClosestNumber.ts rename to src/components/Avatar/__stories__/utils/getClosestNumber.ts index 2736a67b57..35a2226db9 100644 --- a/src/components/UserAvatar/__stories__/getClosestNumber.ts +++ b/src/components/Avatar/__stories__/utils/getClosestNumber.ts @@ -1,4 +1,4 @@ -export function getClosestNumber(targetNumber: number, availableNumbers: number[]) { +export const getClosestNumber = (targetNumber: number, availableNumbers: number[]) => { const stack = [...availableNumbers]; let previousNumber: number | undefined; @@ -23,4 +23,4 @@ export function getClosestNumber(targetNumber: number, availableNumbers: number[ } return previousNumber as number; -} +}; diff --git a/src/components/UserAvatar/__stories__/getSrcSet.ts b/src/components/Avatar/__stories__/utils/getSrcSet.ts similarity index 86% rename from src/components/UserAvatar/__stories__/getSrcSet.ts rename to src/components/Avatar/__stories__/utils/getSrcSet.ts index 268302c885..621a3c2c91 100644 --- a/src/components/UserAvatar/__stories__/getSrcSet.ts +++ b/src/components/Avatar/__stories__/utils/getSrcSet.ts @@ -1,6 +1,6 @@ import type {SrcSetType} from './types'; -export function getSrcSet(srcSet: SrcSetType) { +export const getSrcSet = (srcSet: SrcSetType) => { let srcSetString = ''; for (const item of srcSet) { @@ -16,4 +16,4 @@ export function getSrcSet(srcSet: SrcSetType) { } return srcSetString; -} +}; diff --git a/src/components/UserAvatar/__stories__/types.ts b/src/components/Avatar/__stories__/utils/types.ts similarity index 100% rename from src/components/UserAvatar/__stories__/types.ts rename to src/components/Avatar/__stories__/utils/types.ts diff --git a/src/components/Avatar/__tests__/Avatar.visual.test.tsx b/src/components/Avatar/__tests__/Avatar.visual.test.tsx new file mode 100644 index 0000000000..f3f8c36bbe --- /dev/null +++ b/src/components/Avatar/__tests__/Avatar.visual.test.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +import {expect} from '@playwright/experimental-ct-react'; + +import {Icon, Image, ImageFallback, Showcase, Text, TextInitials, WithBorder} from './stories'; + +import {test} from '~playwright/core'; + +test.describe('Avatar', () => { + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount, browserName}) => { + test.skip(browserName === 'webkit', 'Test is flaky for webkit'); + + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); + + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); +}); diff --git a/src/components/Avatar/__tests__/stories.ts b/src/components/Avatar/__tests__/stories.ts new file mode 100644 index 0000000000..7e5705170d --- /dev/null +++ b/src/components/Avatar/__tests__/stories.ts @@ -0,0 +1,13 @@ +import {composeStories} from '@storybook/react'; + +import * as Stories from '../__stories__/Avatar.stories'; + +export const { + Image, + ImageFallback, + Icon, + Text, + TextInitials, + WithBorder, + AvatarShowcase: Showcase, +} = composeStories(Stories); diff --git a/src/components/Avatar/constants.ts b/src/components/Avatar/constants.ts new file mode 100644 index 0000000000..aa49f83f9c --- /dev/null +++ b/src/components/Avatar/constants.ts @@ -0,0 +1,9 @@ +import type {AvatarSize} from './types/common'; + +export const AVATAR_SIZES: Record = { + xs: 24, + s: 28, + m: 32, + l: 42, + xl: 50, +}; diff --git a/src/components/Avatar/index.ts b/src/components/Avatar/index.ts new file mode 100644 index 0000000000..6e01fd1865 --- /dev/null +++ b/src/components/Avatar/index.ts @@ -0,0 +1,5 @@ +export type {AvatarSize} from './types/common'; +export type {AvatarProps, AvatarTheme, AvatarView} from './types/main'; +export {AVATAR_SIZES} from './constants'; +export {Avatar} from './Avatar'; +export {getAvatarDisplayText} from './AvatarText'; diff --git a/src/components/Avatar/types/common.ts b/src/components/Avatar/types/common.ts new file mode 100644 index 0000000000..a2d320f687 --- /dev/null +++ b/src/components/Avatar/types/common.ts @@ -0,0 +1,6 @@ +export type AvatarSize = 'xs' | 's' | 'm' | 'l' | 'xl'; + +export interface AvatarCommonProps { + size: AvatarSize; + className?: string; +} diff --git a/src/components/Avatar/types/main.ts b/src/components/Avatar/types/main.ts new file mode 100644 index 0000000000..5717172aba --- /dev/null +++ b/src/components/Avatar/types/main.ts @@ -0,0 +1,24 @@ +import type {DistributiveOmit} from '../../../types/utils'; +import type {DOMProps, QAProps} from '../../types'; +import type {AvatarIconProps} from '../AvatarIcon'; +import type {AvatarImageProps} from '../AvatarImage'; +import type {AvatarTextProps} from '../AvatarText'; + +import type {AvatarCommonProps, AvatarSize} from './common'; + +export type AvatarTheme = 'normal' | 'brand'; +export type AvatarView = 'filled' | 'outlined'; + +interface AvatarBaseProps extends DOMProps, QAProps { + size?: AvatarSize; + theme?: AvatarTheme; + view?: AvatarView; + backgroundColor?: string; + borderColor?: string; + title?: string; + 'aria-label'?: string; + 'aria-labelledby'?: string; +} + +export type AvatarProps = AvatarBaseProps & + DistributiveOmit; diff --git a/src/components/Icon/README.md b/src/components/Icon/README.md index 4fd8547b1e..0e636703aa 100644 --- a/src/components/Icon/README.md +++ b/src/components/Icon/README.md @@ -55,7 +55,7 @@ import CheckIcon from './check.svg'; | Name | Description | Type | Default | | :-------- | :-------------------------------------- | :---------------: | :--------------: | -| data | Source of SVG icon | `any` | | +| data | Source of SVG icon | `IconData` | | | width | `width` SVG attribute | `number` `string` | | | height | `height` SVG attribute | `number` `string` | | | size | Both `width` and `height` SVG attribute | `number` `string` | | diff --git a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-chromium-linux.png b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-chromium-linux.png index 466de4a10c..a9180a24e4 100644 Binary files a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-chromium-linux.png and b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-chromium-linux.png differ diff --git a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-webkit-linux.png b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-webkit-linux.png index 284517e5bd..96cc5a717b 100644 Binary files a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-webkit-linux.png and b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-Copy-1-webkit-linux.png differ diff --git a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-chromium-linux.png b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-chromium-linux.png index eb83a2a2d6..da8de28211 100644 Binary files a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-chromium-linux.png and b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-chromium-linux.png differ diff --git a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-webkit-linux.png b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-webkit-linux.png index 937a8ebf6e..bc32d13d9e 100644 Binary files a/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-webkit-linux.png and b/src/components/Label/__snapshots__/Label.visual.test.tsx-snapshots/Label-render-story-ShowcaseStory-1-webkit-linux.png differ diff --git a/src/components/Link/__stories__/LinkShowcase.tsx b/src/components/Link/__stories__/LinkShowcase.tsx index 4bc3ce4350..b1a52d617a 100644 --- a/src/components/Link/__stories__/LinkShowcase.tsx +++ b/src/components/Link/__stories__/LinkShowcase.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {Showcase} from '../../../demo/Showcase'; -import {ShowcaseGrid} from '../../../demo/ShowcaseGrid/ShowcaseGrid'; +import {ShowcaseGrid} from '../../../demo/ShowcaseGrid'; import {Link} from '../Link'; export function LinkShowcase() { diff --git a/src/components/Persona/Persona.tsx b/src/components/Persona/Persona.tsx index fb8c5b597d..f4abf64183 100644 --- a/src/components/Persona/Persona.tsx +++ b/src/components/Persona/Persona.tsx @@ -2,12 +2,12 @@ import React from 'react'; import {Envelope} from '@gravity-ui/icons'; -import {Icon} from '../Icon'; +import {Avatar} from '../Avatar'; import {PersonaWrap} from '../PersonaWrap'; import i18n from './i18n'; import type {PersonaProps} from './types'; -import {extractTextValue, extractTextView, getTwoLetters} from './utils'; +import {extractTextValue, extractTextView} from './utils'; export function Persona({ size = 's', @@ -31,10 +31,14 @@ export function Persona({ switch (type) { case 'person': - avatar = image ? {''} : {getTwoLetters(textValue)}; + avatar = image ? ( + + ) : ( + + ); break; case 'email': - avatar = ; + avatar = ; break; case 'empty': avatar = null; diff --git a/src/components/Persona/__tests__/Persona.test.tsx b/src/components/Persona/__tests__/Persona.test.tsx index 5f81b10a96..f2fb2ac1ae 100644 --- a/src/components/Persona/__tests__/Persona.test.tsx +++ b/src/components/Persona/__tests__/Persona.test.tsx @@ -3,10 +3,11 @@ import React from 'react'; import {queryByAttribute, render, screen} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import {getAvatarDisplayText} from '../../Avatar'; import {Persona} from '../Persona'; import i18n from '../i18n'; import type {PersonaProps} from '../types'; -import {extractTextValue, getTwoLetters} from '../utils'; +import {extractTextValue} from '../utils'; const MOCKED_TEXT = 'text'; const MOCKED_TEXT_NODE_CONTENT_VALUE = 'Some view'; @@ -24,8 +25,8 @@ describe('Persona', () => { render(); const user = userEvent.setup(); const textValue = extractTextValue(text); - const twoLetters = getTwoLetters(textValue); - const personaNode = screen.getByText(twoLetters); + const displayText = getAvatarDisplayText(textValue); + const personaNode = screen.getByText(displayText); await user.click(personaNode); expect(onClick).toBeCalledWith(textValue); }, diff --git a/src/components/Persona/utils.ts b/src/components/Persona/utils.ts index 68c17dcc44..ef07849bff 100644 --- a/src/components/Persona/utils.ts +++ b/src/components/Persona/utils.ts @@ -1,5 +1,3 @@ -import get from 'lodash/get'; - import type {PersonaText} from './types'; export const extractTextValue = (text: PersonaText = '') => { @@ -17,8 +15,3 @@ export const extractTextView = (text: PersonaText = '') => { return text; }; - -export function getTwoLetters(text: string) { - const words = text.split(' '); - return [get(words, '[0][0]'), get(words, '[1][0]')].filter(Boolean).join(''); -} diff --git a/src/components/PersonaWrap/PersonaWrap.scss b/src/components/PersonaWrap/PersonaWrap.scss index cb0f687f51..b3bf24ec9e 100644 --- a/src/components/PersonaWrap/PersonaWrap.scss +++ b/src/components/PersonaWrap/PersonaWrap.scss @@ -8,11 +8,10 @@ $block: '.#{variables.$ns}persona'; $transitionDuration: 0.1s; $transitionTimingFunction: ease-in-out; - height: $avatarSize; - display: inline-flex; - align-items: center; position: relative; z-index: 0; + display: inline-flex; + height: $avatarSize; border-radius: 20px; transition-property: background-color; @@ -56,11 +55,10 @@ $block: '.#{variables.$ns}persona'; &__main { @include mixins.button-reset(); - height: $avatarSize; display: inline-flex; align-items: center; - padding-inline-end: 6px; border-radius: inherit; + padding-inline-end: 6px; #{$block}_closeable & { padding-inline-end: 0; @@ -71,6 +69,7 @@ $block: '.#{variables.$ns}persona'; &:focus { outline: 2px solid var(--g-color-line-focus); } + &:focus:not(:focus-visible) { outline: 0; } @@ -78,18 +77,8 @@ $block: '.#{variables.$ns}persona'; } &__avatar { - width: $avatarSize; - height: $avatarSize; - display: flex; - align-items: center; - border-radius: 50%; - overflow: hidden; - justify-content: center; - background-color: var(--g-color-base-generic-accent); - - transition-property: background-color; - transition-duration: $transitionDuration; - transition-timing-function: $transitionTimingFunction; + --g-avatar-background-color: var(--g-color-base-generic-accent); + --g-avatar-color: var(--g-color-text-primary); #{$block}_size_n & { margin-inline-end: 12px; @@ -98,23 +87,6 @@ $block: '.#{variables.$ns}persona'; #{$block}_size_s & { margin-inline-end: 6px; } - - #{$block}_clickable:hover & { - background-color: var(--g-color-base-generic); - } - - span { - @include mixins.text-accent; - text-transform: uppercase; - font-size: 11px; - line-height: 11px; - } - - img { - width: $avatarSize; - height: $avatarSize; - object-fit: cover; - } } &__text { @@ -132,15 +104,14 @@ $block: '.#{variables.$ns}persona'; &__close { @include mixins.button-reset(); - height: $avatarSize; - width: 16px; + box-sizing: initial; display: inline-flex; - align-items: center; justify-content: center; + align-items: center; + width: 16px; cursor: pointer; padding-inline-end: 6px; color: var(--g-color-text-secondary); - box-sizing: initial; transition-property: color; transition-duration: $transitionDuration; @@ -157,6 +128,7 @@ $block: '.#{variables.$ns}persona'; #{$block}__close:focus & { outline: 2px solid var(--g-color-line-focus); } + #{$block}__close:focus:not(:focus-visible) & { outline: 0; } diff --git a/src/components/User/README.md b/src/components/User/README.md index eb23d1f231..9b779009f5 100644 --- a/src/components/User/README.md +++ b/src/components/User/README.md @@ -1,14 +1,66 @@ -## User + -Display user avatar and his brief info. +# User -### PropTypes + -| Name | Type | Required | Default | Description | -| :---------- | :--------------- | :------- | :------ | :-------------------------------------------------------------------------------------------------------------- | -| imgUrl | `string` | | | Url of user avatar | -| className | `string` | | | Root element class name | -| name | `string` | | | User name (first line of info) | -| description | `string` | | | User additional data (second line of info) | -| size | `UserAvatarSize` | | 'm' | Component size. Supported values is: `xs`, `s`, `m`, `l`, `xl`. With a smallest size user info is not rendered. | -| qa | `string` | | | HTML `data-qa` attribute, used in tests | +```tsx +import {User} from '@gravity-ui/uikit'; +``` + +General component for displaying a user avatar with a info block. It uses [Avatar](../Avatar/README.md) component to render the avatar. Also, it accepts custom react node as an avatar. + +## Name and description + +`User` component has properties `name` and `description` to display a info block. + + + +## Size + +To control the size of the `User` use the `size` property. The default size is `m`. Possible values: `xs`, `s`, `m`, `l`, `xl`. + +This propeperty passes to the internal `Avatar` component too. + + + +## Properties + +| Name | Description | Type | Default | +| :-------------- | :-------------------------------------- | :----------------------------------------------------------------: | :-----: | +| avatar | User avatar | [AvatarProps](../Avatar/README.md#properties) `React.ReactElement` | | +| name | User name | `React.ReactNode` | | +| description | User description | `React.ReactNode` | | +| size | User block size | `'xs'` `'s'` `'m'` `'l'` `'xl'` | `m` | +| aria-label | `aria-label` for user block | `string` | | +| aria-labelledby | `aria-labelledby` for user block | `string` | | +| className | Custom CSS class for root element | `string` | | +| qa | HTML `data-qa` attribute, used in tests | `string` | | diff --git a/src/components/User/User.scss b/src/components/User/User.scss index 2575414232..8adbe1ebad 100644 --- a/src/components/User/User.scss +++ b/src/components/User/User.scss @@ -1,19 +1,24 @@ @use '../../../styles/mixins'; @use '../variables'; -$block: '.#{variables.$ns}user'; +$block: '.#{variables.$ns-new}user'; #{$block} { display: flex; align-items: center; + &__avatar { + display: flex; + align-items: center; + } + &__info { - @include mixins.text-body-short(); + flex: auto; display: flex; flex-direction: column; + min-width: 0; - flex: 1; - max-width: 165px; + @include mixins.text-body-short(); #{$block}__name { color: var(--g-color-text-primary); diff --git a/src/components/User/User.tsx b/src/components/User/User.tsx index c1be92ce4e..9f12992282 100644 --- a/src/components/User/User.tsx +++ b/src/components/User/User.tsx @@ -1,36 +1,56 @@ import React from 'react'; -import {UserAvatar} from '../UserAvatar'; -import type {UserAvatarSize} from '../UserAvatar'; -import type {QAProps} from '../types'; -import {block} from '../utils/cn'; +import {Avatar} from '../Avatar'; +import {blockNew} from '../utils/cn'; + +import type {UserProps} from './types'; import './User.scss'; -const b = block('user'); +const b = blockNew('user'); -export interface UserProps extends QAProps { - name?: string; - description?: string; - imgUrl?: string; - size?: UserAvatarSize; - className?: string; -} +export const User = React.forwardRef( + ( + { + avatar, + name, + description, + size, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledby, + className, + style, + qa, + }, + ref, + ) => { + const showDescription = Boolean(size !== 'xs' && description); -export function User({name, description, imgUrl, size = 'm', className, qa}: UserProps) { - const compact = size === 'xs'; + return ( +
+ {avatar ? ( +
+ {React.isValidElement(avatar) ? avatar : } +
+ ) : null} + {name || showDescription ? ( +
+ {name ? {name} : null} + {showDescription ? ( + {description} + ) : null} +
+ ) : null} +
+ ); + }, +); - return ( -
- {imgUrl && } - {(name || description) && ( -
- {name && {name}} - {!compact && description && ( - {description} - )} -
- )} -
- ); -} +User.displayName = 'User'; diff --git a/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-chromium-linux.png b/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-chromium-linux.png new file mode 100644 index 0000000000..81de70c937 Binary files /dev/null and b/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-chromium-linux.png differ diff --git a/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-webkit-linux.png b/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-webkit-linux.png new file mode 100644 index 0000000000..82f32c94d9 Binary files /dev/null and b/src/components/User/__snapshots__/User.visual.test.tsx-snapshots/User-render-story-Default-1-webkit-linux.png differ diff --git a/src/components/User/__stories__/User.stories.tsx b/src/components/User/__stories__/User.stories.tsx index 1efe19ba94..3c3bec6252 100644 --- a/src/components/User/__stories__/User.stories.tsx +++ b/src/components/User/__stories__/User.stories.tsx @@ -1,18 +1,22 @@ -import React from 'react'; - -import type {Meta, StoryFn} from '@storybook/react'; +import type {Meta, StoryObj} from '@storybook/react'; import {User} from '../User'; -import type {UserProps} from '../User'; -export default { +const meta: Meta = { title: 'Components/Data Display/User', component: User, -} as Meta; +}; + +export default meta; + +type Story = StoryObj; -export const Default: StoryFn = (args) => ; -Default.args = { - name: 'Isaac', - description: 'user@gravity-ui.com', - imgUrl: 'data:image/png;base64,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', +export const Default: Story = { + args: { + avatar: { + imgUrl: 'data:image/png;base64,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', + }, + name: 'Isaac', + description: 'user@gravity-ui.com', + }, }; diff --git a/src/components/User/__tests__/User.test.tsx b/src/components/User/__tests__/User.test.tsx new file mode 100644 index 0000000000..98b87868e0 --- /dev/null +++ b/src/components/User/__tests__/User.test.tsx @@ -0,0 +1,37 @@ +import React from 'react'; + +import {render, screen} from '@testing-library/react'; + +import {User} from '../User'; + +describe('User', () => { + test('render avatar', () => { + render( + Avatar} name="Charles Darwin" description="charles@mail.ai" />, + ); + + const avatar = screen.getByText('Avatar'); + + expect(avatar).toBeVisible(); + }); + + test('render name', () => { + render( + Avatar} name="Charles Darwin" description="charles@mail.ai" />, + ); + + const name = screen.getByText('Charles Darwin'); + + expect(name).toBeVisible(); + }); + + test('render description', () => { + render( + Avatar} name="Charles Darwin" description="charles@mail.ai" />, + ); + + const description = screen.getByText('charles@mail.ai'); + + expect(description).toBeVisible(); + }); +}); diff --git a/src/components/User/__tests__/User.visual.test.tsx b/src/components/User/__tests__/User.visual.test.tsx new file mode 100644 index 0000000000..ece5a432ce --- /dev/null +++ b/src/components/User/__tests__/User.visual.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import {expect} from '@playwright/experimental-ct-react'; + +import {Default} from './stories'; + +import {test} from '~playwright/core'; + +test.describe('User', () => { + test('render story: ', async ({mount}) => { + const component = await mount(); + + await expect(component).toHaveScreenshot(); + }); +}); diff --git a/src/components/User/__tests__/stories.ts b/src/components/User/__tests__/stories.ts new file mode 100644 index 0000000000..ad381f1b5e --- /dev/null +++ b/src/components/User/__tests__/stories.ts @@ -0,0 +1,5 @@ +import {composeStories} from '@storybook/react'; + +import * as Stories from '../__stories__/User.stories'; + +export const {Default} = composeStories(Stories); diff --git a/src/components/User/index.ts b/src/components/User/index.ts index f6b9f36c6e..b2563fe154 100644 --- a/src/components/User/index.ts +++ b/src/components/User/index.ts @@ -1 +1,2 @@ -export * from './User'; +export type {UserSize, UserProps} from './types'; +export {User} from './User'; diff --git a/src/components/User/types.ts b/src/components/User/types.ts new file mode 100644 index 0000000000..f5f76f355e --- /dev/null +++ b/src/components/User/types.ts @@ -0,0 +1,16 @@ +import type React from 'react'; + +import type {DistributiveOmit} from '../../types/utils'; +import type {AvatarProps} from '../Avatar'; +import type {DOMProps, QAProps} from '../types'; + +export type UserSize = 'xs' | 's' | 'm' | 'l' | 'xl'; + +export interface UserProps extends DOMProps, QAProps { + avatar?: DistributiveOmit | React.ReactElement; + name?: React.ReactNode; + description?: React.ReactNode; + size?: UserSize; + 'aria-label'?: string; + 'aria-labelledby'?: string; +} diff --git a/src/components/UserAvatar/README.md b/src/components/UserAvatar/README.md deleted file mode 100644 index 8fac13d836..0000000000 --- a/src/components/UserAvatar/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## UserAvatar - -Component for displaying user avatar. - -### PropTypes - -| 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 | -| loading | `eager \| lazy` | | | The loading attribute specifies whether a browser should load an image immediately or to defer loading. | -| qa | `string` | | | HTML `data-qa` attribute, used in tests | diff --git a/src/components/UserAvatar/UserAvatar.scss b/src/components/UserAvatar/UserAvatar.scss deleted file mode 100644 index 483bd10804..0000000000 --- a/src/components/UserAvatar/UserAvatar.scss +++ /dev/null @@ -1,47 +0,0 @@ -@use '../variables'; - -$block: '.#{variables.$ns}user-avatar'; - -#{$block} { - display: inline-block; - overflow: hidden; - - box-sizing: border-box; - - border-radius: 50%; - background-color: var(--g-color-base-background); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - - &_size { - &_xs { - width: 24px; - height: 24px; - } - - &_s { - width: 28px; - height: 28px; - } - - &_m { - width: 32px; - height: 32px; - } - - &_l { - width: 42px; - height: 42px; - } - - &_xl { - width: 50px; - height: 50px; - } - } - - &__figure { - object-fit: cover; - } -} diff --git a/src/components/UserAvatar/UserAvatar.tsx b/src/components/UserAvatar/UserAvatar.tsx deleted file mode 100644 index a73f83325a..0000000000 --- a/src/components/UserAvatar/UserAvatar.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; - -import type {QAProps} from '../types'; -import {block} from '../utils/cn'; - -import {SIZES} from './constants'; -import type {UserAvatarSize} from './types'; - -import './UserAvatar.scss'; - -export interface UserAvatarProps extends QAProps { - imgUrl?: string; - fallbackImgUrl?: string; - size?: UserAvatarSize; - srcSet?: string; - sizes?: string; - title?: string; - className?: string; - loading?: 'eager' | 'lazy'; - /** @deprecated Use appropriate component, like `