From eea386894c968b6c5f3ca93cc26b3cb0b919f786 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Fri, 3 Oct 2025 09:39:54 -0400 Subject: [PATCH] revert: Remove support for sx from FormControl component (#6681) --- .changeset/grumpy-lobsters-obey.md | 5 --- .../src/FormControl/FormControl.docs.json | 27 +++++++++++- .../react/src/FormControl/FormControl.tsx | 16 ++++--- .../src/FormControl/FormControlCaption.tsx | 20 ++++++--- .../src/FormControl/FormControlLabel.tsx | 7 ++- .../FormControlLeadingVisual.module.css | 21 --------- .../FormControl/FormControlLeadingVisual.tsx | 38 +++++++++++++--- packages/react/src/FormControl/index.ts | 4 -- .../__snapshots__/exports.test.ts.snap | 4 -- .../SelectPanel.examples.stories.module.css | 4 -- .../SelectPanel.examples.stories.tsx | 4 +- packages/react/src/index.ts | 6 --- .../src/components/FormControl.tsx | 44 ------------------- packages/styled-react/src/index.tsx | 2 +- 14 files changed, 90 insertions(+), 112 deletions(-) delete mode 100644 .changeset/grumpy-lobsters-obey.md delete mode 100644 packages/react/src/FormControl/FormControlLeadingVisual.module.css delete mode 100644 packages/styled-react/src/components/FormControl.tsx diff --git a/.changeset/grumpy-lobsters-obey.md b/.changeset/grumpy-lobsters-obey.md deleted file mode 100644 index 80311ebbeda..00000000000 --- a/.changeset/grumpy-lobsters-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@primer/react': major ---- - -Update FormControl component to no longer support sx diff --git a/packages/react/src/FormControl/FormControl.docs.json b/packages/react/src/FormControl/FormControl.docs.json index aee7010d566..c1f113f2db3 100644 --- a/packages/react/src/FormControl/FormControl.docs.json +++ b/packages/react/src/FormControl/FormControl.docs.json @@ -98,6 +98,11 @@ "description": "Class name(s) for custom styling.", "defaultValue": "" }, + { + "name": "sx", + "type": "SystemStyleObject", + "deprecated": true + }, { "name": "ref", "type": "React.RefObject" @@ -147,6 +152,11 @@ "type": "string", "description": "Class name(s) for custom styling.", "defaultValue": "" + }, + { + "name": "sx", + "type": "SystemStyleObject", + "deprecated": true } ] }, @@ -164,6 +174,11 @@ "type": "React.ReactNode", "defaultValue": "", "description": "The content (usually just text) that is rendered to give contextual info about the field" + }, + { + "name": "sx", + "type": "SystemStyleObject", + "deprecated": true } ] }, @@ -188,6 +203,11 @@ "type": "string", "description": "May be used to override the ID assigned by FormControl's React Context", "defaultValue": "" + }, + { + "name": "sx", + "type": "SystemStyleObject", + "deprecated": true } ] }, @@ -199,8 +219,13 @@ "type": "React.ReactNode", "defaultValue": "", "description": "The visual to render before the choice input's label" + }, + { + "name": "sx", + "type": "SystemStyleObject", + "deprecated": true } ] } ] -} +} \ No newline at end of file diff --git a/packages/react/src/FormControl/FormControl.tsx b/packages/react/src/FormControl/FormControl.tsx index 802418f6fc0..ae6f0ff9400 100644 --- a/packages/react/src/FormControl/FormControl.tsx +++ b/packages/react/src/FormControl/FormControl.tsx @@ -11,6 +11,7 @@ import Textarea from '../Textarea' import {CheckboxOrRadioGroupContext} from '../internal/components/CheckboxOrRadioGroup' import ValidationAnimationContainer from '../internal/components/ValidationAnimationContainer' import {useSlots} from '../hooks/useSlots' +import type {SxProp} from '../sx' import {useId} from '../hooks/useId' import {FormControlCaption} from './FormControlCaption' import FormControlLabel from './FormControlLabel' @@ -19,6 +20,7 @@ import FormControlValidation from './_FormControlValidation' import {FormControlContextProvider} from './_FormControlContext' import {warning} from '../utils/warning' import classes from './FormControl.module.css' +import {BoxWithFallback} from '../internal/components/BoxWithFallback' export type FormControlProps = { children?: React.ReactNode @@ -40,10 +42,10 @@ export type FormControlProps = { */ layout?: 'horizontal' | 'vertical' className?: string -} +} & SxProp const FormControl = React.forwardRef( - ({children, disabled: disabledProp, layout = 'vertical', id: idProp, required, className}, ref) => { + ({children, disabled: disabledProp, layout = 'vertical', id: idProp, required, sx, className}, ref) => { const [slots, childrenWithoutSlots] = useSlots(children, { caption: FormControlCaption, label: FormControlLabel, @@ -166,17 +168,19 @@ const FormControl = React.forwardRef( }} > {isChoiceInput || layout === 'horizontal' ? ( -
{InputChildren} -
+ ) : ( -
{slots.label} @@ -203,7 +207,7 @@ const FormControl = React.forwardRef( {slots.validation} ) : null} {slots.caption} -
+ )} ) diff --git a/packages/react/src/FormControl/FormControlCaption.tsx b/packages/react/src/FormControl/FormControlCaption.tsx index d01b2bd710e..862cdc5533d 100644 --- a/packages/react/src/FormControl/FormControlCaption.tsx +++ b/packages/react/src/FormControl/FormControlCaption.tsx @@ -1,25 +1,31 @@ import {clsx} from 'clsx' import type React from 'react' import Text from '../Text' +import type {SxProp} from '../sx' import classes from './FormControlCaption.module.css' import {useFormControlContext} from './_FormControlContext' +import {BoxWithFallback} from '../internal/components/BoxWithFallback' -export type FormControlCaptionProps = React.PropsWithChildren<{ - id?: string - className?: string -}> +type FormControlCaptionProps = React.PropsWithChildren< + { + id?: string + className?: string + } & SxProp +> -function FormControlCaption({id, children, className}: FormControlCaptionProps) { +function FormControlCaption({id, children, sx, className}: FormControlCaptionProps) { const {captionId, disabled} = useFormControlContext() return ( - {children} - + ) } diff --git a/packages/react/src/FormControl/FormControlLabel.tsx b/packages/react/src/FormControl/FormControlLabel.tsx index 59b6f4a5fcd..0ac71b80bd9 100644 --- a/packages/react/src/FormControl/FormControlLabel.tsx +++ b/packages/react/src/FormControl/FormControlLabel.tsx @@ -1,4 +1,5 @@ import type React from 'react' +import type {SxProp} from '../sx' import {useFormControlContext} from './_FormControlContext' import {InputLabel} from '../internal/components/InputLabel' @@ -11,11 +12,11 @@ export type Props = { requiredIndicator?: boolean id?: string className?: string -} +} & SxProp const FormControlLabel: React.FC< React.PropsWithChildren<{htmlFor?: string} & React.ComponentProps & Props> -> = ({as, children, htmlFor, id, visuallyHidden, requiredIndicator = true, requiredText, className, ...props}) => { +> = ({as, children, htmlFor, id, visuallyHidden, requiredIndicator = true, requiredText, sx, className, ...props}) => { const {disabled, id: formControlId, required} = useFormControlContext() /** @@ -32,6 +33,7 @@ const FormControlLabel: React.FC< requiredText, requiredIndicator, disabled, + sx, ...props, } : { @@ -44,6 +46,7 @@ const FormControlLabel: React.FC< requiredText, requiredIndicator, disabled, + sx, ...props, } diff --git a/packages/react/src/FormControl/FormControlLeadingVisual.module.css b/packages/react/src/FormControl/FormControlLeadingVisual.module.css deleted file mode 100644 index 35c81bfe8d5..00000000000 --- a/packages/react/src/FormControl/FormControlLeadingVisual.module.css +++ /dev/null @@ -1,21 +0,0 @@ -.LeadingVisual { - --leadingVisual-size: 16px; - - color: var(--fgColor-default); - display: flex; - align-items: center; - - &:where([data-control-disabled]) { - color: var(--control-fgColor-disabled); - } - - & > * { - min-width: var(--leadingVisual-size); - min-height: var(--leadingVisual-size); - fill: currentColor; - } - - &:where([data-has-caption]) { - --leadingVisual-size: 24px; - } -} diff --git a/packages/react/src/FormControl/FormControlLeadingVisual.tsx b/packages/react/src/FormControl/FormControlLeadingVisual.tsx index fa253d1aa4f..3f2a86ef277 100644 --- a/packages/react/src/FormControl/FormControlLeadingVisual.tsx +++ b/packages/react/src/FormControl/FormControlLeadingVisual.tsx @@ -1,18 +1,46 @@ import type React from 'react' +import {get} from '../constants' +import type {SxProp} from '../sx' import {useFormControlContext} from './_FormControlContext' -import classes from './FormControlLeadingVisual.module.css' +import styled from 'styled-components' +import sx from '../sx' -const FormControlLeadingVisual: React.FC = ({children}) => { +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); + + display: flex; + align-items: center; /* Vertical alignment */ + + &:where([data-control-disabled]) { + color: var(--control-fgColor-disabled); + } + + & > * { + 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/index.ts b/packages/react/src/FormControl/index.ts index a4293bef9d9..a79a15f5d3e 100644 --- a/packages/react/src/FormControl/index.ts +++ b/packages/react/src/FormControl/index.ts @@ -1,6 +1,2 @@ export {useFormControlForwardedProps} from './_FormControlContext' export {default} from './FormControl' -export type {FormControlProps} from './FormControl' -export type {FormControlCaptionProps} from './FormControlCaption' -export type {Props as FormControlLabelProps} from './FormControlLabel' -export type {FormControlValidationProps} from './_FormControlValidation' diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index f61edd54c03..6a9e1c692f9 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -74,10 +74,6 @@ exports[`@primer/react > should not update exports without a semver change 1`] = "type FocusTrapHookSettings", "type FocusZoneHookSettings", "FormControl", - "type FormControlCaptionProps", - "type FormControlLabelProps", - "type FormControlProps", - "type FormControlValidationProps", "Header", "type HeaderItemProps", "type HeaderLinkProps", diff --git a/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.module.css b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.module.css index e7896e2c805..bb3de22a978 100644 --- a/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.module.css +++ b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.module.css @@ -60,7 +60,3 @@ max-height: 0; overflow: hidden; } - -.FormControl { - margin-bottom: var(--base-size-8); -} diff --git a/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx index 49506802d89..5bfde76d900 100644 --- a/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx +++ b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx @@ -1069,11 +1069,11 @@ const CreateNewLabelDialog = ({ Note this Dialog is not accessible. Do not copy this.
- + Name - + Color diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index b74637985b3..f37dbea38d8 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -98,12 +98,6 @@ export {ConfirmationDialog} from './ConfirmationDialog/ConfirmationDialog' export {default as Flash} from './Flash' export type {FlashProps} from './Flash' export {default as FormControl} from './FormControl' -export type { - FormControlProps, - FormControlCaptionProps, - FormControlLabelProps, - FormControlValidationProps, -} from './FormControl' export {useFormControlForwardedProps} from './FormControl' export {default as Header} from './Header' export type {HeaderProps, HeaderItemProps, HeaderLinkProps} from './Header' diff --git a/packages/styled-react/src/components/FormControl.tsx b/packages/styled-react/src/components/FormControl.tsx deleted file mode 100644 index b4affd914be..00000000000 --- a/packages/styled-react/src/components/FormControl.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { - Box, - FormControl as PrimerFormControl, - type FormControlProps as PrimerFormControlProps, - type FormControlCaptionProps as PrimerFormControlCaptionProps, - type FormControlValidationProps as PrimerFormControlValidationProps, - type SxProp, -} from '@primer/react' -import {forwardRef, type PropsWithChildren} from 'react' - -type FormControlProps = PropsWithChildren & SxProp - -const FormControlImpl = forwardRef(function FormControl(props, ref) { - return -}) - -type FormControlCaptionProps = PropsWithChildren & SxProp -const FormControlCaption = (props: FormControlCaptionProps) => { - return -} - -type FormControlValidationProps = PropsWithChildren & SxProp - -const FormControlValidation = (props: FormControlValidationProps) => { - return -} - -const FormControlLeadingVisual = (props: PropsWithChildren) => { - return -} - -const FormControl = Object.assign(FormControlImpl, { - Caption: FormControlCaption, - LeadingVisual: FormControlLeadingVisual, - Validation: FormControlValidation, - Label: PrimerFormControl.Label, -}) as typeof FormControlImpl & { - Caption: typeof FormControlCaption - LeadingVisual: typeof FormControlLeadingVisual - Validation: typeof FormControlValidation - Label: typeof PrimerFormControl.Label -} - -export {FormControl, type FormControlProps} diff --git a/packages/styled-react/src/index.tsx b/packages/styled-react/src/index.tsx index aed597490ab..9e25a25976e 100644 --- a/packages/styled-react/src/index.tsx +++ b/packages/styled-react/src/index.tsx @@ -2,6 +2,7 @@ export {ActionList} from '@primer/react' export {Box, type BoxProps} from './components/Box' export {Button} from '@primer/react' export {Details} from '@primer/react' +export {FormControl} from '@primer/react' export {IconButton} from '@primer/react' export {ProgressBar} from '@primer/react' export {Select} from '@primer/react' @@ -27,7 +28,6 @@ export {CircleBadge} from './components/CircleBadge' export {CounterLabel, type CounterLabelProps} from './components/CounterLabel' export {Dialog, type DialogProps} from './components/Dialog' export {Flash} from './components/Flash' -export {FormControl, type FormControlProps} from './components/FormControl' export {Header, type HeaderProps} from './components/Header' export {Heading} from './components/Heading' export {Label, type LabelProps} from './components/Label'