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 and amje committed Jan 9, 2025
1 parent c43cdf5 commit 7c45de9
Show file tree
Hide file tree
Showing 53 changed files with 893 additions and 704 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 * as 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 @@ -4,6 +4,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
@@ -1,9 +1,9 @@
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();
};
Loading

0 comments on commit 7c45de9

Please sign in to comment.