Skip to content

Commit

Permalink
feat!: rework Avatar, User and UserLabel components (#1991)
Browse files Browse the repository at this point in the history
  • Loading branch information
DakEnviy authored Dec 26, 2024
1 parent 10b13f6 commit 515f4d5
Show file tree
Hide file tree
Showing 122 changed files with 871 additions and 675 deletions.
12 changes: 12 additions & 0 deletions playwright/core/expectScreenshotFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export const expectScreenshotFixture: PlaywrightFixture<ExpectScreenshotFixture>

const themes = paramsThemes || defaultParams.themes;

// Wait for loading of all the images
const locators = await page.locator('//img').all();
await Promise.all(
locators.map((locator) =>
locator.evaluate(
(image: HTMLImageElement) =>
image.complete ||
new Promise<unknown>((resolve) => image.addEventListener('load', resolve)),
),
),
);

if (themes?.includes('light')) {
await page.emulateMedia({colorScheme: 'light'});

Expand Down
2 changes: 0 additions & 2 deletions playwright/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const config: PlaywrightTestConfig = {
updateSnapshots: process.env.UPDATE_REQUEST ? 'all' : 'missing',
snapshotPathTemplate:
'{testDir}/{testFileDir}/../__snapshots__/{testFileName}-snapshots/{arg}{-projectName}-linux{ext}',
/* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
/* Maximum time one test can run for. */
timeout: 10 * 1000,
/* Run tests in files in parallel */
Expand All @@ -52,7 +51,6 @@ const config: PlaywrightTestConfig = {
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
headless: true,
/* Port to use for Playwright component endpoint. */
screenshot: 'only-on-failure',
timezoneId: 'UTC',
ctCacheDir: process.env.IS_DOCKER ? '.cache-docker' : '.cache',
Expand Down
22 changes: 11 additions & 11 deletions scripts/playwright-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ command_exists() {
}

run_command() {
$CONTAINER_TOOL run --rm --network host -it -w /work \
-v $(pwd):/work \
-v "$NODE_MODULES_CACHE_DIR:/work/node_modules" \
-e IS_DOCKER=1 \
"$IMAGE_NAME:$IMAGE_TAG" \
/bin/bash -c "$1"
$CONTAINER_TOOL run --rm --network host -it -w /work \
-v $(pwd):/work \
-v "$NODE_MODULES_CACHE_DIR:/work/node_modules" \
-e IS_DOCKER=1 \
"$IMAGE_NAME:$IMAGE_TAG" \
/bin/bash -c "$1"
}

if command_exists docker; then
Expand All @@ -30,14 +30,14 @@ else
fi

if [[ "$1" = "clear-cache" ]]; then
rm -rf "$NODE_MODULES_CACHE_DIR"
rm -rf "./playwright/.cache-docker"
exit 0
rm -rf "$NODE_MODULES_CACHE_DIR"
rm -rf "./playwright/.cache-docker"
exit 0
fi

if [[ ! -d "$NODE_MODULES_CACHE_DIR" ]]; then
mkdir -p "$NODE_MODULES_CACHE_DIR"
run_command 'npm ci'
mkdir -p "$NODE_MODULES_CACHE_DIR"
run_command 'npm ci'
fi

run_command "$1"
96 changes: 58 additions & 38 deletions src/components/Avatar/Avatar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ $block: '.#{variables.$ns}avatar';

#{$block} {
--_--size: #{avatar-variables.$default-size};
--_--background-color: var(--g-color-base-misc-light);
--_--border-width: 2px;
--_--inner-border-width: 3px;
--_--border-color: currentColor;
--_--color: var(--g-color-text-misc);
--_--background-color: var(--g-color-base-misc-light);
--_--text-color: var(--g-color-text-misc);
--_--font-weight: var(--g-text-body-font-weight);
--_--font-size: var(--g-text-body-1-font-size);
--_--line-height: var(--g-text-body-1-line-height);
--_--font-weight: var(--g-text-body-font-weight);

overflow: hidden;
display: inline-flex;
Expand All @@ -21,28 +23,6 @@ $block: '.#{variables.$ns}avatar';
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: var(--_--font-weight);
}

&_with-border,
&_view_outlined {
position: relative;
Expand All @@ -57,11 +37,13 @@ $block: '.#{variables.$ns}avatar';
}

&::before {
border: 3px solid var(--g-color-base-background);
border: var(--g-avatar-inner-border-width, var(--_--inner-border-width)) solid
var(--g-color-base-background);
}

&::after {
border: 2px solid var(--g-avatar-border-color, var(--_--border-color));
border: var(--g-avatar-border-width, var(--_--border-width)) solid
var(--g-avatar-border-color, var(--_--border-color));
}
}

Expand All @@ -72,30 +54,46 @@ $block: '.#{variables.$ns}avatar';
}
}

&_2xs {
&_3xs,
&_2xs,
&_xs {
--_--font-weight: var(--g-text-caption-font-weight);
--_--font-size: var(--g-text-caption-1-font-size);
--_--line-height: var(--g-text-caption-1-line-height);
--_--font-weight: var(--g-text-caption-font-weight);
}

&_xs,
&_s {
--_--font-size: var(--g-text-caption-1-font-size);
--_--line-height: var(--g-text-caption-1-line-height);
--_--font-weight: var(--g-text-caption-font-weight);
--_--font-size: var(--g-text-caption-2-font-size);
--_--line-height: var(--g-text-caption-2-line-height);
}

&_m,
&_l {
--_--font-weight: var(--g-text-subheader-font-weight);
--_--font-size: var(--g-text-subheader-1-font-size);
--_--line-height: var(--g-text-subheader-1-line-height);
--_--font-weight: var(--g-text-subheader-font-weight);
}

&_xl {
--_--font-weight: var(--g-text-subheader-font-weight);
--_--font-size: var(--g-text-subheader-2-font-size);
--_--line-height: var(--g-text-subheader-2-line-height);
--_--font-weight: var(--g-text-subheader-font-weight);
}

&_3xs,
&_2xs {
--_--border-width: 1.5px;
--_--inner-border-width: 2.5px;
}

&_xs,
&_s,
&_m,
&_l,
&_xl {
--_--border-width: 2px;
--_--inner-border-width: 3px;
}
}

Expand All @@ -104,13 +102,13 @@ $block: '.#{variables.$ns}avatar';
&#{$block}_view {
&_filled {
--_--background-color: var(--g-color-base-misc-light);
--_--color: var(--g-color-text-misc);
--_--text-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);
--_--text-color: var(--g-color-text-misc);
}
}
}
Expand All @@ -119,15 +117,37 @@ $block: '.#{variables.$ns}avatar';
&#{$block}_view {
&_filled {
--_--background-color: var(--g-color-base-brand);
--_--color: var(--g-color-text-brand-contrast);
--_--text-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);
--_--text-color: var(--g-color-text-brand);
}
}
}
}

&__image {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}

&__icon {
color: var(--g-avatar-text-color, var(--_--text-color));

& > svg {
display: block;
}
}

&__text {
color: var(--g-avatar-text-color, var(--_--text-color));
font-weight: var(--g-avatar-font-weight, var(--_--font-weight));
font-size: var(--g-avatar-font-size, var(--_--font-size));
line-height: var(--g-avatar-line-height, var(--_--line-height));
}
}
6 changes: 2 additions & 4 deletions src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

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

import {AvatarIcon} from './AvatarIcon';
import {AvatarImage} from './AvatarImage';
Expand All @@ -20,8 +21,6 @@ export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>((props, ref)
backgroundColor,
borderColor,
title,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledby,
className,
style: styleProp,
qa,
Expand Down Expand Up @@ -75,11 +74,10 @@ export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>((props, ref)
className={b({size, theme, view, 'with-border': Boolean(borderColor)}, className)}
title={title}
role="img"
aria-label={ariaLabel}
aria-labelledby={ariaLabelledby}
style={style}
data-qa={qa}
ref={ref}
{...filterDOMProps(props, {labelable: true})}
>
{renderContent()}
</div>
Expand Down
1 change: 1 addition & 0 deletions src/components/Avatar/AvatarIcon/AvatarIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {AvatarSize} from '../types/common';
import type {AvatarIconProps} from './types';

const avatarSizeToIconSize: Record<AvatarSize, number> = {
'3xs': 10,
'2xs': 12,
xs: 14,
s: 16,
Expand Down
4 changes: 2 additions & 2 deletions src/components/Avatar/AvatarText/AvatarText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import React from 'react';
import type {AvatarTextProps} from './types';
import {getAvatarDisplayText} from './utils';

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

return (
<div style={style} className={className}>
Expand Down
18 changes: 13 additions & 5 deletions src/components/Avatar/AvatarText/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
export const getAvatarDisplayText = (text: string) => {
const words = text.split(/\s+/);
const result =
words.length > 1 ? [words[0][0], words[1][0]].filter(Boolean).join('') : text.slice(0, 2);
import type {AvatarSize} from '../types/common';

return result.toUpperCase();
export const getAvatarDisplayText = (text: string, size: AvatarSize) => {
if (size === '3xs') {
return text[0].toUpperCase();
}

const words = text.split(/[^a-zA-Z]+/);

if (words.length <= 1) {
return text.slice(0, 2).toUpperCase();
}

return [words[0][0], words[1][0]].filter(Boolean).join('').toUpperCase();
};
51 changes: 29 additions & 22 deletions src/components/Avatar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,13 @@ LANDING_BLOCK-->

### Size

To control the size of the `Avatar` use the `size` property. The default size is `m`. Possible values: `2xs`, `xs`, `s`, `m`, `l`, `xl`.
To control the size of the `Avatar` use the `size` property. The default size is `m`. Possible values: `3xs`, `2xs`, `xs`, `s`, `m`, `l`, `xl`.

<!--LANDING_BLOCK
<ExampleBlock
code={`
<Avatar text="Charles Darwin" theme="brand" size="3xs" />
<Avatar text="Charles Darwin" theme="brand" size="2xs" />
<Avatar text="Charles Darwin" theme="brand" size="xs" />
<Avatar text="Charles Darwin" theme="brand" size="s" />
Expand All @@ -155,6 +156,7 @@ To control the size of the `Avatar` use the `size` property. The default size is
<Avatar text="Charles Darwin" theme="brand" size="xl" />
`}
>
<UIKit.Avatar text="Charles Darwin" theme="brand" size="3xs" />
<UIKit.Avatar text="Charles Darwin" theme="brand" size="2xs" />
<UIKit.Avatar text="Charles Darwin" theme="brand" size="xs" />
<UIKit.Avatar text="Charles Darwin" theme="brand" size="s" />
Expand All @@ -169,19 +171,21 @@ LANDING_BLOCK-->

### Common

| Name | Description | Type | Default |
| :-------------- | :-------------------------------------- | :-------------------------------------: | :------: |
| size | Avatar size | `'2xs'` `'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` | |
| style | HTML style attribute | `React.CSSProperties` | |
| qa | HTML `data-qa` attribute, used in tests | `string` | |
| Name | Description | Type | Default |
| :--------------- | :-------------------------------------- | :---------------------------------------------: | :------: |
| size | Avatar size | `'3xs'` `'2xs'` `'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` | |
| aria-describedby | `aria-describedby` for avatar block | `string` | |
| aria-details | `aria-details` for avatar block | `string` | |
| className | Custom CSS class for root element | `string` | |
| style | HTML style attribute | `React.CSSProperties` | |
| qa | HTML `data-qa` attribute, used in tests | `string` | |

### Image-specific

Expand Down Expand Up @@ -210,11 +214,14 @@ LANDING_BLOCK-->

## 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 |
| Name | Description |
| :------------------------------ | :---------------------- |
| `--g-avatar-size` | Size (width and height) |
| `--g-avatar-border-width` | Border width |
| `--g-avatar-inner-border-width` | Inner border width |
| `--g-avatar-border-color` | Border color |
| `--g-avatar-background-color` | Background color |
| `--g-avatar-text-color` | Icon and text color |
| `--g-avatar-font-weight` | Text font weight |
| `--g-avatar-font-size` | Text font size |
| `--g-avatar-line-height` | Text line height |
Binary file not shown.
Binary file not shown.
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.
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.
Binary file not shown.
Binary file not shown.
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.
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.
Binary file not shown.
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.
Binary file not shown.
Binary file not shown.
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.
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.
Binary file not shown.
Binary file not shown.
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.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Loading

0 comments on commit 515f4d5

Please sign in to comment.