diff --git a/.changeset/tidy-clocks-marry.md b/.changeset/tidy-clocks-marry.md new file mode 100644 index 00000000000..1ef03228e3f --- /dev/null +++ b/.changeset/tidy-clocks-marry.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Refactor `Text` to CSS modules behind primer_react_css_modules_team feature flag diff --git a/e2e/components/Text.test.ts b/e2e/components/Text.test.ts index 031a4adf876..3749c6e2139 100644 --- a/e2e/components/Text.test.ts +++ b/e2e/components/Text.test.ts @@ -44,6 +44,25 @@ test.describe('Text', () => { test('default @vrt', async ({page}) => { await visit(page, { id: story.id, + globals: { + featureFlags: { + primer_react_css_modules_team: true, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`Text.${story.title}.png`) + }) + + test('default (styled-system) @vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + featureFlags: { + primer_react_css_modules_team: false, + }, + }, }) // Default state @@ -53,6 +72,23 @@ test.describe('Text', () => { test('axe @aat', async ({page}) => { await visit(page, { id: story.id, + globals: { + featureFlags: { + primer_react_css_modules_team: true, + }, + }, + }) + await expect(page).toHaveNoViolations() + }) + + test('axe (styled-system) @aat', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + featureFlags: { + primer_react_css_modules_team: false, + }, + }, }) await expect(page).toHaveNoViolations() }) diff --git a/packages/react/src/Text/Text.module.css b/packages/react/src/Text/Text.module.css new file mode 100644 index 00000000000..6b7b5552bcc --- /dev/null +++ b/packages/react/src/Text/Text.module.css @@ -0,0 +1,32 @@ +.Text { + &:where([data-size='small']) { + font-size: var(--text-body-size-small); + line-height: var(--text-body-lineHeight-small); + } + + &:where([data-size='medium']) { + font-size: var(--text-body-size-medium); + line-height: var(--text-body-lineHeight-medium); + } + + &:where([data-size='large']) { + font-size: var(--text-body-size-large); + line-height: var(--text-body-lineHeight-large); + } + + &:where([data-weight='light']) { + font-weight: var(--base-text-weight-light); + } + + &:where([data-weight='normal']) { + font-weight: var(--base-text-weight-normal); + } + + &:where([data-weight='medium']) { + font-weight: var(--base-text-weight-medium); + } + + &:where([data-weight='semibold']) { + font-weight: var(--base-text-weight-semibold); + } +} diff --git a/packages/react/src/Text/Text.stories.tsx b/packages/react/src/Text/Text.stories.tsx index 361b30d70b9..5ee7d3514c8 100644 --- a/packages/react/src/Text/Text.stories.tsx +++ b/packages/react/src/Text/Text.stories.tsx @@ -9,19 +9,15 @@ export default { export const Default = () => Default Text -export const Playground: StoryFn = args => {args.text} +export const Playground: StoryFn = args => Playground Playground.args = { - text: 'Playground', as: 'span', size: 'medium', weight: 'normal', } Playground.argTypes = { - text: { - type: 'string', - }, as: { type: 'string', }, @@ -37,12 +33,6 @@ Playground.argTypes = { disable: true, }, }, - forwardedAs: { - controls: false, - table: { - disable: true, - }, - }, size: { control: { type: 'radio', diff --git a/packages/react/src/Text/Text.tsx b/packages/react/src/Text/Text.tsx index d74320cddb8..543cadde3c2 100644 --- a/packages/react/src/Text/Text.tsx +++ b/packages/react/src/Text/Text.tsx @@ -1,9 +1,16 @@ +import cx from 'clsx' import styled from 'styled-components' +import React, {forwardRef} from 'react' import type {SystemCommonProps, SystemTypographyProps} from '../constants' import {COMMON, TYPOGRAPHY} from '../constants' import type {SxProp} from '../sx' import sx from '../sx' +import {useFeatureFlag} from '../FeatureFlags' +import Box from '../Box' +import {useRefObjectAsForwardedRef} from '../hooks' +import classes from './Text.module.css' import type {ComponentProps} from '../utils/types' +import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic' type StyledTextProps = { size?: 'large' | 'medium' | 'small' @@ -12,10 +19,7 @@ type StyledTextProps = { SystemCommonProps & SxProp -const Text = styled.span.attrs(({size, weight}) => ({ - 'data-size': size, - 'data-weight': weight, -}))` +const StyledText = styled.span` ${TYPOGRAPHY}; ${COMMON}; @@ -52,5 +56,57 @@ const Text = styled.span.attrs(({size, weight}) => ({ ${sx}; ` -export type TextProps = ComponentProps + +const Text = forwardRef(({as: Component = 'span', className, size, weight, ...props}, forwardedRef) => { + const enabled = useFeatureFlag('primer_react_css_modules_team') + + const innerRef = React.useRef(null) + useRefObjectAsForwardedRef(forwardedRef, innerRef) + + if (enabled) { + if (props.sx) { + return ( + // @ts-ignore shh + + ) + } + + return ( + // @ts-ignore shh + + ) + } + + return ( + // @ts-ignore shh + + ) +}) as PolymorphicForwardRefComponent<'span', StyledTextProps> + +Text.displayName = 'Text' + +export type TextProps = ComponentProps export default Text