Skip to content

Commit

Permalink
refactor(CounterLabel): update to use CSS Modules behind flag (#4965)
Browse files Browse the repository at this point in the history
* refactor(CounterLabel): update to use CSS Modules behind flag

* chore: add changeset

* test: update snapshots and remove duplicate tests

* chore: update css modules

* Update packages/react/src/CounterLabel/CounterLabel.module.css

Co-authored-by: Katie Langerman <18661030+langermank@users.noreply.github.com>

* Update packages/react/src/CounterLabel/CounterLabel.module.css

Co-authored-by: Katie Langerman <18661030+langermank@users.noreply.github.com>

* test(e2e): update e2e tests for counter label

* chore: fix spacing to use original px value

* chore: update size to match rails

* chore: add fallbacks in styled components case

* Update packages/react/src/CounterLabel/CounterLabel.tsx

Co-authored-by: Katie Langerman <18661030+langermank@users.noreply.github.com>

* test: update snapshots

* test: update story ids to include features

* test(vrt): update snapshots

* chore: update import for CounterLabel

---------

Co-authored-by: Josh Black <joshblack@users.noreply.github.com>
Co-authored-by: Katie Langerman <18661030+langermank@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 25, 2024
1 parent 954170b commit 5426a9a
Show file tree
Hide file tree
Showing 143 changed files with 225 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-lions-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Update CounterLabel to use CSS Modules behind feature flag
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.
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.
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.
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.
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.
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 68 additions & 57 deletions e2e/components/CounterLabel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,83 @@ import {test, expect} from '@playwright/test'
import {visit} from '../test-helpers/storybook'
import {themes} from '../test-helpers/themes'

test.describe('CounterLabel', () => {
test.describe('Default', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-counterlabel--default',
globals: {
colorScheme: theme,
},
})
const stories = [
{
title: 'Default',
id: 'components-counterlabel--default',
},
{
title: 'Primary Theme',
id: 'components-counterlabel-features--primary-theme',
},
{
title: 'Secondary Theme',
id: 'components-counterlabel-features--secondary-theme',
},
] as const

// Default state
expect(await page.screenshot()).toMatchSnapshot(`CounterLabel.Default.${theme}.png`)
})
test.describe('CounterLabel', () => {
for (const story of stories) {
test.describe(story.title, () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: story.id,
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-counterlabel--default',
globals: {
colorScheme: theme,
},
// Default state
expect(await page.screenshot()).toMatchSnapshot(`CounterLabel.${story.title}.${theme}.png`)
})
await expect(page).toHaveNoViolations({
rules: {
'color-contrast': {
enabled: theme !== 'dark_dimmed',

test('default (styled-components) @vrt', async ({page}) => {
await visit(page, {
id: story.id,
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: false,
},
},
},
})
})
})
}
})
})

test.describe('Primary Theme', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-counterlabel-features--primary-theme',
globals: {
colorScheme: theme,
},
// Default state
expect(await page.screenshot()).toMatchSnapshot(`CounterLabel.${story.title}.${theme}.png`)
})

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

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

test('axe (styled-components) @aat', async ({page}) => {
await visit(page, {
id: story.id,
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: false,
},
},
},
})
await expect(page).toHaveNoViolations()
})
})
})
}
})
}
})
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export default {
} as Meta<typeof CounterLabel>

export const PrimaryTheme: StoryFn<typeof CounterLabel> = () => <CounterLabel scheme="primary">12</CounterLabel>

export const SecondaryTheme: StoryFn<typeof CounterLabel> = () => <CounterLabel scheme="secondary">12</CounterLabel>
25 changes: 25 additions & 0 deletions packages/react/src/CounterLabel/CounterLabel.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.CounterLabel {
display: inline-block;
padding: var(--base-size-2) var(--base-size-6);
font-size: var(--text-body-size-small);
font-weight: var(--base-text-weight-semibold);
/* stylelint-disable-next-line primer/typography */
line-height: 1;
border: var(--borderWidth-thin) solid var(--counter-borderColor);
/* stylelint-disable-next-line primer/borders */
border-radius: 20px;

&[data-scheme='primary'] {
color: var(--fgColor-onEmphasis);
background-color: var(--bgColor-neutral-emphasis);
}

&[data-scheme='secondary'] {
color: var(--fgColor-default);
background-color: var(--bgColor-neutral-muted);
}

&:empty {
display: none;
}
}
16 changes: 15 additions & 1 deletion packages/react/src/CounterLabel/CounterLabel.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import React from 'react'
import type {StoryFn, Meta} from '@storybook/react'
import type {StoryFn, Meta, StoryObj} from '@storybook/react'
import CounterLabel from './CounterLabel'

export default {
title: 'Components/CounterLabel',
component: CounterLabel,
} as Meta<typeof CounterLabel>

export const Default: StoryFn<typeof CounterLabel> = () => <CounterLabel>12</CounterLabel>

export const Playground: StoryObj<typeof CounterLabel> = {
render: args => <CounterLabel {...args}>12</CounterLabel>,
args: {
scheme: 'primary',
},
argTypes: {
scheme: {
control: 'select',
options: ['primary', 'secondary'],
},
},
}
101 changes: 69 additions & 32 deletions packages/react/src/CounterLabel/CounterLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import {clsx} from 'clsx'
import type {HTMLAttributes} from 'react'
import React, {forwardRef} from 'react'
import Box from '../Box'
import type {BetterSystemStyleObject, SxProp} from '../sx'
import {merge} from '../sx'
import VisuallyHidden from '../_VisuallyHidden'
import styled from 'styled-components'
import {get} from '../constants'
import sx from '../sx'
import type {SxProp} from '../sx'
import {VisuallyHidden} from '../VisuallyHidden'
import {defaultSxProp} from '../utils/defaultSxProp'
import {useFeatureFlag} from '../FeatureFlags'
import Box from '../Box'
import classes from './CounterLabel.module.css'

export type CounterLabelProps = React.PropsWithChildren<
HTMLAttributes<HTMLSpanElement> & {
Expand All @@ -14,42 +19,74 @@ export type CounterLabelProps = React.PropsWithChildren<
>

const CounterLabel = forwardRef<HTMLSpanElement, CounterLabelProps>(
({scheme = 'secondary', sx = defaultSxProp, children, className, ...props}, forwardedRef) => {
({scheme = 'secondary', sx = defaultSxProp, className, children, ...rest}, forwardedRef) => {
const enabled = useFeatureFlag('primer_react_css_modules_team')
const label = <VisuallyHidden>&nbsp;({children})</VisuallyHidden>
const counterProps = {
ref: forwardedRef,
['aria-hidden']: 'true' as const,
['data-scheme']: scheme,
...rest,
}

if (enabled) {
if (sx !== defaultSxProp) {
return (
<>
<Box as="span" {...counterProps} className={clsx(className, classes.CounterLabel)} sx={sx}>
{children}
</Box>
{label}
</>
)
}
return (
<>
<span {...counterProps} className={clsx(className, classes.CounterLabel)}>
{children}
</span>
{label}
</>
)
}

return (
<>
<Box
aria-hidden="true"
className={className}
sx={merge<BetterSystemStyleObject>(
{
display: 'inline-block',
padding: '2px 5px',
fontSize: 0,
fontWeight: 'bold',
lineHeight: 'condensedUltra',
borderRadius: '20px',
backgroundColor: scheme === 'primary' ? 'neutral.emphasis' : 'neutral.muted',
border:
'var(--borderWidth-thin,max(1px, 0.0625rem)) solid var(--counter-borderColor,var(--color-counter-border))',
color: scheme === 'primary' ? 'fg.onEmphasis' : 'fg.default',
'&:empty': {
display: 'none',
},
},
sx,
)}
{...props}
as="span"
ref={forwardedRef}
>
<StyledCounterLabel {...counterProps} className={className} sx={sx}>
{children}
</Box>
<VisuallyHidden>&nbsp;({children})</VisuallyHidden>
</StyledCounterLabel>
{label}
</>
)
},
)

const StyledCounterLabel = styled.span`
display: inline-block;
padding: var(--base-size-2, 0.125rem) var(--base-size-6, 0.375rem);
font-size: 12px;
font-weight: var(--base-text-weight-semibold, bold);
line-height: 1;
border-radius: 20px;
border: var(--borderWidth-thin, max(1px, 0.0625rem)) solid var(--counter-borderColor, var(--color-counter-border));
&[data-scheme='primary'] {
background-color: ${get('colors.neutral.emphasis')};
color: ${get('colors.fg.onEmphasis')};
}
&[data-scheme='secondary'] {
background-color: ${get('colors.neutral.muted')};
color: ${get('colors.fg.default')};
}
&:empty {
display: none;
}
${sx}
`

CounterLabel.displayName = 'CounterLabel'

export default CounterLabel
Loading

0 comments on commit 5426a9a

Please sign in to comment.