Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6a86e54
rms BoxWithFallback and sx prop from InputLabel and UnstyledTextInput
mperrotti Sep 30, 2025
0787f12
adds changeset
mperrotti Sep 30, 2025
64ad2c6
fixes FormControlLabel types to adapt to InputLabel changes
mperrotti Sep 30, 2025
220bab0
Merge branch 'main' of github.com:primer/react into mp/rm-boxwithfall…
mperrotti Sep 30, 2025
d24e12a
Apply suggestion from @Copilot
francinelucca Oct 1, 2025
9a935e1
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
mperrotti Oct 1, 2025
53a61f9
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
mperrotti Oct 1, 2025
9a070a7
reverts type changes to InputLabel
mperrotti Oct 1, 2025
aedf8bc
bring back InputLabel props to FormControlLabel
mperrotti Oct 2, 2025
d4dd920
exports FormControl.Label from styled-react
mperrotti Oct 2, 2025
3328862
fixes typo
mperrotti Oct 2, 2025
90a0946
revert styled FormControl changes
francinelucca Oct 3, 2025
36b4999
remove unused import
francinelucca Oct 3, 2025
ca2a8d3
Merge branch 'main' of github.com:primer/react into mp/rm-boxwithfall…
francinelucca Oct 3, 2025
3236185
remaining sx removals
francinelucca Oct 6, 2025
48d4b1f
chore: remove remaining sx usage
francinelucca Oct 6, 2025
155488b
remove remaining sx
francinelucca Oct 6, 2025
514a572
remove remaining sx
francinelucca Oct 6, 2025
9d39df0
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 6, 2025
c7bbb2b
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 6, 2025
b0ac7d8
refactor FormControlLabel
francinelucca Oct 6, 2025
17c99ef
component wrapper fix
francinelucca Oct 6, 2025
b9952c3
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 6, 2025
25143fe
lint
francinelucca Oct 6, 2025
28a81b1
Merge branch 'mp/rm-boxwithfallback-internal-input-helpers' of github…
francinelucca Oct 6, 2025
963fafd
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 6, 2025
fe5808f
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 7, 2025
27c7c8e
Merge branch 'main' into mp/rm-boxwithfallback-internal-input-helpers
francinelucca Oct 7, 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/better-steaks-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': major
---

Removes `sx` prop from internal helper components which results in `sx` no longer being available on the TextInput.Label component
72 changes: 40 additions & 32 deletions packages/react/src/FormControl/FormControlLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,51 @@ export type Props = {
requiredIndicator?: boolean
id?: string
className?: string
as?: 'label' | 'legend' | 'span'
}

const FormControlLabel: React.FC<
React.PropsWithChildren<{htmlFor?: string} & React.ComponentProps<typeof InputLabel> & Props>
> = ({as, children, htmlFor, id, visuallyHidden, requiredIndicator = true, requiredText, className, ...props}) => {
type FormControlLabelProps = React.PropsWithChildren<{htmlFor?: string} & Props>

const FormControlLabel: React.FC<FormControlLabelProps> = ({
as,
children,
htmlFor,
id,
visuallyHidden,
requiredIndicator = true,
requiredText,
className,
...props
}) => {
const {disabled, id: formControlId, required} = useFormControlContext()

/**
* Ensure we can pass through props correctly, since legend/span accept no defined 'htmlFor'
*/
const labelProps: React.ComponentProps<typeof InputLabel> =
as === 'legend' || as === 'span'
? {
as,
id,
className,
visuallyHidden,
required,
requiredText,
requiredIndicator,
disabled,
...props,
}
: {
as,
id,
className,
visuallyHidden,
htmlFor: htmlFor || formControlId,
required,
requiredText,
requiredIndicator,
disabled,
...props,
}
// Base props that are common to all element types
const baseProps = {
id,
className,
visuallyHidden,
required,
requiredText,
requiredIndicator,
disabled,
...props,
}

// For legend and span elements, don't pass htmlFor
if (as === 'legend' || as === 'span') {
return (
<InputLabel as={as} {...baseProps}>
{children}
</InputLabel>
)
}

return <InputLabel {...labelProps}>{children}</InputLabel>
// For label elements (default), include htmlFor
return (
<InputLabel as={as} htmlFor={htmlFor || formControlId} {...baseProps}>
{children}
</InputLabel>
)
}

export default FormControlLabel
53 changes: 22 additions & 31 deletions packages/react/src/internal/components/InputLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
import {clsx} from 'clsx'
import type React from 'react'
import {type SxProp} from '../../sx'
import type {ElementType} from 'react'
import classes from './InputLabel.module.css'
import {BoxWithFallback} from './BoxWithFallback'
import type {PolymorphicProps} from '../../utils/modern-polymorphic'

type BaseProps = SxProp & {
disabled?: boolean
required?: boolean
requiredText?: string
requiredIndicator?: boolean
visuallyHidden?: boolean
id?: string
className?: string
}

export type LabelProps = BaseProps & {
htmlFor?: string
as?: 'label'
}

export type LegendOrSpanProps = BaseProps & {
as: 'legend' | 'span'
htmlFor?: undefined
}
type InputLabelProps<As extends ElementType = 'label'> = PolymorphicProps<
As,
'label',
{
disabled?: boolean
required?: boolean
requiredText?: string
requiredIndicator?: boolean
visuallyHidden?: boolean
}
> &
React.PropsWithChildren

type Props = React.PropsWithChildren<LabelProps | LegendOrSpanProps>
export type LabelProps = InputLabelProps<'label'>
export type LegendOrSpanProps = InputLabelProps<'legend' | 'span'>

function InputLabel({
function InputLabel<As extends ElementType = 'label'>({
children,
disabled,
htmlFor,
Expand All @@ -35,16 +29,13 @@ function InputLabel({
requiredText,
requiredIndicator,
visuallyHidden,
sx,
as = 'label',
as,
className,
...props
}: Props) {
}: InputLabelProps<As>) {
const Component = as || 'label'
Comment thread
francinelucca marked this conversation as resolved.
Outdated
return (
// @ts-ignore weird typing issue with union for `as` prop
<BoxWithFallback
as={as}
sx={sx}
<Component
data-control-disabled={disabled ? '' : undefined}
data-visually-hidden={visuallyHidden ? '' : undefined}
htmlFor={htmlFor}
Expand All @@ -60,7 +51,7 @@ function InputLabel({
) : (
children
)}
</BoxWithFallback>
</Component>
)
}

Expand Down
6 changes: 2 additions & 4 deletions packages/react/src/internal/components/UnstyledTextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import {type SxProp} from '../../sx'
import React from 'react'

import styles from './UnstyledTextInput.module.css'
import {clsx} from 'clsx'
import {BoxWithFallback} from './BoxWithFallback'

type ToggledUnstyledTextInputProps = React.ComponentPropsWithoutRef<'input'> & SxProp
type ToggledUnstyledTextInputProps = React.ComponentPropsWithoutRef<'input'>

const UnstyledTextInput = React.forwardRef<HTMLInputElement, ToggledUnstyledTextInputProps>(function UnstyledTextInput(
{className, ...rest},
forwardRef,
) {
return <BoxWithFallback as="input" ref={forwardRef} {...rest} className={clsx(className, styles.Input)} />
return <input ref={forwardRef} {...rest} className={clsx(className, styles.Input)} />
})
UnstyledTextInput.displayName = 'UnstyledTextInput'

Expand Down
Loading