diff --git a/.changeset/grumpy-numbers-eat.md b/.changeset/grumpy-numbers-eat.md new file mode 100644 index 00000000000..5b3a723c7e0 --- /dev/null +++ b/.changeset/grumpy-numbers-eat.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Convert BaseStyles to CSS modules behind team feature flag diff --git a/packages/react/src/BaseStyles.module.css b/packages/react/src/BaseStyles.module.css new file mode 100644 index 00000000000..f1c0e87ec64 --- /dev/null +++ b/packages/react/src/BaseStyles.module.css @@ -0,0 +1,50 @@ +/* stylelint-disable selector-max-specificity */ +/* stylelint-disable selector-type-no-unknown */ + +/* -------------------------------- + * Global Styles + *--------------------------------- */ +* { + box-sizing: border-box; +} + +body { + margin: 0; +} + +table { + /* stylelint-disable-next-line primer/borders */ + border-collapse: collapse; +} + +[role='button']:focus:not(:focus-visible):not(.focus-visible), +[role='tabpanel'][tabindex='0']:focus:not(:focus-visible):not(.focus-visible), +button:focus:not(:focus-visible):not(.focus-visible), +summary:focus:not(:focus-visible):not(.focus-visible), +a:focus:not(:focus-visible):not(.focus-visible) { + outline: none; + box-shadow: none; +} + +[tabindex='0']:focus:not(:focus-visible):not(.focus-visible), +details-dialog:focus:not(:focus-visible):not(.focus-visible) { + outline: none; +} + +/* -------------------------------------------------------------------------- */ + +.BaseStyles { + /* Global styles for light mode */ + &:has([data-color-mode='light']) { + input & { + color-scheme: light; + } + } + + /* Global styles for dark mode */ + &:has([data-color-mode='dark']) { + input & { + color-scheme: dark; + } + } +} diff --git a/packages/react/src/BaseStyles.tsx b/packages/react/src/BaseStyles.tsx index 351c1cb39f2..2a5ffb24347 100644 --- a/packages/react/src/BaseStyles.tsx +++ b/packages/react/src/BaseStyles.tsx @@ -1,13 +1,19 @@ import React from 'react' +import {clsx} from 'clsx' import styled, {createGlobalStyle} from 'styled-components' +import type {ComponentProps} from './utils/types' import type {SystemCommonProps, SystemTypographyProps} from './constants' import {COMMON, TYPOGRAPHY} from './constants' import {useTheme} from './ThemeProvider' -import type {ComponentProps} from './utils/types' +import {useFeatureFlag} from './FeatureFlags' +import {toggleStyledComponent} from './internal/utils/toggleStyledComponent' +import classes from './BaseStyles.module.css' // load polyfill for :focus-visible import 'focus-visible' +const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team' + const GlobalStyle = createGlobalStyle<{colorScheme?: 'light' | 'dark'}>` * { box-sizing: border-box; } body { margin: 0; } @@ -29,27 +35,34 @@ const GlobalStyle = createGlobalStyle<{colorScheme?: 'light' | 'dark'}>` } ` -const Base = styled.div` - ${TYPOGRAPHY}; - ${COMMON}; -` +const Base = toggleStyledComponent( + CSS_MODULES_FEATURE_FLAG, + 'div', + styled.div` + ${TYPOGRAPHY}; + ${COMMON}; + `, +) export type BaseStylesProps = ComponentProps function BaseStyles(props: BaseStylesProps) { - const {children, color = 'fg.default', fontFamily = 'normal', lineHeight = 'default', ...rest} = props + const {children, color = 'fg.default', fontFamily = 'normal', lineHeight = 'default', className, ...rest} = props const {colorScheme, dayScheme, nightScheme} = useTheme() + const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) + + const stylingProps = enabled ? {className: clsx(classes.BaseStyles, className)} : {className} /** * We need to map valid primer/react color modes onto valid color modes for primer/primitives * valid color modes for primer/primitives: auto | light | dark * valid color modes for primer/primer: auto | day | night | light | dark */ - return ( - + {!enabled && } {children} ) diff --git a/packages/react/src/__tests__/BaseStyles.test.tsx b/packages/react/src/__tests__/BaseStyles.test.tsx index e7608955463..8895f46d3d8 100644 --- a/packages/react/src/__tests__/BaseStyles.test.tsx +++ b/packages/react/src/__tests__/BaseStyles.test.tsx @@ -30,4 +30,16 @@ describe('BaseStyles', () => { const {container} = render() expect(container.children[0]).toHaveStyle({color: '#f00', 'font-family': 'Arial', 'line-height': '3.5'}) }) + + it('accepts className and style props', () => { + const styles = { + style: {margin: '10px'}, + className: 'test-classname', + sx: {}, + } + + const {container} = render() + expect(container.children[0]).toHaveClass('test-classname') + expect(container.children[0]).toHaveStyle({margin: '10px'}) + }) })