diff --git a/.changeset/soft-bananas-behave.md b/.changeset/soft-bananas-behave.md
deleted file mode 100644
index 1df88830ada..00000000000
--- a/.changeset/soft-bananas-behave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@primer/react": minor
----
-
-Update FormControl sub-components to use new styled components format for migration
diff --git a/package-lock.json b/package-lock.json
index 086b673380e..8394b00ba12 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -62,7 +62,7 @@
"name": "example-app-router",
"version": "0.0.0",
"dependencies": {
- "@primer/react": "37.6.0",
+ "@primer/react": "37.5.0",
"next": "^14.2.10",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -81,7 +81,7 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
- "@primer/react": "37.6.0",
+ "@primer/react": "37.5.0",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.11.0",
@@ -99,7 +99,7 @@
"name": "example-consumer-test",
"version": "0.0.0",
"dependencies": {
- "@primer/react": "37.6.0",
+ "@primer/react": "37.5.0",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.2.19",
"@types/styled-components": "^5.1.11",
@@ -125,7 +125,7 @@
"version": "0.0.0",
"dependencies": {
"@primer/octicons-react": "^19.9.0",
- "@primer/react": "37.6.0",
+ "@primer/react": "37.5.0",
"clsx": "^1.2.1",
"next": "^14.2.10",
"react": "^18.3.1",
@@ -30443,7 +30443,7 @@
},
"packages/react": {
"name": "@primer/react",
- "version": "37.6.0",
+ "version": "37.5.0",
"license": "MIT",
"dependencies": {
"@github/relative-time-element": "^4.4.3",
diff --git a/package.json b/package.json
index b4f69ece0ba..cf3ab916a77 100644
--- a/package.json
+++ b/package.json
@@ -93,6 +93,5 @@
"webpack": false,
"running": false
}
- ],
- "packageManager": "npm@10.9.1+sha512.c89530d37c4baa38afd43e76a077a84b9aa63840b986426584fd5c5a54ab0a0b21bb1595c851042b733784b0b43706d36a494b4d8ae1a086a762cb8d3f95942a"
+ ]
}
diff --git a/packages/react/src/FormControl/FormControl.tsx b/packages/react/src/FormControl/FormControl.tsx
index 69d4b9bf871..a629806a353 100644
--- a/packages/react/src/FormControl/FormControl.tsx
+++ b/packages/react/src/FormControl/FormControl.tsx
@@ -14,9 +14,9 @@ import {get} from '../constants'
import {useSlots} from '../hooks/useSlots'
import type {SxProp} from '../sx'
import {useId} from '../hooks/useId'
-import {FormControlCaption} from './FormControlCaption'
-import FormControlLabel from './FormControlLabel'
-import FormControlLeadingVisual from './FormControlLeadingVisual'
+import FormControlCaption from './_FormControlCaption'
+import FormControlLabel from './_FormControlLabel'
+import FormControlLeadingVisual from './_FormControlLeadingVisual'
import FormControlValidation from './_FormControlValidation'
import {FormControlContextProvider} from './_FormControlContext'
import {warning} from '../utils/warning'
diff --git a/packages/react/src/FormControl/FormControlCaption.tsx b/packages/react/src/FormControl/FormControlCaption.tsx
deleted file mode 100644
index dc05e1a3bad..00000000000
--- a/packages/react/src/FormControl/FormControlCaption.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-import type {SxProp} from '../sx'
-import {useFormControlContext} from './_FormControlContext'
-import Text from '../Text'
-import styled from 'styled-components'
-import {get} from '../constants'
-import sx from '../sx'
-
-const StyledCaption = styled(Text)`
- color: var(--fgColor-muted);
- display: block;
- font-size: ${get('fontSizes.0')};
-
- &:where([data-control-disabled]) {
- color: var(--control-fgColor-disabled);
- }
-
- ${sx}
-`
-
-type FormControlCaptionProps = React.PropsWithChildren<
- {
- id?: string
- } & SxProp
->
-
-function FormControlCaption({id, children, sx}: FormControlCaptionProps) {
- const {captionId, disabled} = useFormControlContext()
- return (
-
- {children}
-
- )
-}
-
-export {FormControlCaption}
diff --git a/packages/react/src/FormControl/FormControlLeadingVisual.tsx b/packages/react/src/FormControl/FormControlLeadingVisual.tsx
deleted file mode 100644
index 27c18d69aca..00000000000
--- a/packages/react/src/FormControl/FormControlLeadingVisual.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react'
-import {get} from '../constants'
-import type {SxProp} from '../sx'
-import {useFormControlContext} from './_FormControlContext'
-import styled from 'styled-components'
-import sx from '../sx'
-
-const FormControlLeadingVisual: React.FC> = ({children, sx}) => {
- const {disabled, captionId} = useFormControlContext()
- return (
-
- {children}
-
- )
-}
-
-const StyledLeadingVisual = styled.div`
- --leadingVisual-size: ${get('fontSizes.2')};
-
- color: var(--fgColor-default);
- margin-inline-start: ${get('space.2')};
-
- &:where([data-control-disabled]) {
- color: var(--fgColor-muted);
- }
-
- & > * {
- min-width: var(--leadingVisual-size);
- min-height: var(--leadingVisual-size);
- fill: currentColor;
- }
-
- &:where([data-has-caption]) {
- --leadingVisual-size: ${get('fontSizes.4')};
- }
-
- ${sx}
-`
-
-export default FormControlLeadingVisual
diff --git a/packages/react/src/FormControl/_FormControlCaption.tsx b/packages/react/src/FormControl/_FormControlCaption.tsx
new file mode 100644
index 00000000000..4a3be2bdedb
--- /dev/null
+++ b/packages/react/src/FormControl/_FormControlCaption.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import InputCaption from '../internal/components/InputCaption'
+import type {SxProp} from '../sx'
+import {useFormControlContext} from './_FormControlContext'
+
+const FormControlCaption: React.FC> = ({children, sx, id}) => {
+ const {captionId, disabled} = useFormControlContext()
+ return (
+
+ {children}
+
+ )
+}
+
+export default FormControlCaption
diff --git a/packages/react/src/FormControl/FormControlLabel.tsx b/packages/react/src/FormControl/_FormControlLabel.tsx
similarity index 95%
rename from packages/react/src/FormControl/FormControlLabel.tsx
rename to packages/react/src/FormControl/_FormControlLabel.tsx
index 485894c18d4..4d62b19e114 100644
--- a/packages/react/src/FormControl/FormControlLabel.tsx
+++ b/packages/react/src/FormControl/_FormControlLabel.tsx
@@ -1,7 +1,7 @@
import React from 'react'
+import InputLabel from '../internal/components/InputLabel'
import type {SxProp} from '../sx'
import {useFormControlContext} from './_FormControlContext'
-import {InputLabel} from '../internal/components/InputLabel'
export type Props = {
/**
@@ -49,7 +49,6 @@ const FormControlLabel: React.FC<
sx,
...props,
}
-
return {children}
}
diff --git a/packages/react/src/FormControl/_FormControlLeadingVisual.tsx b/packages/react/src/FormControl/_FormControlLeadingVisual.tsx
new file mode 100644
index 00000000000..80551681704
--- /dev/null
+++ b/packages/react/src/FormControl/_FormControlLeadingVisual.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import Box from '../Box'
+import {get} from '../constants'
+import type {SxProp} from '../sx'
+import {useFormControlContext} from './_FormControlContext'
+
+const FormControlLeadingVisual: React.FC> = ({children, sx}) => {
+ const {disabled, captionId} = useFormControlContext()
+ return (
+ *': {
+ minWidth: captionId ? get('fontSizes.4') : get('fontSizes.2'),
+ minHeight: captionId ? get('fontSizes.4') : get('fontSizes.2'),
+ fill: 'currentColor',
+ },
+ ...sx,
+ }}
+ ml={2}
+ >
+ {children}
+
+ )
+}
+
+export default FormControlLeadingVisual
diff --git a/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx b/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx
index b407db2cf19..6cffe9375e3 100644
--- a/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx
+++ b/packages/react/src/experimental/SelectPanel2/SelectPanel.tsx
@@ -20,7 +20,7 @@ import {useSlots} from '../../hooks/useSlots'
import {useProvidedRefOrCreate, useId, useAnchoredPosition} from '../../hooks'
import type {OverlayProps} from '../../Overlay/Overlay'
import {StyledOverlay, heightMap} from '../../Overlay/Overlay'
-import {InputLabel} from '../../internal/components/InputLabel'
+import InputLabel from '../../internal/components/InputLabel'
import {invariant} from '../../utils/invariant'
import {AriaStatus} from '../../live-region'
import {useResponsiveValue} from '../../hooks/useResponsiveValue'
diff --git a/packages/react/src/internal/components/InputCaption.tsx b/packages/react/src/internal/components/InputCaption.tsx
new file mode 100644
index 00000000000..03fbb184be9
--- /dev/null
+++ b/packages/react/src/internal/components/InputCaption.tsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import Text from '../../Text'
+import type {SxProp} from '../../sx'
+
+type Props = {
+ /**
+ * The unique identifier used to associate the caption with an input
+ */
+ id: string
+ /**
+ * Whether the input associated with this caption is disabled
+ */
+ disabled?: boolean
+} & SxProp
+
+const InputCaption: React.FC> = ({children, disabled, id, sx}) => (
+
+ {children}
+
+)
+
+export default InputCaption
diff --git a/packages/react/src/internal/components/InputLabel.tsx b/packages/react/src/internal/components/InputLabel.tsx
index 9126d192086..b4d2fa43aed 100644
--- a/packages/react/src/internal/components/InputLabel.tsx
+++ b/packages/react/src/internal/components/InputLabel.tsx
@@ -1,7 +1,7 @@
import React from 'react'
-import styled from 'styled-components'
-import {get} from '../../constants'
-import sx, {type SxProp} from '../../sx'
+import Box from '../../Box'
+import type {SxProp} from '../../sx'
+import VisuallyHidden from '../../_VisuallyHidden'
type BaseProps = SxProp & {
disabled?: boolean
@@ -23,9 +23,9 @@ export type LegendOrSpanProps = BaseProps & {
htmlFor?: undefined
}
-type Props = React.PropsWithChildren
+type Props = LabelProps | LegendOrSpanProps
-function InputLabel({
+const InputLabel: React.FC> = ({
children,
disabled,
htmlFor,
@@ -38,62 +38,37 @@ function InputLabel({
as = 'label',
className,
...props
-}: Props) {
+}) => {
return (
-
{required || requiredText ? (
-
- {children}
+
+ {children}
{requiredText ?? '*'}
-
+
) : (
children
)}
-
+
)
}
-const StyledRequiredText = styled.span`
- display: flex;
- column-gap: ${get('space.1')};
-`
-
-const StyledLabel = styled.label`
- align-self: flex-start;
- display: block;
- color: var(--fgColor-default);
- cursor: pointer;
- font-weight: 600;
- font-size: ${get('fontSizes.1')};
-
- &:where([data-control-disabled]) {
- color: var(--fgColor-muted);
- cursor: not-allowed;
- }
-
- &:where([data-visually-hidden]) {
- border: 0;
- clip: rect(0 0 0 0);
- clip-path: inset(50%);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- white-space: nowrap;
- width: 1px;
- }
-
- ${sx}
-`
-
-export {InputLabel}
+export default InputLabel
diff --git a/packages/react/src/internal/components/InputValidation.tsx b/packages/react/src/internal/components/InputValidation.tsx
index d23fe867cb5..cfa2c8537b5 100644
--- a/packages/react/src/internal/components/InputValidation.tsx
+++ b/packages/react/src/internal/components/InputValidation.tsx
@@ -1,12 +1,10 @@
import type {IconProps} from '@primer/octicons-react'
import {AlertFillIcon, CheckCircleFillIcon} from '@primer/octicons-react'
import React from 'react'
+import Box from '../../Box'
import Text from '../../Text'
import type {SxProp} from '../../sx'
import type {FormValidationStatus} from '../../utils/types/FormValidationStatus'
-import styled from 'styled-components'
-import {get} from '../../constants'
-import sx from '../../sx'
type Props = {
id: string
@@ -21,8 +19,14 @@ const validationIconMap: Record<
error: AlertFillIcon,
}
+const validationColorMap: Record, string> = {
+ success: 'success.fg',
+ error: 'danger.fg',
+}
+
const InputValidation: React.FC> = ({children, id, validationStatus, sx}) => {
const IconComponent = validationStatus ? validationIconMap[validationStatus] : undefined
+ const fgColor = validationStatus ? validationColorMap[validationStatus] : undefined
// TODO: use `text-caption-lineHeight` token as a custom property when it's available
// then, we can move this all to CSS and use `calc` to get our height values
@@ -31,57 +35,30 @@ const InputValidation: React.FC> = ({children, id
const iconBoxMinHeight = iconSize * captionLineHeight
return (
-
- {IconComponent ? (
-
+
+ {IconComponent && (
+
-
- ) : null}
-
+
+ )}
+
{children}
-
-
+
+
)
}
-const StyledInputValidation = styled(Text)`
- color: var(--inputValidation-fgColor);
- display: flex;
- font-size: ${get('fontSizes.0')};
- font-weight: 600;
-
- & :where(a) {
- color: currentColor;
- text-dectoration: underline;
- }
-
- &:where([data-validation-status='success']) {
- --inputValidation-fgColor: ${get('colors.success.fg')};
- }
-
- &:where([data-validation-status='error']) {
- --inputValidation-fgColor: ${get('colors.danger.fg')};
- }
-
- ${sx}
-`
-
-const StyledValidationIcon = styled.span`
- align-items: center;
- display: flex;
- margin-inline-end: ${get('space.1')};
- min-height: var(--inputValidation-iconSize);
-`
-
-const StyledValidationText = styled.span`
- line-height: var(--inputValidation-lineHeight);
-`
-
export default InputValidation