Skip to content

Commit 8e481ca

Browse files
authoredDec 17, 2024··
feat(BaseStyles): Fix Typography and Common props when CSS modules feature flag is enabled (#5444)
* Fix Typography and Common props for BaseStyles behind feature flag * Update Text to use util includesSystemProps * Fix whiteSpace prop for BaseStyles * Add changeset * Fix color ts error * Updated color variable in AnchoredOverlay
1 parent f9e193b commit 8e481ca

8 files changed

+152
-48
lines changed
 

‎.changeset/polite-books-sneeze.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/react": patch
3+
---
4+
5+
Fix Typography and Common props for BaseStyles when CSS modules feature flag is enabled
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import {BaseStyles} from '.'
22
import type {Meta} from '@storybook/react'
3-
import React from 'react'
43
import type {ComponentProps} from './utils/types'
54

65
export default {
76
title: 'Behaviors/BaseStyles/Dev',
87
component: BaseStyles,
98
} as Meta<ComponentProps<typeof BaseStyles>>
109

11-
export const Default = () => <BaseStyles>Hello</BaseStyles>
10+
export const Default = () => 'Hello'

‎packages/react/src/BaseStyles.tsx

+89-24
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import React from 'react'
1+
import React, {type CSSProperties, type PropsWithChildren} from 'react'
22
import {clsx} from 'clsx'
33
import styled, {createGlobalStyle} from 'styled-components'
4-
import type {ComponentProps} from './utils/types'
54
import type {SystemCommonProps, SystemTypographyProps} from './constants'
65
import {COMMON, TYPOGRAPHY} from './constants'
76
import {useTheme} from './ThemeProvider'
87
import {useFeatureFlag} from './FeatureFlags'
9-
import {toggleStyledComponent} from './internal/utils/toggleStyledComponent'
8+
import Box from './Box'
9+
import type {SxProp} from './sx'
10+
import {includesSystemProps, getTypographyAndCommonProps} from './utils/includeSystemProps'
11+
1012
import classes from './BaseStyles.module.css'
1113

1214
// load polyfill for :focus-visible
@@ -35,45 +37,108 @@ const GlobalStyle = createGlobalStyle<{colorScheme?: 'light' | 'dark'}>`
3537
}
3638
`
3739

38-
const Base = toggleStyledComponent(
39-
CSS_MODULES_FEATURE_FLAG,
40-
'div',
41-
styled.div<SystemTypographyProps & SystemCommonProps>`
42-
${TYPOGRAPHY};
43-
${COMMON};
44-
`,
45-
)
40+
const StyledDiv = styled.div<SystemTypographyProps & SystemCommonProps>`
41+
${TYPOGRAPHY};
42+
${COMMON};
43+
`
4644

47-
export type BaseStylesProps = ComponentProps<typeof Base>
45+
export type BaseStylesProps = PropsWithChildren & {
46+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
47+
as?: React.ComponentType<any> | keyof JSX.IntrinsicElements
48+
className?: string
49+
style?: CSSProperties
50+
color?: string // Fixes `color` ts-error
51+
} & SystemTypographyProps &
52+
SystemCommonProps &
53+
SxProp
4854

4955
function BaseStyles(props: BaseStylesProps) {
50-
const {children, color = 'fg.default', fontFamily = 'normal', lineHeight = 'default', className, ...rest} = props
56+
const {
57+
children,
58+
color = 'var(--fgColor-default)',
59+
fontFamily = 'normal',
60+
lineHeight = 'default',
61+
className,
62+
as: Component = 'div',
63+
...rest
64+
} = props
5165

5266
const {colorScheme, dayScheme, nightScheme} = useTheme()
5367
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)
5468

55-
const stylingProps = enabled ? {className: clsx(classes.BaseStyles, className)} : {className}
69+
if (enabled) {
70+
const newClassName = clsx(classes.BaseStyles, className)
71+
72+
// If props includes TYPOGRAPHY or COMMON props, pass them to the Box component
73+
if (includesSystemProps(props)) {
74+
const systemProps = getTypographyAndCommonProps(props)
75+
return (
76+
// @ts-ignore shh
77+
<Box
78+
as={Component}
79+
className={newClassName}
80+
color={color}
81+
fontFamily={fontFamily}
82+
lineHeight={lineHeight}
83+
data-portal-root
84+
/**
85+
* We need to map valid primer/react color modes onto valid color modes for primer/primitives
86+
* valid color modes for primer/primitives: auto | light | dark
87+
* valid color modes for primer/primer: auto | day | night | light | dark
88+
*/
89+
data-color-mode={colorScheme?.includes('dark') ? 'dark' : 'light'}
90+
data-light-theme={dayScheme}
91+
data-dark-theme={nightScheme}
92+
style={systemProps}
93+
{...rest}
94+
>
95+
{children}
96+
</Box>
97+
)
98+
}
99+
100+
return (
101+
<Component
102+
className={newClassName}
103+
color={color}
104+
fontFamily={fontFamily}
105+
lineHeight={lineHeight}
106+
data-portal-root
107+
/**
108+
* We need to map valid primer/react color modes onto valid color modes for primer/primitives
109+
* valid color modes for primer/primitives: auto | light | dark
110+
* valid color modes for primer/primer: auto | day | night | light | dark
111+
*/
112+
data-color-mode={colorScheme?.includes('dark') ? 'dark' : 'light'}
113+
data-light-theme={dayScheme}
114+
data-dark-theme={nightScheme}
115+
{...rest}
116+
>
117+
{children}
118+
</Component>
119+
)
120+
}
56121

57-
/**
58-
* We need to map valid primer/react color modes onto valid color modes for primer/primitives
59-
* valid color modes for primer/primitives: auto | light | dark
60-
* valid color modes for primer/primer: auto | day | night | light | dark
61-
*/
62122
return (
63-
<Base
64-
{...rest}
65-
{...stylingProps}
123+
<StyledDiv
124+
className={className}
66125
color={color}
67126
fontFamily={fontFamily}
68127
lineHeight={lineHeight}
69128
data-portal-root
129+
/**
130+
* We need to map valid primer/react color modes onto valid color modes for primer/primitives
131+
* valid color modes for primer/primitives: auto | light | dark
132+
* valid color modes for primer/primer: auto | day | night | light | dark
133+
*/
70134
data-color-mode={colorScheme?.includes('dark') ? 'dark' : 'light'}
71135
data-light-theme={dayScheme}
72136
data-dark-theme={nightScheme}
137+
{...rest}
73138
>
74-
{!enabled && <GlobalStyle colorScheme={colorScheme?.includes('dark') ? 'dark' : 'light'} />}
139+
<GlobalStyle colorScheme={colorScheme?.includes('dark') ? 'dark' : 'light'} />
75140
{children}
76-
</Base>
141+
</StyledDiv>
77142
)
78143
}
79144

‎packages/react/src/Text/Text.tsx

+2-14
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import sx from '../sx'
88
import {useFeatureFlag} from '../FeatureFlags'
99
import Box from '../Box'
1010
import {useRefObjectAsForwardedRef} from '../hooks'
11-
import classes from './Text.module.css'
1211
import type {ComponentProps} from '../utils/types'
12+
import {includesSystemProps} from '../utils/includeSystemProps'
13+
import classes from './Text.module.css'
1314

1415
type StyledTextProps = {
1516
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -58,19 +59,6 @@ const StyledText = styled.span<StyledTextProps>`
5859
${sx};
5960
`
6061

61-
const COMMON_PROP_NAMES = new Set(Object.keys(COMMON))
62-
const TYPOGRAPHY_PROP_NAMES = new Set(Object.keys(TYPOGRAPHY))
63-
64-
const includesSystemProps = (props: StyledTextProps) => {
65-
if (props.sx) {
66-
return true
67-
}
68-
69-
return Object.keys(props).some(prop => {
70-
return TYPOGRAPHY_PROP_NAMES.has(prop) || COMMON_PROP_NAMES.has(prop)
71-
})
72-
}
73-
7462
const Text = forwardRef(({as: Component = 'span', className, size, weight, ...props}, forwardedRef) => {
7563
const enabled = useFeatureFlag('primer_react_css_modules_ga')
7664

‎packages/react/src/__tests__/BaseStyles.test.tsx

+17-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('BaseStyles', () => {
1616
})
1717

1818
it('has default styles', () => {
19-
const {container} = render(<BaseStyles></BaseStyles>)
19+
const {container} = render(<BaseStyles>Hello</BaseStyles>)
2020
expect(container).toMatchSnapshot()
2121
})
2222

@@ -27,18 +27,32 @@ describe('BaseStyles', () => {
2727
lineHeight: '3.5',
2828
}
2929

30-
const {container} = render(<BaseStyles {...styles}></BaseStyles>)
30+
const {container} = render(<BaseStyles {...styles}>Hello</BaseStyles>)
3131
expect(container.children[0]).toHaveStyle({color: '#f00', 'font-family': 'Arial', 'line-height': '3.5'})
3232
})
3333

34+
it('respects system props', () => {
35+
const {container} = render(
36+
<BaseStyles display="contents" whiteSpace="pre-wrap" mr="2">
37+
Hello
38+
</BaseStyles>,
39+
)
40+
41+
expect(container.children[0]).toHaveStyle({
42+
display: 'contents',
43+
'white-space': 'pre-wrap',
44+
'margin-right': '8px',
45+
})
46+
})
47+
3448
it('accepts className and style props', () => {
3549
const styles = {
3650
style: {margin: '10px'},
3751
className: 'test-classname',
3852
sx: {},
3953
}
4054

41-
const {container} = render(<BaseStyles {...styles}></BaseStyles>)
55+
const {container} = render(<BaseStyles {...styles}>Hello</BaseStyles>)
4256
expect(container.children[0]).toHaveClass('test-classname')
4357
expect(container.children[0]).toHaveStyle({margin: '10px'})
4458
})

‎packages/react/src/__tests__/__snapshots__/AnchoredOverlay.test.tsx.snap

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`AnchoredOverlay should render consistently when open 1`] = `
44
.c0 {
55
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
66
line-height: 1.5;
7-
color: var(--fgColor-default,var(--color-fg-default,#1F2328));
7+
color: var(--fgColor-default);
88
}
99
1010
.c1 {
@@ -38,7 +38,7 @@ exports[`AnchoredOverlay should render consistently when open 1`] = `
3838
<div>
3939
<div
4040
class="c0"
41-
color="fg.default"
41+
color="var(--fgColor-default)"
4242
data-color-mode="light"
4343
data-dark-theme="dark"
4444
data-light-theme="light"

‎packages/react/src/__tests__/__snapshots__/BaseStyles.test.tsx.snap

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ exports[`BaseStyles has default styles 1`] = `
44
.c0 {
55
font-family: normal;
66
line-height: default;
7-
color: fg.default;
7+
color: var(--fgColor-default);
88
}
99
1010
<div>
1111
<div
1212
class="c0"
13-
color="fg.default"
13+
color="var(--fgColor-default)"
1414
data-color-mode="light"
1515
data-portal-root="true"
1616
font-family="normal"
17-
/>
17+
>
18+
Hello
19+
</div>
1820
</div>
1921
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {COMMON, TYPOGRAPHY, type SystemCommonProps, type SystemTypographyProps} from '../constants'
2+
import type {SxProp} from '../sx'
3+
4+
const COMMON_PROP_NAMES = new Set(Object.keys(COMMON))
5+
const TYPOGRAPHY_PROP_NAMES = new Set(Object.keys(TYPOGRAPHY))
6+
7+
const includesSystemProps = (props: SxProp) => {
8+
if (props.sx) {
9+
return true
10+
}
11+
12+
return Object.keys(props).some(prop => {
13+
return TYPOGRAPHY_PROP_NAMES.has(prop) || COMMON_PROP_NAMES.has(prop)
14+
})
15+
}
16+
17+
type TypographyAndCommonProp = SystemTypographyProps & SystemCommonProps
18+
19+
const getTypographyAndCommonProps = (props: TypographyAndCommonProp): TypographyAndCommonProp => {
20+
let typographyAndCommonProps = {} as TypographyAndCommonProp
21+
for (const prop of Object.keys(props)) {
22+
if (TYPOGRAPHY_PROP_NAMES.has(prop) || COMMON_PROP_NAMES.has(prop)) {
23+
const p = prop as keyof TypographyAndCommonProp
24+
typographyAndCommonProps = {...typographyAndCommonProps, [p]: props[p]}
25+
}
26+
}
27+
28+
return typographyAndCommonProps
29+
}
30+
31+
export {includesSystemProps, getTypographyAndCommonProps}

0 commit comments

Comments
 (0)
Please sign in to comment.