Skip to content

Commit

Permalink
chore(ButtonGroup): Migrate ButtonGroup component to use CSS modules …
Browse files Browse the repository at this point in the history
…behind the primer_react_css_modules_team feature flag (#5001)

* Convert ButtonGroup to css modules

* Update tests

* Create orange-steaks-do.md

* Disable lint

* Update displayName
  • Loading branch information
jonrohan authored Sep 23, 2024
1 parent c141de1 commit 597d285
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-steaks-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": patch
---

Migrate `ButtonGroup` component to use CSS modules behind the `primer_react_css_modules_team` feature flag
102 changes: 102 additions & 0 deletions e2e/components/ButtonGroup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup--default',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})

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

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

Expand All @@ -23,6 +41,22 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup--default',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})
await expect(page).toHaveNoViolations()
})

test('axe @aat (styled-components)', async ({page}) => {
await visit(page, {
id: 'components-buttongroup--default',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: false,
},
},
})
await expect(page).toHaveNoViolations()
Expand All @@ -39,6 +73,24 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup--playground',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})

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

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

Expand All @@ -51,6 +103,22 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup--playground',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})
await expect(page).toHaveNoViolations()
})

test('axe @aat (styled-components)', async ({page}) => {
await visit(page, {
id: 'components-buttongroup--playground',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: false,
},
},
})
await expect(page).toHaveNoViolations()
Expand All @@ -67,6 +135,24 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup-features--icon-buttons',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})

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

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

Expand All @@ -79,6 +165,22 @@ test.describe('ButtonGroup', () => {
id: 'components-buttongroup-features--icon-buttons',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: true,
},
},
})
await expect(page).toHaveNoViolations()
})

test('axe @aat (styled-components)', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-features--icon-buttons',
globals: {
colorScheme: theme,
featureFlags: {
primer_react_css_modules_team: false,
},
},
})
await expect(page).toHaveNoViolations()
Expand Down
60 changes: 60 additions & 0 deletions packages/react/src/ButtonGroup/ButtonGroup.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.ButtonGroup {
display: inline-flex;
vertical-align: middle;
isolation: isolate;

& > *:not([data-loading-wrapper]) {
/* stylelint-disable-next-line primer/spacing */
margin-inline-end: -1px;
position: relative;
border-radius: 0;

&:first-child {
border-top-left-radius: var(--borderRadius-medium);
border-bottom-left-radius: var(--borderRadius-medium);
}

&:last-child {
border-top-right-radius: var(--borderRadius-medium);
border-bottom-right-radius: var(--borderRadius-medium);
}

&:focus,
&:active,
&:hover {
z-index: 1;
}
}

/* if child is loading button */
[data-loading-wrapper] {
&:first-child {
button,
a {
border-top-left-radius: var(--borderRadius-medium);
border-bottom-left-radius: var(--borderRadius-medium);
}
}

&:last-child {
button,
a {
border-top-right-radius: var(--borderRadius-medium);
border-bottom-right-radius: var(--borderRadius-medium);
}
}
}

[data-loading-wrapper] > * {
/* stylelint-disable-next-line primer/spacing */
margin-inline-end: -1px;
position: relative;
border-radius: 0;

&:focus,
&:active,
&:hover {
z-index: 1;
}
}
}
122 changes: 75 additions & 47 deletions packages/react/src/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,96 @@
import styled from 'styled-components'
import React from 'react'
import {get} from '../constants'
import sx from '../sx'
import type {ComponentProps} from '../utils/types'
import classes from './ButtonGroup.module.css'
import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent'
import {clsx} from 'clsx'
import {useFeatureFlag} from '../FeatureFlags'

const ButtonGroup = styled.div`
display: inline-flex;
vertical-align: middle;
isolation: isolate;
const StyledButtonGroup = toggleStyledComponent(
'primer_react_css_modules_team',
styled.div`
display: inline-flex;
vertical-align: middle;
isolation: isolate;
&& > *:not([data-loading-wrapper]) {
margin-inline-end: -1px;
position: relative;
border-radius: 0;
&& > *:not([data-loading-wrapper]) {
margin-inline-end: -1px;
position: relative;
border-radius: 0;
:first-child {
border-top-left-radius: ${get('radii.2')};
border-bottom-left-radius: ${get('radii.2')};
}
:last-child {
border-top-right-radius: ${get('radii.2')};
border-bottom-right-radius: ${get('radii.2')};
}
:focus,
:active,
:hover {
z-index: 1;
}
}
// if child is loading button
[data-loading-wrapper] {
:first-child {
button,
a {
:first-child {
border-top-left-radius: ${get('radii.2')};
border-bottom-left-radius: ${get('radii.2')};
}
}
:last-child {
button,
a {
:last-child {
border-top-right-radius: ${get('radii.2')};
border-bottom-right-radius: ${get('radii.2')};
}
:focus,
:active,
:hover {
z-index: 1;
}
}
}
[data-loading-wrapper] > * {
margin-inline-end: -1px;
position: relative;
border-radius: 0;
// if child is loading button
[data-loading-wrapper] {
:first-child {
button,
a {
border-top-left-radius: ${get('radii.2')};
border-bottom-left-radius: ${get('radii.2')};
}
}
:last-child {
button,
a {
border-top-right-radius: ${get('radii.2')};
border-bottom-right-radius: ${get('radii.2')};
}
}
}
:focus,
:active,
:hover {
z-index: 1;
[data-loading-wrapper] > * {
margin-inline-end: -1px;
position: relative;
border-radius: 0;
:focus,
:active,
:hover {
z-index: 1;
}
}
}
${sx};
`
${sx};
`,
)

export type ButtonGroupProps = ComponentProps<typeof StyledButtonGroup>
const ButtonGroup = React.forwardRef<HTMLElement, ButtonGroupProps>(function ButtonGroup(
{children, className, ...rest},
forwardRef,
) {
const enabled = useFeatureFlag('primer_react_css_modules_team')
return (
<StyledButtonGroup
ref={forwardRef}
className={clsx(className, {
[classes.ButtonGroup]: enabled,
})}
{...rest}
>
{children}
</StyledButtonGroup>
)
})

ButtonGroup.displayName = 'ButtonGroup'

export type ButtonGroupProps = ComponentProps<typeof ButtonGroup>
export default ButtonGroup

0 comments on commit 597d285

Please sign in to comment.