diff --git a/.changeset/shaggy-comics-whisper.md b/.changeset/shaggy-comics-whisper.md deleted file mode 100644 index a665f985634..00000000000 --- a/.changeset/shaggy-comics-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/react": minor ---- - -Remove CSS modules feature flag from Header diff --git a/packages/react/src/Header/Header.tsx b/packages/react/src/Header/Header.tsx index 0d5c2c6efc8..33c7a6b7b0d 100644 --- a/packages/react/src/Header/Header.tsx +++ b/packages/react/src/Header/Header.tsx @@ -1,81 +1,139 @@ import type {Location, Pathname} from 'history' +import styled, {css} from 'styled-components' +import {get} from '../constants' import type {SxProp} from '../sx' +import sx from '../sx' +import type {ComponentProps} from '../utils/types' +import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {useFeatureFlag} from '../FeatureFlags' import React from 'react' import {clsx} from 'clsx' import classes from './Header.module.css' import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic' -import {defaultSxProp} from '../utils/defaultSxProp' -import Box from '../Box' -export type HeaderProps = React.ComponentProps<'header'> & SxProp & {as?: React.ElementType} -export type HeaderItemProps = React.ComponentProps<'div'> & SxProp & {full?: boolean} -export type HeaderLinkProps = React.ComponentProps<'a'> & SxProp & {to?: Location | Pathname; as?: React.ElementType} +type StyledHeaderProps = React.ComponentProps<'header'> & SxProp +type StyledHeaderItemProps = React.ComponentProps<'div'> & SxProp & {full?: boolean} +type StyledHeaderLinkProps = React.ComponentProps<'a'> & SxProp & {to?: Location | Pathname} -const Header = React.forwardRef(function Header( - {children, className, sx: sxProp = defaultSxProp, as = 'header', ...rest}, +const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_ga' + +const StyledHeader = toggleStyledComponent( + CSS_MODULES_FEATURE_FLAG, + 'header', + styled.header` + z-index: 32; + display: flex; + padding: ${get('space.3')}; + font-size: ${get('fontSizes.1')}; + line-height: ${get('lineHeights.default')}; + color: ${get('colors.header.text')}; + background-color: ${get('colors.header.bg')}; + align-items: center; + flex-wrap: nowrap; + overflow: auto; + + ${sx}; + `, +) + +const Header = React.forwardRef(function Header( + {children, className, ...rest}, forwardRef, ) { - if (sxProp !== defaultSxProp || as !== 'header') { - return ( - - {children} - - ) - } + const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) return ( -
+ {children} -
+ ) -}) as PolymorphicForwardRefComponent<'header', HeaderProps> +}) as PolymorphicForwardRefComponent<'header', StyledHeaderProps> Header.displayName = 'Header' -const HeaderItem = React.forwardRef(function HeaderItem( - {children, className, sx: sxProp = defaultSxProp, full, ...rest}, +const StyledHeaderItem = toggleStyledComponent( + CSS_MODULES_FEATURE_FLAG, + 'div', + styled.div` + display: flex; + margin-right: ${get('space.3')}; + align-self: stretch; + align-items: center; + flex-wrap: nowrap; + + ${({full}) => + full && + css` + flex: auto; + `}; + + ${sx}; + `, +) + +const HeaderItem = React.forwardRef(function HeaderItem( + {children, className, ...rest}, forwardRef, ) { - if (sxProp !== defaultSxProp) { - return ( - - {children} - - ) - } + const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) return ( -
+ {children} -
+ ) }) HeaderItem.displayName = 'Header.Item' -const HeaderLink = React.forwardRef(function HeaderLink( - {children, className, sx: sxProp = defaultSxProp, as = 'a', ...rest}, +const StyledHeaderLink = toggleStyledComponent( + CSS_MODULES_FEATURE_FLAG, + 'a', + styled.a.attrs(({to}) => { + const isReactRouter = typeof to === 'string' + if (isReactRouter) { + // according to their docs, NavLink supports aria-current: + // https://reacttraining.com/react-router/web/api/NavLink/aria-current-string + return {'aria-current': 'page'} + } else { + return {} + } + })` + font-weight: ${get('fontWeights.bold')}; + color: ${get('colors.header.logo')}; + white-space: nowrap; + cursor: pointer; + text-decoration: none; + display: flex; + align-items: center; + + &:hover, + &:focus { + color: ${get('colors.header.text')}; + } + + ${sx}; + `, +) + +const HeaderLink = React.forwardRef(function HeaderLink( + {children, className, ...rest}, forwardRef, ) { - if (sxProp !== defaultSxProp || as !== 'a') { - return ( - - {children} - - ) - } + const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) return ( - + {children} - + ) }) HeaderLink.displayName = 'Header.Link' +export type HeaderProps = ComponentProps +export type HeaderLinkProps = ComponentProps +export type HeaderItemProps = ComponentProps export default Object.assign(Header, {Link: HeaderLink, Item: HeaderItem}) diff --git a/packages/react/src/__tests__/Header.test.tsx b/packages/react/src/__tests__/Header.test.tsx index 02673ed76da..e084cc9e8c6 100644 --- a/packages/react/src/__tests__/Header.test.tsx +++ b/packages/react/src/__tests__/Header.test.tsx @@ -13,7 +13,7 @@ describe('Header', () => { }) describe('Header.Item', () => { - behavesAsComponent({Component: Header.Item, options: {skipAs: true}}) + behavesAsComponent({Component: Header.Item}) it('accepts and applies className', () => { expect(render().props.className).toContain('primer')