Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
d95b2f9
rm Box and sx prop from components, add to styled-react
mperrotti Sep 10, 2025
778eca1
fixes NavList/ActionList type errors surfaced when creating wrappers …
mperrotti Sep 10, 2025
dac0887
adds PageHeader to styled-react and replaces its legacy polymorphic t…
mperrotti Sep 10, 2025
ea20922
fix type errors in styled-react UnderlineNav/UnderlineNav.Item
mperrotti Sep 10, 2025
3645c19
adds changeset
mperrotti Sep 10, 2025
58b207b
fix typescript issues in styled-react component ports
mperrotti Sep 11, 2025
73803e7
Merge branch 'main' into mp/rm-box-and-sx-from-components
mperrotti Sep 11, 2025
a0bbeb1
fixes mistake in UnderlineNavItem prop type
mperrotti Sep 11, 2025
487ae53
Merge branch 'mp/rm-box-and-sx-from-components' of github.com:primer/…
mperrotti Sep 11, 2025
c142b2e
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 11, 2025
c8cf28b
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 12, 2025
23b3fb1
revert Dialog changes (handled in separate PR)
mperrotti Sep 12, 2025
f742094
fixes type errors
mperrotti Sep 12, 2025
e6c77b6
fixes type error in PageLayout default story
mperrotti Sep 12, 2025
5683bc0
fixes failing VRT for PageLayout Dev Default story
mperrotti Sep 12, 2025
75b602a
replaces polymorphic2 with modern-polymorphic
mperrotti Sep 12, 2025
7c427b9
fixes type error in styled-react PageHeader
mperrotti Sep 12, 2025
f2efa0d
fixes silly typo causing type errors
mperrotti Sep 12, 2025
66d0ecb
fixes type errors in AriaAlert, and AriaStatus
mperrotti Sep 12, 2025
1801545
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 15, 2025
cc36c5d
updates snapshots
mperrotti Sep 15, 2025
ecb1484
Merge branch 'main' into mp/rm-box-and-sx-from-components
mperrotti Sep 15, 2025
d7e66df
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 16, 2025
634a103
adds SxProp type to styled-react
mperrotti Sep 16, 2025
6f04f57
attempts to fix type errors in integration tests
mperrotti Sep 16, 2025
a664932
more ActionList type fixes
mperrotti Sep 17, 2025
f6bcc88
UnderlineNavItem type fixes
mperrotti Sep 17, 2025
dd28ce5
get rid of ts-expect-error directives (woohoo)
mperrotti Sep 17, 2025
82ab9a4
still trying to fix ActionList type errors - ActionMenu.tsx having is…
mperrotti Sep 17, 2025
b8ffdbd
more ActionList.Item type fixes, patches new type errors surfaced in …
mperrotti Sep 17, 2025
41477d0
ugh linter fix
mperrotti Sep 17, 2025
06ae495
trying a dumb fix for new ActionList integration test error
mperrotti Sep 17, 2025
46952dd
trying an even dumber fix for ActionList.Item onSelect type errors
mperrotti Sep 17, 2025
90776ed
revert NavList and ActionList changes to shrink the PR
mperrotti Sep 17, 2025
2463320
reverts changes to AutocompleteMenu
mperrotti Sep 17, 2025
4c3f7e0
reverts changes to AutocompleteMenu
mperrotti Sep 17, 2025
b3cbc20
reverts styled-react tests for NavList
mperrotti Sep 17, 2025
e8e9312
reverts UnderlineNav changes
mperrotti Sep 17, 2025
b2913cb
reverts UnderlineNav changes in styled-react
mperrotti Sep 17, 2025
268ca7b
reverts UnderlineTabbedInterface changes
mperrotti Sep 17, 2025
267943e
reverts PageHeader changes
mperrotti Sep 17, 2025
2b47b69
reverts PageLayout changes
mperrotti Sep 17, 2025
207f275
reverts ActionList-related changes from SegmentedControl
mperrotti Sep 17, 2025
557f2e6
adds expect-error directive for something that's handled in a separat…
mperrotti Sep 17, 2025
58fc145
deal with failing tests
mperrotti Sep 18, 2025
2e6cbbf
reverts PageHeader subcomponent prop types export (moved to separate PR)
mperrotti Sep 18, 2025
9d7c05d
updates snapshots
mperrotti Sep 18, 2025
5d688d2
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 24, 2025
5540417
rm dupe checkbox imports in styled-react
mperrotti Sep 24, 2025
5bcebe0
correct heading lineheight assertions
mperrotti Sep 24, 2025
7b1ef28
styled-react tweaks for int tests: exports LinkProps, converts Link t…
mperrotti Sep 24, 2025
c42c45b
Merge branch 'main' of github.com:primer/react into mp/rm-box-and-sx-…
mperrotti Sep 24, 2025
6ae78cc
moves styled-react Heading and Link to their own component files
mperrotti Sep 24, 2025
2b24955
reverts Heading changes - they're handled in a separate PR
mperrotti Sep 24, 2025
178e221
updates changelog
mperrotti Sep 24, 2025
bb77600
un-skip tests
mperrotti Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/light-schools-wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': major
---

Removes `Box` component usage and `sx` prop from some components
12 changes: 1 addition & 11 deletions packages/react/src/Checkbox/Checkbox.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,7 @@
{
"name": "ref",
"type": "React.RefObject<HTMLInputElement>"
},
{
"name": "as",
"type": "React.ElementType",
"defaultValue": "\"input\""
},
{
"name": "sx",
"type": "SystemStyleObject",
"deprecated": true
}
],
"subcomponents": []
}
}
29 changes: 2 additions & 27 deletions packages/react/src/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import {clsx} from 'clsx'
import {useProvidedRefOrCreate} from '../hooks'
import React, {useContext, useEffect, type ChangeEventHandler, type InputHTMLAttributes, type ReactElement} from 'react'
import {type SxProp} from '../sx'
import useLayoutEffect from '../utils/useIsomorphicLayoutEffect'
import type {FormValidationStatus} from '../utils/types/FormValidationStatus'
import {CheckboxGroupContext} from '../CheckboxGroup/CheckboxGroupContext'
import classes from './Checkbox.module.css'
import sharedClasses from './shared.module.css'
import Box from '../Box'

export type CheckboxProps = {
/**
Expand Down Expand Up @@ -35,27 +33,14 @@ export type CheckboxProps = {
* Used during form submission and to identify which checkbox inputs are selected
*/
value?: string
} & Exclude<InputHTMLAttributes<HTMLInputElement>, 'value'> &
SxProp
} & Exclude<InputHTMLAttributes<HTMLInputElement>, 'value'>

/**
* An accessible, native checkbox component
*/
const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
(
{
checked,
className,
defaultChecked,
indeterminate,
disabled,
onChange,
sx: sxProp,
required,
validationStatus,
value,
...rest
},
{checked, className, defaultChecked, indeterminate, disabled, onChange, required, validationStatus, value, ...rest},
ref,
): ReactElement => {
const checkboxRef = useProvidedRefOrCreate(ref as React.RefObject<HTMLInputElement>)
Expand Down Expand Up @@ -99,16 +84,6 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
}
})

if (sxProp) {
return (
<Box
as="input"
{...inputProps}
className={clsx(className, sharedClasses.Input, classes.Checkbox)}
sx={sxProp}
/>
)
}
return <input {...inputProps} className={clsx(className, sharedClasses.Input, classes.Checkbox)} />
},
)
Expand Down
5 changes: 0 additions & 5 deletions packages/react/src/Heading/Heading.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@
"stories": [],
"importPath": "@primer/react",
"props": [
{
"name": "sx",
"type": "SystemStyleObject",
"deprecated": true
},
{
"name": "as",
"type": "React.ElementType",
Expand Down
11 changes: 0 additions & 11 deletions packages/react/src/Heading/Heading.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@ export default {
title: 'Components/Heading/Features',
}

export const TestSx: StoryFn<typeof Heading> = () => (
<Heading
sx={{
fontSize: 2,
fontWeight: 'normal',
}}
>
Heading with sx override
</Heading>
)

export const Small: StoryFn<typeof Heading> = () => <Heading variant="small">Small heading</Heading>

export const Medium: StoryFn<typeof Heading> = () => <Heading variant="medium">Medium heading</Heading>
Expand Down
46 changes: 22 additions & 24 deletions packages/react/src/Heading/Heading.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import {clsx} from 'clsx'
import React, {forwardRef, useEffect} from 'react'
import React, {useEffect} from 'react'
import {useRefObjectAsForwardedRef} from '../hooks'
import type {SxProp} from '../sx'
import type {ComponentProps} from '../utils/types'
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic'
import classes from './Heading.module.css'
import Box from '../Box'
import {type PolymorphicProps, fixedForwardRef} from '../utils/modern-polymorphic'

type StyledHeadingProps = {
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
variant?: 'large' | 'medium' | 'small'
} & SxProp
type HeadingElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'

const Heading = forwardRef(({as: Component = 'h2', className, variant, ...props}, forwardedRef) => {
const UnwrappedHeading = <As extends HeadingElement = 'h2'>(
props: PolymorphicProps<
As,
'h2',
{
as?: As
variant?: 'large' | 'medium' | 'small'
}
>,
forwardedRef: React.ForwardedRef<unknown>,
) => {
const {as: Component = 'h2', className, variant, ...restProps} = props
const innerRef = React.useRef<HTMLHeadingElement>(null)
useRefObjectAsForwardedRef(forwardedRef, innerRef)

Expand All @@ -33,22 +39,14 @@ const Heading = forwardRef(({as: Component = 'h2', className, variant, ...props}
}, [innerRef])
}

if (props.sx) {
return (
<Box
as={Component}
className={clsx(className, classes.Heading)}
data-variant={variant}
{...props}
// @ts-ignore temporary disable as we migrate to css modules, until we remove PolymorphicForwardRefComponent
ref={innerRef}
/>
)
}
return <Component className={clsx(className, classes.Heading)} data-variant={variant} {...props} ref={innerRef} />
}) as PolymorphicForwardRefComponent<'h2', StyledHeadingProps>
return <Component className={clsx(className, classes.Heading)} data-variant={variant} {...restProps} ref={innerRef} />
}

const Heading = fixedForwardRef(UnwrappedHeading)

Heading.displayName = 'Heading'
// We can't assign displayName to the result of fixedForwardRef directly,
// so we assign it to the component and cast it to the expected type
Object.assign(Heading, {displayName: 'Heading'})

export type HeadingProps = ComponentProps<typeof Heading>
export default Heading
130 changes: 0 additions & 130 deletions packages/react/src/Heading/__tests__/Heading.test.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
import {describe, expect, it, vi} from 'vitest'
import {Heading} from '../..'
import {render, screen} from '@testing-library/react'
import ThemeProvider from '../../ThemeProvider'

const theme = {
breakpoints: ['400px', '640px', '960px', '1280px'],
colors: {
green: ['#010', '#020', '#030', '#040', '#050', '#060'],
},
fontSizes: ['12px', '14px', '16px', '20px', '24px', '32px', '40px', '48px'],
fonts: {
normal: 'Helvetica,sans-serif',
mono: 'Consolas,monospace',
},
lineHeights: {
normal: 1.5,
condensed: 1.25,
condensedUltra: 1,
},
fontWeights: {
light: '300',
normal: '400',
semibold: '500',
bold: '600',
},
}

describe('Heading', () => {
it('should support `className` on the outermost element', () => {
Expand All @@ -38,89 +14,6 @@ describe('Heading', () => {
expect(heading.tagName).toBe('H2')
})

it('respects fontWeight', () => {
const {container} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontWeight: 'bold'}} />
</ThemeProvider>,
)
const heading = container.firstChild as HTMLElement
expect(heading).toHaveStyle(`font-weight: ${theme.fontWeights.bold}`)

const {container: container2} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontWeight: 'normal'}} />
</ThemeProvider>,
)
const heading2 = container2.firstChild as HTMLElement
expect(heading2).toHaveStyle(`font-weight: ${theme.fontWeights.normal}`)

const {container: container3} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontWeight: 'semibold'}} />
</ThemeProvider>,
)
const heading3 = container3.firstChild as HTMLElement
expect(heading3).toHaveStyle(`font-weight: ${theme.fontWeights.semibold}`)

const {container: container4} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontWeight: 'light'}} />
</ThemeProvider>,
)
const heading4 = container4.firstChild as HTMLElement
expect(heading4).toHaveStyle(`font-weight: ${theme.fontWeights.light}`)
})

it('respects lineHeight', () => {
const {container} = render(
<ThemeProvider theme={theme}>
<Heading sx={{lineHeight: 'normal'}} />
</ThemeProvider>,
)
const heading = container.firstChild as HTMLElement
///These sx tests should go away right?
expect(heading).toHaveStyle(`line-height: 48px`)

const {container: container2} = render(
<ThemeProvider theme={theme}>
<Heading sx={{lineHeight: 'condensed'}} />
</ThemeProvider>,
)
const heading2 = container2.firstChild as HTMLElement
expect(heading2).toHaveStyle(`line-height: 40px`)

const {container: container3} = render(
<ThemeProvider theme={theme}>
<Heading sx={{lineHeight: 'condensedUltra'}} />
</ThemeProvider>,
)
const heading3 = container3.firstChild as HTMLElement
expect(heading3).toHaveStyle(`line-height: 32px`)
})

it('respects fontFamily="mono"', () => {
const {container} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontFamily: 'mono'}} />
</ThemeProvider>,
)
const heading = container.firstChild as HTMLElement
expect(heading).toHaveStyle(`font-family: ${theme.fonts.mono}`)
})

it('renders fontSize', () => {
for (const fontSize of theme.fontSizes) {
const {container} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontSize}} />
</ThemeProvider>,
)
const heading = container.firstChild as HTMLElement
expect(heading).toHaveStyle(`font-size: ${fontSize}`)
}
})

it('logs a warning when trying to render invalid "as" prop', () => {
const consoleSpy = vi.spyOn(globalThis.console, 'warn').mockImplementation(() => {})

Expand All @@ -130,15 +23,6 @@ describe('Heading', () => {

consoleSpy.mockRestore()
})
it('respects the "fontStyle" prop', () => {
const {container} = render(
<ThemeProvider theme={theme}>
<Heading sx={{fontStyle: 'italic'}} />
</ThemeProvider>,
)
const heading = container.firstChild as HTMLElement
expect(heading).toHaveStyle('font-style: italic')
})

// How can we test for generated class names?
it.skip('should only include css modules class', () => {
Expand All @@ -148,18 +32,4 @@ describe('Heading', () => {
// for this component
expect(screen.getByText('test')).not.toHaveClass(/^Heading__StyledHeading/)
})

it('should support overrides with sx if provided', () => {
render(
<Heading
sx={{
fontWeight: '900',
}}
>
test
</Heading>,
)

expect(screen.getByText('test')).toHaveStyle('font-weight: 900')
})
})
2 changes: 1 addition & 1 deletion packages/react/src/Hidden/Hidden.examples.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const PullRequestPage = () => (
<StateLabel status="pullOpened">Open</StateLabel>
<Hidden when={['narrow']}>
<Text sx={{fontSize: 1, color: 'fg.muted'}}>
<Link href="#" muted sx={{fontWeight: 'bold'}}>
<Link href="#" muted style={{fontWeight: 'var(--base-text-weight-semibold)'}}>
broccolinisoup
</Link>{' '}
wants to merge 3 commits into
Expand Down
5 changes: 0 additions & 5 deletions packages/react/src/Link/Link.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@
"name": "as",
"type": "React.ElementType",
"defaultValue": "\"a\""
},
{
"name": "sx",
"type": "SystemStyleObject",
"deprecated": true
}
],
"subcomponents": []
Expand Down
Loading
Loading