Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Avatar): Refactor Avatar component to use CSS modules behind feature flag #4885

Merged
merged 13 commits into from
Sep 11, 2024
5 changes: 5 additions & 0 deletions .changeset/tame-boats-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Refactor Avatar component to use CSS modules behind feature flag
244 changes: 128 additions & 116 deletions e2e/components/Avatar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,139 +3,151 @@ import {visit} from '../test-helpers/storybook'
import {themes} from '../test-helpers/themes'

test.describe('Avatar', () => {
test.describe('Default', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar--default',
globals: {
colorScheme: theme,
},
})
for (const enabled of [true, false]) {
test.describe(`Feature flag enabled: ${enabled}`, () => {
test.describe('Default', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar--default',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Default.${theme}.png`)
})
// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Default.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar--default',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar--default',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
})
})
})
})
}
})
}
})

test.describe('Size', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size',
globals: {
colorScheme: theme,
},
})
test.describe('Size', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size.${theme}.png`)
})
// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
})
})
})
})
}
})
}
})

test.describe('Size Responsive', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size-responsive',
globals: {
colorScheme: theme,
},
})
test.describe('Size Responsive', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size-responsive',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size Responsive.${theme}.png`)
})
// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Size Responsive.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size-responsive',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--size-responsive',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
})
})
})
})
}
})
}
})

test.describe('Square', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--square',
globals: {
colorScheme: theme,
},
})
test.describe('Square', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--square',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Square.${theme}.png`)
})
// Default state
expect(await page.screenshot()).toMatchSnapshot(`Avatar.Square.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--square',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-avatar-features--square',
globals: {
colorScheme: theme,
primer_react_css_modules_team: enabled,
},
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',
},
},
})
})
})
})
}
})
}
})
})
}
})
10 changes: 10 additions & 0 deletions packages/react/src/Avatar/Avatar.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ export default {

export const Square = () => <Avatar square alt="primer" src="https://avatars.githubusercontent.com/primer" />

export const SquareSxProp = () => (
<Avatar
square
sx={{border: '1px solid red'}}
size={40}
alt="primer"
src="https://avatars.githubusercontent.com/primer"
/>
)

export const Size = () => (
<div>
<Avatar size={4} alt="mona" src="https://avatars.githubusercontent.com/u/92997159?v=4" />
Expand Down
31 changes: 31 additions & 0 deletions packages/react/src/Avatar/Avatar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
:where(.Avatar) {
display: inline-block;
width: var(--avatarSize-regular);
height: var(--avatarSize-regular);
overflow: hidden; /* Ensure page layout in Firefox should images fail to load */
line-height: 1;
vertical-align: middle;
border-radius: 50%;
box-shadow: 0 0 0 1px var(--avatar-borderColor);

&:where([data-square='true']) {
border-radius: var(--borderRadius-medium);
}

&:where([data-responsive='true']) {
@media screen and (--viewportRange-narrow) {
width: var(--avatarSize-narrow);
height: var(--avatarSize-narrow);
}

@media screen and (--viewportRange-regular) {
width: var(--avatarSize-regular);
height: var(--avatarSize-regular);
}

@media screen and (--viewportRange-wide) {
width: var(--avatarSize-wide);
height: var(--avatarSize-wide);
}
}
}
Loading
Loading