Skip to content

Commit

Permalink
chore: Add defaultAs argument to toggleStyledComponent utility (#5149)
Browse files Browse the repository at this point in the history
* Add defaultAs argument to toggleStyledComponent utility

* Fix unknown
  • Loading branch information
jonrohan authored Oct 21, 2024
1 parent 9a30c63 commit 64ad5ea
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/react/src/Banner/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ const StyledBanner = toggleStyledComponent(
* line-height of `20px` so that means that the height of icons should match
* that value.
*/
'div',
styled.div`
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {useFeatureFlag} from '../FeatureFlags'

const StyledButtonGroup = toggleStyledComponent(
'primer_react_css_modules_team',
'div',
styled.div`
display: inline-flex;
vertical-align: middle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,32 @@ import {toggleStyledComponent} from '../toggleStyledComponent'
import styled from 'styled-components'

describe('toggleStyledComponent', () => {
test('renders the component as `defaultAs` when flag is enabled and no `as` prop is provided', () => {
const TestComponent = toggleStyledComponent('testFeatureFlag', 'span', ({as: BaseComponent = 'div'}) => (
<BaseComponent />
))
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: true}}>
<TestComponent />
</FeatureFlags>,
)
expect(container.firstChild).toBeInstanceOf(HTMLSpanElement)
})

test('renders the component as `defaultAs` when flag is disabled and no `as` prop is provided', () => {
const TestComponent = toggleStyledComponent('testFeatureFlag', 'span', ({as: BaseComponent = 'div'}) => (
<BaseComponent />
))
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: false}}>
<TestComponent />
</FeatureFlags>,
)
expect(container.firstChild).toBeInstanceOf(HTMLSpanElement)
})

test('renders the `as` prop when flag is enabled', () => {
const TestComponent = toggleStyledComponent('testFeatureFlag', () => <div />)
const TestComponent = toggleStyledComponent('testFeatureFlag', 'div', () => <div />)
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: true}}>
<TestComponent as="button" />
Expand All @@ -16,7 +40,7 @@ describe('toggleStyledComponent', () => {
})

test('renders a div as fallback when flag is enabled and no `as` prop is provided', () => {
const TestComponent = toggleStyledComponent('testFeatureFlag', () => <div />)
const TestComponent = toggleStyledComponent('testFeatureFlag', 'div', () => <div />)
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: true}}>
<TestComponent />
Expand All @@ -26,7 +50,7 @@ describe('toggleStyledComponent', () => {
})

test('renders Box with `as` if `sx` is provided and flag is enabled', () => {
const TestComponent = toggleStyledComponent('testFeatureFlag', () => styled.div``)
const TestComponent = toggleStyledComponent('testFeatureFlag', 'div', () => styled.div``)
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: true}}>
<TestComponent as="button" sx={{color: 'red'}} />
Expand All @@ -38,7 +62,7 @@ describe('toggleStyledComponent', () => {
})

test('renders styled component when flag is disabled', () => {
const StyledComponent = toggleStyledComponent('testFeatureFlag', styled.div.attrs({['data-styled']: true})``)
const StyledComponent = toggleStyledComponent('testFeatureFlag', 'div', styled.div.attrs({['data-styled']: true})``)
const {container} = render(
<FeatureFlags flags={{testFeatureFlag: false}}>
<StyledComponent />
Expand Down
10 changes: 8 additions & 2 deletions packages/react/src/internal/utils/toggleStyledComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ type CSSModulesProps = {
*
* @param flag - the feature flag that will control whether or not the provided
* styled component is used
* @param defautlAs - the default component to use when `as` is not provided
* @param Component - the styled component that will be used if the feature flag
* is disabled
*/
export function toggleStyledComponent<T, P extends CSSModulesProps>(flag: string, Component: React.ComponentType<P>) {
export function toggleStyledComponent<T, P extends CSSModulesProps>(
flag: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultAs: string | React.ComponentType<any>,
Component: React.ComponentType<P>,
) {
const Wrapper = React.forwardRef<T, P>(function Wrapper(
{as: BaseComponent = 'div', sx: sxProp = defaultSxProp, ...rest},
{as: BaseComponent = defaultAs, sx: sxProp = defaultSxProp, ...rest},
ref,
) {
const enabled = useFeatureFlag(flag)
Expand Down

0 comments on commit 64ad5ea

Please sign in to comment.