Skip to content

Commit 07b75e7

Browse files
authored
feat(Details): Convert Details to css module behind feature flag (#5167)
* Convert Details component to CSS modules behind team flag * Update snapshot name * Create clean-mails-accept.md * test(vrt): update snapshots * Fixing the type to not allow styled system * Fix for sxProp --------- Co-authored-by: jonrohan <jonrohan@users.noreply.github.com>
1 parent e421f32 commit 07b75e7

23 files changed

+117
-44
lines changed

.changeset/clean-mails-accept.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/react": minor
3+
---
4+
5+
Convert Details to css module behind feature flag

e2e/components/Details.test.ts

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,56 @@ import {test, expect} from '@playwright/test'
22
import {visit} from '../test-helpers/storybook'
33
import {themes} from '../test-helpers/themes'
44

5-
test.describe('Details', () => {
6-
test.describe('Default', () => {
7-
for (const theme of themes) {
8-
test.describe(theme, () => {
9-
test('default @vrt', async ({page}) => {
10-
await visit(page, {
11-
id: 'components-details--default',
12-
globals: {
13-
colorScheme: theme,
14-
},
15-
})
5+
const stories: Array<{title: string; id: string}> = [
6+
{
7+
title: 'Default',
8+
id: 'components-details--default',
9+
},
10+
{
11+
title: 'SX Prop Stress Test',
12+
id: 'components-details-dev--sx-prop-stress-test',
13+
},
14+
]
1615

17-
// Default state - closed
18-
expect(await page.screenshot()).toMatchSnapshot(`Details.Default.${theme}.png`)
19-
// Click the summary to open
20-
await page.getByText('See Details').click()
21-
await page.getByText('This is some content').waitFor()
22-
// Open state
23-
expect(await page.screenshot()).toMatchSnapshot(`Details.Default.${theme}.open.png`)
24-
})
16+
test.describe('Details', () => {
17+
for (const story of stories) {
18+
test.describe(story.title, () => {
19+
for (const theme of themes) {
20+
test.describe(theme, () => {
21+
test('default @vrt', async ({page}) => {
22+
await visit(page, {
23+
id: story.id,
24+
globals: {
25+
colorScheme: theme,
26+
},
27+
})
2528

26-
test('axe @aat', async ({page}) => {
27-
await visit(page, {
28-
id: 'components-details--default',
29-
globals: {
30-
colorScheme: theme,
31-
},
29+
// Default state - closed
30+
expect(await page.screenshot()).toMatchSnapshot(`Details.${story.title}.${theme}.png`)
31+
// Click the summary to open
32+
await page.getByText('See Details').click()
33+
await page.getByText('This is some content').waitFor()
34+
// Open state
35+
expect(await page.screenshot()).toMatchSnapshot(`Details.${story.title}.${theme}.open.png`)
3236
})
33-
await expect(page).toHaveNoViolations({
34-
rules: {
35-
'color-contrast': {
36-
enabled: false,
37+
38+
test('axe @aat', async ({page}) => {
39+
await visit(page, {
40+
id: story.id,
41+
globals: {
42+
colorScheme: theme,
43+
},
44+
})
45+
await expect(page).toHaveNoViolations({
46+
rules: {
47+
'color-contrast': {
48+
enabled: false,
49+
},
3750
},
38-
},
51+
})
3952
})
4053
})
41-
})
42-
}
43-
})
54+
}
55+
})
56+
}
4457
})
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react'
2+
import type {StoryFn, Meta} from '@storybook/react'
3+
import Details from './Details'
4+
import {Button} from '../Button'
5+
import useDetails from '../hooks/useDetails'
6+
7+
export default {
8+
title: 'Components/Details/Dev',
9+
component: Details,
10+
} as Meta<typeof Details>
11+
12+
export const SxPropStressTest: StoryFn<typeof Details> = () => {
13+
const {getDetailsProps} = useDetails({closeOnOutsideClick: true})
14+
return (
15+
<Details
16+
{...getDetailsProps()}
17+
sx={{
18+
backgroundColor: 'accent.emphasis',
19+
color: 'accent.fg',
20+
p: 4,
21+
}}
22+
>
23+
<Button as="summary">See Details</Button>
24+
This is some content
25+
</Details>
26+
)
27+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.Details > summary {
2+
list-style: none;
3+
}
4+
5+
.Details > summary::-webkit-details-marker {
6+
display: none;
7+
}
Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,41 @@
1+
import React, {type ComponentPropsWithoutRef, type ReactElement} from 'react'
12
import styled from 'styled-components'
23
import type {SxProp} from '../sx'
34
import sx from '../sx'
4-
import type {ComponentProps} from '../utils/types'
5+
import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent'
6+
import {useFeatureFlag} from '../FeatureFlags'
7+
import {clsx} from 'clsx'
8+
import classes from './Details.module.css'
59

6-
const Details = styled.details<SxProp>`
7-
& > summary {
8-
list-style: none;
9-
}
10-
& > summary::-webkit-details-marker {
11-
display: none;
12-
}
10+
const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'
1311

14-
${sx};
15-
`
12+
const StyledDetails = toggleStyledComponent(
13+
CSS_MODULES_FEATURE_FLAG,
14+
'details',
15+
styled.details<SxProp>`
16+
& > summary {
17+
list-style: none;
18+
}
19+
& > summary::-webkit-details-marker {
20+
display: none;
21+
}
22+
23+
${sx};
24+
`,
25+
)
26+
27+
const Details = React.forwardRef<HTMLDetailsElement, DetailsProps>(
28+
({className, children, ...rest}, ref): ReactElement => {
29+
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)
30+
return (
31+
<StyledDetails className={clsx(className, {[classes.Details]: enabled})} {...rest} ref={ref}>
32+
{children}
33+
</StyledDetails>
34+
)
35+
},
36+
)
1637

1738
Details.displayName = 'Details'
1839

19-
export type DetailsProps = ComponentProps<typeof Details>
40+
export type DetailsProps = ComponentPropsWithoutRef<'details'> & SxProp
2041
export default Details

0 commit comments

Comments
 (0)