diff --git a/.changeset/grumpy-lobsters-obey.md b/.changeset/grumpy-lobsters-obey.md new file mode 100644 index 00000000000..80311ebbeda --- /dev/null +++ b/.changeset/grumpy-lobsters-obey.md @@ -0,0 +1,5 @@ +--- +'@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 c1f113f2db3..aee7010d566 100644 --- a/packages/react/src/FormControl/FormControl.docs.json +++ b/packages/react/src/FormControl/FormControl.docs.json @@ -98,11 +98,6 @@ "description": "Class name(s) for custom styling.", "defaultValue": "" }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true - }, { "name": "ref", "type": "React.RefObject" @@ -152,11 +147,6 @@ "type": "string", "description": "Class name(s) for custom styling.", "defaultValue": "" - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -174,11 +164,6 @@ "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 } ] }, @@ -203,11 +188,6 @@ "type": "string", "description": "May be used to override the ID assigned by FormControl's React Context", "defaultValue": "" - }, - { - "name": "sx", - "type": "SystemStyleObject", - "deprecated": true } ] }, @@ -219,13 +199,8 @@ "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 7a7e3353ff1..417b844648b 100644 --- a/packages/react/src/FormControl/FormControl.tsx +++ b/packages/react/src/FormControl/FormControl.tsx @@ -11,7 +11,6 @@ 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' @@ -20,7 +19,6 @@ 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' import {isSlot} from '../utils/is-slot' export type FormControlProps = { @@ -44,10 +42,10 @@ export type FormControlProps = { layout?: 'horizontal' | 'vertical' className?: string style?: React.CSSProperties -} & SxProp +} const FormControl = React.forwardRef( - ({children, disabled: disabledProp, layout = 'vertical', id: idProp, required, sx, className, style}, ref) => { + ({children, disabled: disabledProp, layout = 'vertical', id: idProp, required, className, style}, ref) => { const [slots, childrenWithoutSlots] = useSlots(children, { caption: FormControlCaption, label: FormControlLabel, @@ -179,20 +177,18 @@ const FormControl = React.forwardRef( }} > {isChoiceInput || layout === 'horizontal' ? ( - {InputChildren} - + ) : ( - @@ -222,7 +218,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 56a9cdeeff7..a4f402a7213 100644 --- a/packages/react/src/FormControl/FormControlCaption.tsx +++ b/packages/react/src/FormControl/FormControlCaption.tsx @@ -1,33 +1,27 @@ 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' -type FormControlCaptionProps = React.PropsWithChildren< - { - id?: string - className?: string - style?: React.CSSProperties - } & SxProp -> +export type FormControlCaptionProps = React.PropsWithChildren<{ + id?: string + className?: string + style?: React.CSSProperties +}> -function FormControlCaption({id, children, sx, className, style}: FormControlCaptionProps) { +function FormControlCaption({id, children, className, style}: FormControlCaptionProps) { const {captionId, disabled} = useFormControlContext() return ( - {children} - + ) } diff --git a/packages/react/src/FormControl/FormControlLabel.tsx b/packages/react/src/FormControl/FormControlLabel.tsx index 272736759b4..7489596ed36 100644 --- a/packages/react/src/FormControl/FormControlLabel.tsx +++ b/packages/react/src/FormControl/FormControlLabel.tsx @@ -1,5 +1,4 @@ import type React from 'react' -import type {SxProp} from '../sx' import {useFormControlContext} from './_FormControlContext' import {InputLabel} from '../internal/components/InputLabel' import type {FCWithSlotMarker} from '../utils/types' @@ -14,11 +13,11 @@ export type Props = { id?: string className?: string style?: React.CSSProperties -} & SxProp +} const FormControlLabel: FCWithSlotMarker< React.PropsWithChildren<{htmlFor?: string} & React.ComponentProps & Props> -> = ({as, children, htmlFor, id, visuallyHidden, requiredIndicator = true, requiredText, sx, className, ...props}) => { +> = ({as, children, htmlFor, id, visuallyHidden, requiredIndicator = true, requiredText, className, ...props}) => { const {disabled, id: formControlId, required} = useFormControlContext() /** @@ -35,7 +34,6 @@ const FormControlLabel: FCWithSlotMarker< requiredText, requiredIndicator, disabled, - sx, ...props, } : { @@ -48,7 +46,6 @@ const FormControlLabel: FCWithSlotMarker< requiredText, requiredIndicator, disabled, - sx, ...props, } diff --git a/packages/react/src/FormControl/FormControlLeadingVisual.module.css b/packages/react/src/FormControl/FormControlLeadingVisual.module.css new file mode 100644 index 00000000000..35c81bfe8d5 --- /dev/null +++ b/packages/react/src/FormControl/FormControlLeadingVisual.module.css @@ -0,0 +1,21 @@ +.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 5042a344788..5063c690df7 100644 --- a/packages/react/src/FormControl/FormControlLeadingVisual.tsx +++ b/packages/react/src/FormControl/FormControlLeadingVisual.tsx @@ -1,53 +1,25 @@ import type React from 'react' -import type {SxProp} from '../sx' import {useFormControlContext} from './_FormControlContext' -import styled from 'styled-components' -import sx from '../sx' +import classes from './FormControlLeadingVisual.module.css' import type {FCWithSlotMarker} from '../utils/types' -const FormControlLeadingVisual: FCWithSlotMarker> = ({ +const FormControlLeadingVisual: FCWithSlotMarker> = ({ children, - sx, style, }) => { const {disabled, captionId} = useFormControlContext() return ( - {children} - + ) } -const StyledLeadingVisual = styled.div` - --leadingVisual-size: var(--text-title-size-small); - - 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: var(--base-size-24); - } - - ${sx} -` - FormControlLeadingVisual.__SLOT__ = Symbol('FormControl.LeadingVisual') export default FormControlLeadingVisual diff --git a/packages/react/src/FormControl/_FormControlValidation.tsx b/packages/react/src/FormControl/_FormControlValidation.tsx index 3268964b644..6cde64ba242 100644 --- a/packages/react/src/FormControl/_FormControlValidation.tsx +++ b/packages/react/src/FormControl/_FormControlValidation.tsx @@ -1,6 +1,5 @@ import type React from 'react' import InputValidation from '../internal/components/InputValidation' -import type {SxProp} from '../sx' import type {FormValidationStatus} from '../utils/types/FormValidationStatus' import {useFormControlContext} from './_FormControlContext' import type {FCWithSlotMarker} from '../utils/types' @@ -10,13 +9,12 @@ export type FormControlValidationProps = { id?: string className?: string style?: React.CSSProperties -} & SxProp +} const FormControlValidation: FCWithSlotMarker> = ({ children, className, variant, - sx, id, style, }) => { @@ -26,7 +24,6 @@ const FormControlValidation: FCWithSlotMarker {children} diff --git a/packages/react/src/FormControl/index.ts b/packages/react/src/FormControl/index.ts index a79a15f5d3e..a4293bef9d9 100644 --- a/packages/react/src/FormControl/index.ts +++ b/packages/react/src/FormControl/index.ts @@ -1,2 +1,6 @@ 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 dcb72ad996b..efc9123a2aa 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -74,6 +74,10 @@ 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.tsx b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx index dd3cba2b143..15616ace1d7 100644 --- a/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx +++ b/packages/react/src/experimental/SelectPanel2/SelectPanel.examples.stories.tsx @@ -1078,11 +1078,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 56f9268070c..5159f3ad5d4 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -101,6 +101,12 @@ 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/react/src/internal/components/InputLabel.tsx b/packages/react/src/internal/components/InputLabel.tsx index 63e7bf86086..5f8924ce1a3 100644 --- a/packages/react/src/internal/components/InputLabel.tsx +++ b/packages/react/src/internal/components/InputLabel.tsx @@ -1,10 +1,8 @@ import {clsx} from 'clsx' import type React from 'react' -import {type SxProp} from '../../sx' import classes from './InputLabel.module.css' -import {BoxWithFallback} from './BoxWithFallback' -type BaseProps = SxProp & { +type BaseProps = { disabled?: boolean required?: boolean requiredText?: string @@ -35,16 +33,14 @@ function InputLabel({ requiredText, requiredIndicator, visuallyHidden, - sx, as = 'label', className, ...props }: Props) { + const Component = as + return ( - // @ts-ignore weird typing issue with union for `as` prop - + ) } diff --git a/packages/react/src/internal/components/InputValidation.tsx b/packages/react/src/internal/components/InputValidation.tsx index 22809a452fa..e013cab6948 100644 --- a/packages/react/src/internal/components/InputValidation.tsx +++ b/packages/react/src/internal/components/InputValidation.tsx @@ -2,7 +2,6 @@ import type {IconProps} from '@primer/octicons-react' import {AlertFillIcon, CheckCircleFillIcon} from '@primer/octicons-react' import type React from 'react' import Text from '../../Text' -import type {SxProp} from '../../sx' import type {FormValidationStatus} from '../../utils/types/FormValidationStatus' import classes from './InputValidation.module.css' import {clsx} from 'clsx' @@ -12,7 +11,7 @@ type Props = { id: string validationStatus?: FormValidationStatus style?: React.CSSProperties -} & SxProp +} const validationIconMap: Record< NonNullable, diff --git a/packages/styled-react/src/components/FormControl.tsx b/packages/styled-react/src/components/FormControl.tsx new file mode 100644 index 00000000000..f70575b7bef --- /dev/null +++ b/packages/styled-react/src/components/FormControl.tsx @@ -0,0 +1,30 @@ +import { + FormControl as PrimerFormControl, + type FormControlProps as PrimerFormControlProps, + type SxProp, +} from '@primer/react' +import {type PropsWithChildren} from 'react' +import styled from 'styled-components' +import {sx} from '../sx' + +type FormControlProps = PropsWithChildren & SxProp + +const FormControlImpl: React.ComponentType = styled(PrimerFormControl).withConfig({ + shouldForwardProp: prop => (prop as keyof FormControlProps) !== 'sx', +})` + ${sx} +` + +const FormControl = Object.assign(FormControlImpl, { + Caption: PrimerFormControl.Caption, + LeadingVisual: PrimerFormControl.LeadingVisual, + Validation: PrimerFormControl.Validation, + Label: PrimerFormControl.Label, +}) as typeof FormControlImpl & { + Caption: typeof PrimerFormControl.Caption + LeadingVisual: typeof PrimerFormControl.LeadingVisual + Validation: typeof PrimerFormControl.Validation + 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 14c29eb1ca9..6d9c4fba9e2 100644 --- a/packages/styled-react/src/index.tsx +++ b/packages/styled-react/src/index.tsx @@ -3,7 +3,6 @@ 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' @@ -38,6 +37,7 @@ 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'