From 27a21a33c6d73c674fa19c524c8914408da2fd39 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 11:38:20 -0500 Subject: [PATCH 1/8] docs(styled-react): update architecture for polymorphic components --- packages/styled-react/ARCHITECTURE.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/styled-react/ARCHITECTURE.md b/packages/styled-react/ARCHITECTURE.md index a5ea328aaf8..c799e09ba31 100644 --- a/packages/styled-react/ARCHITECTURE.md +++ b/packages/styled-react/ARCHITECTURE.md @@ -61,17 +61,19 @@ import { type ExampleComponentProps as PrimerExampleComponentProps, } from '@primer/react' import {forwardRef} from 'react' -import {PolymorphicForwardRef as ForwardRefComponent} from '../polymorphic' +import {ForwardRefComponent} from '../polymorphic' +import {sx} from '../sx' type ExampleComponentProps = PrimerExampleComponentProps & SxProp -const ExampleComponent = forwardRef(function ExampleComponent(props, ref) { - // @ts-expect-error the polymorphic component type is not inferred - // correctly - return -}) as ForwardRefComponent<'div', ExampleComponentProps> +const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(ExampleComponent).withConfig({ + shouldForwardProp: prop => prop !== 'sx', +})` + ${sx} +` export {ExampleComponent} +export type {ExampleComponentProps} ``` ## Sub-components From b527e7ca1b3ee73ebfedad153f77eada0a8e8e0f Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 11:41:07 -0500 Subject: [PATCH 2/8] docs: update example --- packages/styled-react/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/styled-react/ARCHITECTURE.md b/packages/styled-react/ARCHITECTURE.md index c799e09ba31..1672aed3e99 100644 --- a/packages/styled-react/ARCHITECTURE.md +++ b/packages/styled-react/ARCHITECTURE.md @@ -66,7 +66,7 @@ import {sx} from '../sx' type ExampleComponentProps = PrimerExampleComponentProps & SxProp -const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(ExampleComponent).withConfig({ +const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(PrimerExampleComponent).withConfig({ shouldForwardProp: prop => prop !== 'sx', })` ${sx} From 1197412b730b2b5dcb05316e7926c9e1f0765002 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 12:11:18 -0500 Subject: [PATCH 3/8] Add generic to withConfig so that shouldForwardProp is typed --- packages/styled-react/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/styled-react/ARCHITECTURE.md b/packages/styled-react/ARCHITECTURE.md index 1672aed3e99..561215e0869 100644 --- a/packages/styled-react/ARCHITECTURE.md +++ b/packages/styled-react/ARCHITECTURE.md @@ -66,7 +66,7 @@ import {sx} from '../sx' type ExampleComponentProps = PrimerExampleComponentProps & SxProp -const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(PrimerExampleComponent).withConfig({ +const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(PrimerExampleComponent).withConfig({ shouldForwardProp: prop => prop !== 'sx', })` ${sx} From 638013013c2e98730651200ade23dcd7971dc029 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 12:21:32 -0500 Subject: [PATCH 4/8] chore: format files --- packages/styled-react/ARCHITECTURE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/styled-react/ARCHITECTURE.md b/packages/styled-react/ARCHITECTURE.md index 561215e0869..04c93e99974 100644 --- a/packages/styled-react/ARCHITECTURE.md +++ b/packages/styled-react/ARCHITECTURE.md @@ -66,7 +66,9 @@ import {sx} from '../sx' type ExampleComponentProps = PrimerExampleComponentProps & SxProp -const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled(PrimerExampleComponent).withConfig({ +const ExampleComponent: ForwardRefComponent<'div', ExampleComponentProps> = styled( + PrimerExampleComponent, +).withConfig({ shouldForwardProp: prop => prop !== 'sx', })` ${sx} From 59424de46ad1c292c78642f577bd8d9c79a89375 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 12:49:07 -0500 Subject: [PATCH 5/8] feat(PageHeader): remove support for sx --- .changeset/wet-mammals-feel.md | 5 + package-lock.json | 1 + .../src/PageHeader/PageHeader.dev.stories.tsx | 50 ------ .../react/src/PageHeader/PageHeader.docs.json | 78 +-------- packages/react/src/PageHeader/PageHeader.tsx | 148 +++++------------- packages/react/src/index.ts | 6 +- packages/styled-react/package.json | 1 + packages/styled-react/rollup.config.js | 3 +- packages/styled-react/src/components/Box.tsx | 1 + .../src/components/PageHeader.tsx | 41 +++++ packages/styled-react/src/experimental.tsx | 8 +- packages/styled-react/src/index.tsx | 7 +- packages/styled-react/src/sx.ts | 1 + 13 files changed, 115 insertions(+), 235 deletions(-) create mode 100644 .changeset/wet-mammals-feel.md create mode 100644 packages/styled-react/src/components/Box.tsx create mode 100644 packages/styled-react/src/components/PageHeader.tsx create mode 100644 packages/styled-react/src/sx.ts diff --git a/.changeset/wet-mammals-feel.md b/.changeset/wet-mammals-feel.md new file mode 100644 index 00000000000..35fe4ef4ebd --- /dev/null +++ b/.changeset/wet-mammals-feel.md @@ -0,0 +1,5 @@ +--- +'@primer/react': major +--- + +Remove support for `sx` from `PageHeader` diff --git a/package-lock.json b/package-lock.json index 7b949b95ae7..9cc83269aba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26422,6 +26422,7 @@ "@types/react": "18.3.11", "@types/react-dom": "18.3.1", "@vitejs/plugin-react": "^4.3.3", + "babel-plugin-styled-components": "2.1.4", "publint": "^0.3.12", "react": "18.3.1", "react-dom": "18.3.1", diff --git a/packages/react/src/PageHeader/PageHeader.dev.stories.tsx b/packages/react/src/PageHeader/PageHeader.dev.stories.tsx index 66fc9fdd471..ed30893f569 100644 --- a/packages/react/src/PageHeader/PageHeader.dev.stories.tsx +++ b/packages/react/src/PageHeader/PageHeader.dev.stories.tsx @@ -47,53 +47,3 @@ export const LargeVariantWithMultilineTitle = () => ( ) - -export const ArrayTypeFontSizeOnTitle = () => ( -
- - - - Issue Title - - - -
-) - -export const ThemeBaseFontSizeOnTitle = () => ( -
- - - - Issue Title - - - -
-) - -export const StringTypeFontSizeOnTitle = () => ( -
- - - - Issue Title - - - -
-) diff --git a/packages/react/src/PageHeader/PageHeader.docs.json b/packages/react/src/PageHeader/PageHeader.docs.json index 4ead3c802ed..448c021ce18 100644 --- a/packages/react/src/PageHeader/PageHeader.docs.json +++ b/packages/react/src/PageHeader/PageHeader.docs.json @@ -69,11 +69,6 @@ "type": "AriaRole", "description": "The ARIA role to assign to the top-level node of this component." }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true - }, { "name": "as", "type": "React.ElementType", @@ -100,11 +95,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -134,11 +124,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "`{ narrow: false regular: true wide: true }`", "description": "Whether the parent link is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -156,11 +141,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -178,11 +158,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -206,11 +181,6 @@ "type": "| 'subtitle' | 'medium' | 'large' | { narrow?: | 'subtitle' | 'medium' | 'large' regular?: | 'subtitle' | 'medium' | 'large' wide?: | 'subtitle' | 'medium' | 'large' }", "defaultValue": "medium", "description": "Default title (medium) is the most common page title size. Use for static titles in most situations.\nLarge variant should be used for user-generated content such as issues, pull requests, or discussions.\nSubtitle variant can be used when a PageHeader.Title is already present in the page, such as in a SplitPageLayout." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -228,11 +198,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -250,11 +215,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -273,11 +233,6 @@ "defaultValue": "false", "description": "Whether the content is hidden." }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true - }, { "name": "as", "type": "React.ElementType", @@ -299,11 +254,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -321,11 +271,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -343,11 +288,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -365,11 +305,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -387,11 +322,6 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -425,13 +355,9 @@ "type": "| boolean | { narrow?: boolean regular?: boolean wide?: boolean }", "defaultValue": "false", "description": "Whether the content is hidden." - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] } ] -} \ No newline at end of file +} + diff --git a/packages/react/src/PageHeader/PageHeader.tsx b/packages/react/src/PageHeader/PageHeader.tsx index f78a6890b12..92f811140c7 100644 --- a/packages/react/src/PageHeader/PageHeader.tsx +++ b/packages/react/src/PageHeader/PageHeader.tsx @@ -1,7 +1,7 @@ import React, {useEffect} from 'react' import type {ResponsiveValue} from '../hooks/useResponsiveValue' import {isResponsiveValue, useResponsiveValue} from '../hooks/useResponsiveValue' -import type {SxProp, CSSCustomProperties} from '../sx' +import type {CSSCustomProperties} from '../sx' import Heading from '../Heading' import {ArrowLeftIcon} from '@primer/octicons-react' import type {LinkProps as BaseLinkProps} from '../Link' @@ -15,14 +15,12 @@ import type {AriaRole} from '../utils/types' import {clsx} from 'clsx' import classes from './PageHeader.module.css' -import {defaultSxProp} from '../utils/defaultSxProp' -import {BoxWithFallback} from '../internal/components/BoxWithFallback' // Types that are shared between PageHeader children components export type ChildrenPropTypes = { className?: string hidden?: boolean | ResponsiveValue -} & SxProp +} // Default state for the `visible` prop when a sub component is only visible on narrow viewport const hiddenOnRegularAndWide = { @@ -46,10 +44,10 @@ export type PageHeaderProps = { className?: string role?: AriaRole hasBorder?: boolean -} & SxProp +} const Root = React.forwardRef>( - ({children, className, sx = defaultSxProp, as = 'div', 'aria-label': ariaLabel, role, hasBorder}, forwardedRef) => { + ({children, className, as: BaseComponent = 'div', 'aria-label': ariaLabel, role, hasBorder}, forwardedRef) => { const rootRef = useProvidedRefOrCreate(forwardedRef as React.RefObject) const isInteractive = (element: HTMLElement) => { @@ -105,17 +103,15 @@ const Root = React.forwardRef {children} - + ) }, ) as PolymorphicForwardRefComponent<'div', PageHeaderProps> @@ -128,12 +124,11 @@ const ContextArea: React.FC> = ({ children, className, hidden = hiddenOnRegularAndWide, - sx: sxProp = defaultSxProp, }) => { return ( - +
{children} - +
) } type LinkProps = Pick< @@ -146,18 +141,7 @@ export type ParentLinkProps = React.PropsWithChildren( - ( - { - children, - className, - sx: sxProp = defaultSxProp, - href, - 'aria-label': ariaLabel, - as = 'a', - hidden = hiddenOnRegularAndWide, - }, - ref, - ) => { + ({children, className, href, 'aria-label': ariaLabel, as = 'a', hidden = hiddenOnRegularAndWide}, ref) => { return ( <> ( aria-label={ariaLabel} muted className={clsx(classes.ParentLink, className)} - sx={sxProp} {...getHiddenDataAttributes(hidden)} href={href} > @@ -186,13 +169,12 @@ ParentLink.displayName = 'ParentLink' const ContextBar: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = hiddenOnRegularAndWide, }) => { return ( - +
{children} - +
) } @@ -201,18 +183,12 @@ const ContextBar: React.FC> = ({ const ContextAreaActions: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = hiddenOnRegularAndWide, }) => { return ( - +
{children} - +
) } @@ -224,20 +200,19 @@ type TitleAreaProps = { // --------------------------------------------------------------------- const TitleArea = React.forwardRef>( - ({children, className, sx: sxProp = defaultSxProp, hidden = false, variant = 'medium'}, forwardedRef) => { + ({children, className, hidden = false, variant = 'medium'}, forwardedRef) => { const titleAreaRef = useProvidedRefOrCreate(forwardedRef as React.RefObject) const currentVariant = useResponsiveValue(variant, 'medium') return ( - {children} - + ) }, ) as PolymorphicForwardRefComponent<'div', TitleAreaProps> @@ -248,7 +223,6 @@ TitleArea.displayName = 'TitleArea' const LeadingAction: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = hiddenOnNarrow, }) => { const style: CSSCustomProperties = {} @@ -256,58 +230,45 @@ const LeadingAction: React.FC> = ({ const {height} = sxProp if (height) style['--custom-height'] = height return ( - {children} - + ) } // This is reserved for only breadcrumbs. -const Breadcrumbs: React.FC> = ({ - children, - className, - sx: sxProp = defaultSxProp, - hidden = false, -}) => { +const Breadcrumbs: React.FC> = ({children, className, hidden = false}) => { return ( - {children} - + ) } // PageHeader.LeadingVisual and PageHeader.TrailingVisual should remain visible on narrow viewports. -const LeadingVisual: React.FC> = ({ - children, - className, - sx: sxProp = defaultSxProp, - hidden = false, -}) => { +const LeadingVisual: React.FC> = ({children, className, hidden = false}) => { const style: CSSCustomProperties = {} // @ts-ignore sx has height attribute const {height} = sxProp if (height) style['--custom-height'] = height return ( - {children} - + ) } @@ -315,13 +276,7 @@ export type TitleProps = { as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' } & ChildrenPropTypes -const Title: React.FC> = ({ - children, - className, - sx: sxProp = defaultSxProp, - hidden = false, - as = 'h2', -}) => { +const Title: React.FC> = ({children, className, hidden = false, as = 'h2'}) => { const style: CSSCustomProperties = {} // @ts-ignore sxProp can have color attribute const {fontSize, lineHeight, fontWeight} = sxProp @@ -336,7 +291,6 @@ const Title: React.FC> = ({ data-hidden={hidden} as={as} style={style} - sx={sxProp} {...getHiddenDataAttributes(hidden)} > {children} @@ -348,7 +302,6 @@ const Title: React.FC> = ({ const TrailingVisual: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = false, }) => { const style: CSSCustomProperties = {} @@ -356,22 +309,20 @@ const TrailingVisual: React.FC> = ({ const {height} = sxProp if (height) style['--custom-height'] = height return ( - {children} - + ) } const TrailingAction: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = hiddenOnNarrow, }) => { const style: CSSCustomProperties = {} @@ -379,52 +330,42 @@ const TrailingAction: React.FC> = ({ const {height} = sxProp if (height) style['--custom-height'] = height return ( - {children} - + ) } -const Actions: React.FC> = ({ - children, - className, - sx: sxProp = defaultSxProp, - hidden = false, -}) => { +export type ActionsProps = React.PropsWithChildren + +const Actions = ({children, className, hidden = false}: ActionsProps) => { const style: CSSCustomProperties = {} // @ts-ignore sx has height attribute const {height} = sxProp if (height) style['--custom-height'] = height return ( - {children} - + ) } // PageHeader.Description: The description area of the header. Visible on all viewports -const Description: React.FC> = ({ - children, - className, - sx: sxProp = defaultSxProp, - hidden = false, -}) => { +const Description: React.FC> = ({children, className, hidden = false}) => { return ( - +
{children} - +
) } @@ -438,30 +379,27 @@ export type NavigationProps = { const Navigation: React.FC> = ({ children, className, - sx: sxProp = defaultSxProp, hidden = false, - as, + as: BaseComponent = 'div', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, }) => { warning( - as === 'nav' && !ariaLabel && !ariaLabelledBy, + BaseComponent === 'nav' && !ariaLabel && !ariaLabelledBy, 'Use `aria-label` or `aria-labelledby` prop to provide an accessible label to the `nav` landmark for assistive technology', ) return ( - {children} - + ) } diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 9578768eee8..932a9a23c0c 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -208,7 +208,11 @@ export {Stack} from './Stack' export type {StackProps, StackItemProps} from './Stack' export {PageHeader} from './PageHeader' -export type {PageHeaderProps} from './PageHeader' +export type { + PageHeaderProps, + TitleProps as PageHeaderTitleProps, + ActionsProps as PageHeaderActionsProps, +} from './PageHeader' export {default as sx, merge} from './sx' export type {BetterCssProperties, BetterSystemStyleObject, SxProp} from './sx' diff --git a/packages/styled-react/package.json b/packages/styled-react/package.json index 32e6ced69f7..a5508677aa4 100644 --- a/packages/styled-react/package.json +++ b/packages/styled-react/package.json @@ -34,6 +34,7 @@ "@types/react": "18.3.11", "@types/react-dom": "18.3.1", "@vitejs/plugin-react": "^4.3.3", + "babel-plugin-styled-components": "2.1.4", "publint": "^0.3.12", "react": "18.3.1", "react-dom": "18.3.1", diff --git a/packages/styled-react/rollup.config.js b/packages/styled-react/rollup.config.js index 3d8bd571154..8aae93d5045 100644 --- a/packages/styled-react/rollup.config.js +++ b/packages/styled-react/rollup.config.js @@ -21,7 +21,8 @@ export default defineConfig({ tsconfig: 'tsconfig.build.json', }), babel({ - presets: ['@babel/preset-typescript', '@babel/preset-react'], + presets: ['@babel/preset-typescript', ['@babel/preset-react', {runtime: 'automatic'}]], + plugins: ['babel-plugin-styled-components'], extensions: ['.ts', '.tsx'], babelHelpers: 'bundled', }), diff --git a/packages/styled-react/src/components/Box.tsx b/packages/styled-react/src/components/Box.tsx new file mode 100644 index 00000000000..3694e3b630c --- /dev/null +++ b/packages/styled-react/src/components/Box.tsx @@ -0,0 +1 @@ +export {Box, type BoxProps} from '@primer/react' diff --git a/packages/styled-react/src/components/PageHeader.tsx b/packages/styled-react/src/components/PageHeader.tsx new file mode 100644 index 00000000000..271d2281481 --- /dev/null +++ b/packages/styled-react/src/components/PageHeader.tsx @@ -0,0 +1,41 @@ +import { + PageHeader as PrimerPageHeader, + type PageHeaderProps as PrimerPageHeaderProps, + type PageHeaderTitleProps as PrimerPageHeaderTitleProps, + type PageHeaderActionsProps as PrimerPageHeaderActionsProps, +} from '@primer/react' +import styled from 'styled-components' +import {sx, type SxProp} from '../sx' +import type {ForwardRefComponent} from '../polymorphic' +import {Box} from './Box' + +type PageHeaderProps = PrimerPageHeaderProps & SxProp + +const PageHeaderImpl: ForwardRefComponent<'div', PageHeaderProps> = styled( + PrimerPageHeader, +).withConfig({ + shouldForwardProp: prop => prop !== 'sx', +})` + ${sx} +` + +type PageHeaderActionsProps = PrimerPageHeaderActionsProps & SxProp + +function PageHeaderActions(props: PageHeaderActionsProps) { + return +} + +type PageHeaderTitleProps = PrimerPageHeaderTitleProps & SxProp + +function PageHeaderTitle(props: PageHeaderTitleProps) { + // @ts-expect-error type mismatch between Box usage here and PrimerPageHeader.Title + return +} + +const PageHeader = Object.assign(PageHeaderImpl, { + Actions: PageHeaderActions, + Title: PageHeaderTitle, +}) + +export {PageHeader} +export type {PageHeaderProps, PageHeaderActionsProps, PageHeaderTitleProps} diff --git a/packages/styled-react/src/experimental.tsx b/packages/styled-react/src/experimental.tsx index 5ed22b2d9c1..7b1764bbcb9 100644 --- a/packages/styled-react/src/experimental.tsx +++ b/packages/styled-react/src/experimental.tsx @@ -1 +1,7 @@ -export {Dialog, PageHeader, Table, Tooltip, UnderlinePanels} from '@primer/react/experimental' +export { + PageHeader, + type PageHeaderProps, + type PageHeaderActionsProps, + type PageHeaderTitleProps, +} from './components/PageHeader' +export {Dialog, Table, Tooltip, UnderlinePanels} from '@primer/react/experimental' diff --git a/packages/styled-react/src/index.tsx b/packages/styled-react/src/index.tsx index 66763c5389a..dbd38a581fd 100644 --- a/packages/styled-react/src/index.tsx +++ b/packages/styled-react/src/index.tsx @@ -90,6 +90,12 @@ const ToggleSwitch = forwardRef(function T return }) +export { + PageHeader, + type PageHeaderProps, + type PageHeaderActionsProps, + type PageHeaderTitleProps, +} from './components/PageHeader' export {SegmentedControl, StateLabel, SubNav, ToggleSwitch} export { @@ -115,7 +121,6 @@ export { LinkButton, NavList, Overlay, - PageHeader, PageLayout, ProgressBar, RadioGroup, diff --git a/packages/styled-react/src/sx.ts b/packages/styled-react/src/sx.ts new file mode 100644 index 00000000000..e706676100f --- /dev/null +++ b/packages/styled-react/src/sx.ts @@ -0,0 +1 @@ +export {sx, type SxProp} from '@primer/react' From d3d5d7c345d0775a35793d3cf39e9362c82eddeb Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 14:26:20 -0500 Subject: [PATCH 6/8] refactor: update sx usage with style --- packages/react/src/PageHeader/PageHeader.tsx | 39 +------------------ .../__snapshots__/exports.test.ts.snap | 8 ++-- packages/react/src/experimental/index.ts | 7 +++- .../src/components/PageHeader.tsx | 39 +++++++++++++++++-- .../styled-react/vitest.config.browser.ts | 17 ++++++++ 5 files changed, 63 insertions(+), 47 deletions(-) diff --git a/packages/react/src/PageHeader/PageHeader.tsx b/packages/react/src/PageHeader/PageHeader.tsx index 92f811140c7..ff3e1178df4 100644 --- a/packages/react/src/PageHeader/PageHeader.tsx +++ b/packages/react/src/PageHeader/PageHeader.tsx @@ -225,15 +225,10 @@ const LeadingAction: React.FC> = ({ className, hidden = hiddenOnNarrow, }) => { - const style: CSSCustomProperties = {} - // @ts-ignore sx has height attribute - const {height} = sxProp - if (height) style['--custom-height'] = height return (
{children} @@ -256,15 +251,10 @@ const Breadcrumbs: React.FC> = ({chil // PageHeader.LeadingVisual and PageHeader.TrailingVisual should remain visible on narrow viewports. const LeadingVisual: React.FC> = ({children, className, hidden = false}) => { - const style: CSSCustomProperties = {} - // @ts-ignore sx has height attribute - const {height} = sxProp - if (height) style['--custom-height'] = height return (
{children} @@ -277,20 +267,12 @@ export type TitleProps = { } & ChildrenPropTypes const Title: React.FC> = ({children, className, hidden = false, as = 'h2'}) => { - const style: CSSCustomProperties = {} - // @ts-ignore sxProp can have color attribute - const {fontSize, lineHeight, fontWeight} = sxProp - if (fontSize) style['--custom-font-size'] = fontSize - if (lineHeight) style['--custom-line-height'] = lineHeight - if (fontWeight) style['--custom-font-weight'] = fontWeight - return ( {children} @@ -304,15 +286,10 @@ const TrailingVisual: React.FC> = ({ className, hidden = false, }) => { - const style: CSSCustomProperties = {} - // @ts-ignore sx has height attribute - const {height} = sxProp - if (height) style['--custom-height'] = height return (
{children} @@ -325,15 +302,10 @@ const TrailingAction: React.FC> = ({ className, hidden = hiddenOnNarrow, }) => { - const style: CSSCustomProperties = {} - // @ts-ignore sx has height attribute - const {height} = sxProp - if (height) style['--custom-height'] = height return (
{children} @@ -344,17 +316,8 @@ const TrailingAction: React.FC> = ({ export type ActionsProps = React.PropsWithChildren const Actions = ({children, className, hidden = false}: ActionsProps) => { - const style: CSSCustomProperties = {} - // @ts-ignore sx has height attribute - const {height} = sxProp - if (height) style['--custom-height'] = height return ( -
+
{children}
) diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index d34f9dce59c..d529158da09 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -103,7 +103,9 @@ exports[`@primer/react > should not update exports without a semver change 1`] = "Overlay", "type OverlayProps", "PageHeader", + "type PageHeaderActionsProps", "type PageHeaderProps", + "type PageHeaderTitleProps", "PageLayout", "type PageLayoutContentProps", "type PageLayoutFooterProps", @@ -272,7 +274,6 @@ exports[`@primer/react/experimental > should not update exports without a semver "ButtonBase", "type ButtonBaseProps", "type CellAlignment", - "type ChildrenPropTypes", "type Column", "type ColumnWidth", "createColumnHelper", @@ -300,7 +301,6 @@ exports[`@primer/react/experimental > should not update exports without a semver "type IssueLabelProps", "KeybindingHint", "type KeybindingHintProps", - "type NavigationProps", "NavList", "type NavListDividerProps", "type NavListGroupProps", @@ -311,8 +311,9 @@ exports[`@primer/react/experimental > should not update exports without a semver "type NavListTrailingVisualProps", "type ObjectPaths", "PageHeader", + "type PageHeaderActionsProps", "type PageHeaderProps", - "type ParentLinkProps", + "type PageHeaderTitleProps", "ScrollableRegion", "type ScrollableRegionProps", "SelectPanel", @@ -340,7 +341,6 @@ exports[`@primer/react/experimental > should not update exports without a semver "type TableRowProps", "type TableSubtitleProps", "type TableTitleProps", - "type TitleProps", "Tooltip", "type TooltipProps", "UnderlinePanels", diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index eac14c85f6e..f514177728e 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -42,7 +42,12 @@ export * from '../Dialog/Dialog' export {InlineMessage} from '../InlineMessage' export type {InlineMessageProps} from '../InlineMessage' -export * from '../PageHeader' +export {PageHeader} from '../PageHeader' +export type { + PageHeaderProps, + TitleProps as PageHeaderTitleProps, + ActionsProps as PageHeaderActionsProps, +} from '../PageHeader' export * from '../Hidden' diff --git a/packages/styled-react/src/components/PageHeader.tsx b/packages/styled-react/src/components/PageHeader.tsx index 271d2281481..739c677c3e1 100644 --- a/packages/styled-react/src/components/PageHeader.tsx +++ b/packages/styled-react/src/components/PageHeader.tsx @@ -21,15 +21,46 @@ const PageHeaderImpl: ForwardRefComponent<'div', PageHeaderProps> = styled( type PageHeaderActionsProps = PrimerPageHeaderActionsProps & SxProp -function PageHeaderActions(props: PageHeaderActionsProps) { - return +function PageHeaderActions({sx, ...rest}: PageHeaderActionsProps) { + const style: CSSCustomProperties = {} + if (sx) { + // @ts-ignore sx has height attribute + const {height} = sx + if (height) { + style['--custom-height'] = height + } + } + + // @ts-expect-error type mismatch between Box usage here and PrimerPageHeader.Actions + return } type PageHeaderTitleProps = PrimerPageHeaderTitleProps & SxProp -function PageHeaderTitle(props: PageHeaderTitleProps) { +type CSSCustomProperties = { + [key: `--${string}`]: string | number +} + +function PageHeaderTitle({sx, ...rest}: PageHeaderTitleProps) { + const style: CSSCustomProperties = {} + if (sx) { + // @ts-ignore sx can have color attribute + const {fontSize, lineHeight, fontWeight} = sx + if (fontSize) { + style['--custom-font-size'] = fontSize + } + + if (lineHeight) { + style['--custom-line-height'] = lineHeight + } + + if (fontWeight) { + style['--custom-font-weight'] = fontWeight + } + } + // @ts-expect-error type mismatch between Box usage here and PrimerPageHeader.Title - return + return } const PageHeader = Object.assign(PageHeaderImpl, { diff --git a/packages/styled-react/vitest.config.browser.ts b/packages/styled-react/vitest.config.browser.ts index 00b25150af3..dd9772c045c 100644 --- a/packages/styled-react/vitest.config.browser.ts +++ b/packages/styled-react/vitest.config.browser.ts @@ -1,3 +1,4 @@ +import path from 'node:path' import react from '@vitejs/plugin-react' import {defineConfig} from 'vitest/config' @@ -6,6 +7,22 @@ export default defineConfig({ define: { __DEV__: true, }, + resolve: { + alias: [ + { + find: '@primer/react/experimental', + replacement: path.resolve(import.meta.dirname, '..', 'react', 'src', 'experimental', 'index.ts'), + }, + { + find: '@primer/react/deprecated', + replacement: path.resolve(import.meta.dirname, '..', 'react', 'src', 'deprecated', 'index.ts'), + }, + { + find: '@primer/react', + replacement: path.resolve(import.meta.dirname, '..', 'react', 'src', 'index.ts'), + }, + ], + }, test: { name: '@primer/styled-react (browser)', include: ['src/**/*.browser.test.?(c|m)[jt]s?(x)'], From ec854482b192db92d4bb3986d2f751a787c54d64 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 14:28:11 -0500 Subject: [PATCH 7/8] chore: remove unused export --- packages/react/src/PageHeader/PageHeader.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react/src/PageHeader/PageHeader.tsx b/packages/react/src/PageHeader/PageHeader.tsx index ff3e1178df4..8fff2517360 100644 --- a/packages/react/src/PageHeader/PageHeader.tsx +++ b/packages/react/src/PageHeader/PageHeader.tsx @@ -1,7 +1,6 @@ import React, {useEffect} from 'react' import type {ResponsiveValue} from '../hooks/useResponsiveValue' import {isResponsiveValue, useResponsiveValue} from '../hooks/useResponsiveValue' -import type {CSSCustomProperties} from '../sx' import Heading from '../Heading' import {ArrowLeftIcon} from '@primer/octicons-react' import type {LinkProps as BaseLinkProps} from '../Link' From 4f45cf4ff51e6cbf668ee919f4f0f27ae4ce5952 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Sep 2025 16:26:15 -0500 Subject: [PATCH 8/8] chore: add back in TitleProps --- packages/react/src/__tests__/__snapshots__/exports.test.ts.snap | 1 + packages/react/src/experimental/index.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index d529158da09..0469c021a26 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -341,6 +341,7 @@ exports[`@primer/react/experimental > should not update exports without a semver "type TableRowProps", "type TableSubtitleProps", "type TableTitleProps", + "type TitleProps", "Tooltip", "type TooltipProps", "UnderlinePanels", diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index f514177728e..44bd0c7f8d5 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -45,6 +45,7 @@ export type {InlineMessageProps} from '../InlineMessage' export {PageHeader} from '../PageHeader' export type { PageHeaderProps, + TitleProps, TitleProps as PageHeaderTitleProps, ActionsProps as PageHeaderActionsProps, } from '../PageHeader'