diff --git a/.changeset/hungry-pumas-poke.md b/.changeset/hungry-pumas-poke.md new file mode 100644 index 00000000000..1a82f7332bb --- /dev/null +++ b/.changeset/hungry-pumas-poke.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Removes feature flag for FormControl diff --git a/packages/react/src/FormControl/FormControl.tsx b/packages/react/src/FormControl/FormControl.tsx index e66af31eb61..91d6b9dc0e5 100644 --- a/packages/react/src/FormControl/FormControl.tsx +++ b/packages/react/src/FormControl/FormControl.tsx @@ -20,12 +20,8 @@ import FormControlLeadingVisual from './FormControlLeadingVisual' import FormControlValidation from './_FormControlValidation' import {FormControlContextProvider} from './_FormControlContext' import {warning} from '../utils/warning' -import styled from 'styled-components' -import sx from '../sx' -import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' -import {cssModulesFlag} from './feature-flags' -import {useFeatureFlag} from '../FeatureFlags' import classes from './FormControl.module.css' +import {defaultSxProp} from '../utils/defaultSxProp' export type FormControlProps = { children?: React.ReactNode @@ -51,7 +47,6 @@ export type FormControlProps = { const FormControl = React.forwardRef( ({children, disabled: disabledProp, layout = 'vertical', id: idProp, required, sx, className}, ref) => { - const enabled = useFeatureFlag(cssModulesFlag) const [slots, childrenWithoutSlots] = useSlots(children, { caption: FormControlCaption, label: FormControlLabel, @@ -122,6 +117,46 @@ const FormControl = React.forwardRef( } const isLabelHidden = slots.label?.props.visuallyHidden + const InputChildren = ( + <> +
+ {React.isValidElement(InputComponent) + ? React.cloneElement( + InputComponent as React.ReactElement<{ + id: string + disabled: boolean + required: boolean + ['aria-describedby']: string + }>, + { + id, + disabled, + // allow checkboxes to be required + required: required && !isRadioInput, + ['aria-describedby']: captionId as string, + }, + ) + : null} + {childrenWithoutSlots.filter( + child => + React.isValidElement(child) && ![Checkbox, Radio].some(inputComponent => child.type === inputComponent), + )} +
+ {slots.leadingVisual ? ( +
+ {slots.leadingVisual} +
+ ) : null} +
+ {slots.label} + {slots.caption} +
+ + ) return ( ( }} > {isChoiceInput || layout === 'horizontal' ? ( - - - {React.isValidElement(InputComponent) - ? React.cloneElement( - InputComponent as React.ReactElement<{ - id: string - disabled: boolean - required: boolean - ['aria-describedby']: string - }>, - { - id, - disabled, - // allow checkboxes to be required - required: required && !isRadioInput, - ['aria-describedby']: captionId as string, - }, - ) - : null} - {childrenWithoutSlots.filter( - child => - React.isValidElement(child) && - ![Checkbox, Radio].some(inputComponent => child.type === inputComponent), - )} - - {slots.leadingVisual ? ( - - {slots.leadingVisual} - - ) : null} - - {slots.label} - {slots.caption} - - + sx !== defaultSxProp ? ( + + {InputChildren} + + ) : ( +
+ {InputChildren} +
+ ) ) : ( ( display="flex" flexDirection="column" alignItems="flex-start" - sx={ - enabled - ? sx - : {...(isLabelHidden ? {'> *:not(label) + *': {marginTop: 1}} : {'> * + *': {marginTop: 1}}), ...sx} - } - className={clsx(className, { - [classes.ControlVerticalLayout]: enabled, - })} + sx={sx} + className={clsx(className, classes.ControlVerticalLayout)} > {slots.label} {React.isValidElement(InputComponent) && @@ -229,69 +228,6 @@ const FormControl = React.forwardRef( }, ) -const StyledHorizontalLayout = toggleStyledComponent( - cssModulesFlag, - 'div', - styled.div` - display: flex; - - &:where([data-has-leading-visual]) { - align-items: center; - } - - ${sx} - `, -) - -const StyledChoiceInputs = toggleStyledComponent( - cssModulesFlag, - 'div', - styled.div` - > input { - margin-left: 0; - margin-right: 0; - } - `, -) - -const StyledLabelContainer = toggleStyledComponent( - cssModulesFlag, - 'div', - styled.div` - > * { - padding-left: var(--stack-gap-condensed); - } - - > label { - font-weight: var(--base-text-weight-normal); - } - `, -) - -const StyledLeadingVisual = toggleStyledComponent( - cssModulesFlag, - 'div', - styled.div` - color: var(--fgColor-default); - margin-left: var(--base-size-8); - - &:where([data-disabled]) { - color: var(--fgColor-muted); - } - - > * { - fill: currentColor; - min-width: var(--text-body-size-large); - min-height: var(--text-body-size-large); - } - - > *:where([data-has-caption]) { - min-width: var(--base-size-24); - min-height: var(--base-size-24); - } - `, -) - export default Object.assign(FormControl, { Caption: FormControlCaption, Label: FormControlLabel, diff --git a/packages/react/src/FormControl/FormControlCaption.tsx b/packages/react/src/FormControl/FormControlCaption.tsx index fa6e36034b6..c9c29e6c1cd 100644 --- a/packages/react/src/FormControl/FormControlCaption.tsx +++ b/packages/react/src/FormControl/FormControlCaption.tsx @@ -1,14 +1,10 @@ import {clsx} from 'clsx' import React from 'react' -import styled from 'styled-components' -import {cssModulesFlag} from './feature-flags' -import {useFeatureFlag} from '../FeatureFlags' import Text from '../Text' -import sx from '../sx' import type {SxProp} from '../sx' import classes from './FormControlCaption.module.css' import {useFormControlContext} from './_FormControlContext' -import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {toggleSxComponent} from '../internal/utils/toggleSxComponent' type FormControlCaptionProps = React.PropsWithChildren< { @@ -18,36 +14,18 @@ type FormControlCaptionProps = React.PropsWithChildren< > function FormControlCaption({id, children, sx, className}: FormControlCaptionProps) { - const enabled = useFeatureFlag(cssModulesFlag) const {captionId, disabled} = useFormControlContext() + const Caption = toggleSxComponent(sx, Text) as React.ComponentType + return ( - {children} - + ) } -const StyledCaption = toggleStyledComponent( - cssModulesFlag, - Text, - styled(Text)` - color: var(--fgColor-muted); - display: block; - font-size: var(--text-body-size-small); - - &:where([data-control-disabled]) { - color: var(--control-fgColor-disabled); - } - - ${sx} - `, -) - export {FormControlCaption} diff --git a/packages/react/src/FormControl/feature-flags.ts b/packages/react/src/FormControl/feature-flags.ts deleted file mode 100644 index 32e2cdb02ce..00000000000 --- a/packages/react/src/FormControl/feature-flags.ts +++ /dev/null @@ -1 +0,0 @@ -export const cssModulesFlag = 'primer_react_css_modules_ga' diff --git a/packages/react/src/internal/components/InputLabel.tsx b/packages/react/src/internal/components/InputLabel.tsx index 54002f3a3fb..e4b77f039f4 100644 --- a/packages/react/src/internal/components/InputLabel.tsx +++ b/packages/react/src/internal/components/InputLabel.tsx @@ -1,11 +1,8 @@ import {clsx} from 'clsx' import React from 'react' -import styled from 'styled-components' -import sx, {type SxProp} from '../../sx' -import {cssModulesFlag} from '../../FormControl/feature-flags' -import {useFeatureFlag} from '../../FeatureFlags' +import {type SxProp} from '../../sx' import classes from './InputLabel.module.css' -import {toggleStyledComponent} from '../utils/toggleStyledComponent' +import {toggleSxComponent} from '../utils/toggleSxComponent' type BaseProps = SxProp & { disabled?: boolean @@ -43,76 +40,26 @@ function InputLabel({ className, ...props }: Props) { - const enabled = useFeatureFlag(cssModulesFlag) + const Label = toggleSxComponent({sx}, as) as React.ComponentType return ( - {required || requiredText ? ( - + {children} {requiredText ?? '*'} - + ) : ( children )} - + ) } -const StyledLabel = toggleStyledComponent( - cssModulesFlag, - 'label', - styled.label` - align-self: flex-start; - display: block; - color: var(--fgColor-default); - cursor: pointer; - font-weight: 600; - font-size: var(--text-body-size-medium); - - &: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} - `, -) - -const StyledRequiredText = toggleStyledComponent( - cssModulesFlag, - 'span', - styled.span` - display: flex; - column-gap: var(--base-size-4); - `, -) - export {InputLabel} diff --git a/packages/react/src/internal/components/InputValidation.tsx b/packages/react/src/internal/components/InputValidation.tsx index d7224c429fa..05542c65571 100644 --- a/packages/react/src/internal/components/InputValidation.tsx +++ b/packages/react/src/internal/components/InputValidation.tsx @@ -2,14 +2,11 @@ import type {IconProps} from '@primer/octicons-react' import {AlertFillIcon, CheckCircleFillIcon} from '@primer/octicons-react' import {clsx} from 'clsx' import React from 'react' -import styled from 'styled-components' import Text from '../../Text' -import sx from '../../sx' import type {SxProp} from '../../sx' -import {cssModulesFlag} from '../../FormControl/feature-flags' import type {FormValidationStatus} from '../../utils/types/FormValidationStatus' -import {useFeatureFlag} from '../../FeatureFlags' import classes from './InputValidation.module.css' +import {defaultSxProp} from '../../utils/defaultSxProp' type Props = { id: string @@ -25,7 +22,6 @@ const validationIconMap: Record< } const InputValidation: React.FC> = ({children, id, validationStatus, sx}) => { - const enabled = useFeatureFlag(cssModulesFlag) const IconComponent = validationStatus ? validationIconMap[validationStatus] : undefined // TODO: use `text-caption-lineHeight` token as a custom property when it's available @@ -35,19 +31,15 @@ const InputValidation: React.FC> = ({children, id const iconBoxMinHeight = iconSize * captionLineHeight return ( - {IconComponent ? ( - + ) : null} - {children} - - + + ) } -const StyledInputValidation = styled(Text)` - color: var(--inputValidation-fgColor); - display: flex; - font-size: var(--text-body-size-small); - font-weight: 600; - - & :where(a) { - color: currentColor; - text-dectoration: underline; - } - - &:where([data-validation-status='success']) { - --inputValidation-fgColor: var(--fgColor-success); - } - - &:where([data-validation-status='error']) { - --inputValidation-fgColor: var(--fgColor-danger); - } - - ${sx} -` - -const StyledValidationIcon = styled.span` - align-items: center; - display: flex; - margin-inline-end: var(--base-size-4); - min-height: var(--inputValidation-iconSize); -` - -const StyledValidationText = styled.span` - line-height: var(--inputValidation-lineHeight); -` - export default InputValidation diff --git a/packages/react/src/internal/utils/toggleSxComponent.tsx b/packages/react/src/internal/utils/toggleSxComponent.tsx index 44904262ee7..aba06239780 100644 --- a/packages/react/src/internal/utils/toggleSxComponent.tsx +++ b/packages/react/src/internal/utils/toggleSxComponent.tsx @@ -17,7 +17,7 @@ type CSSModulesProps = { * @param defaultAs - the default component to use when `as` is not provided */ export function toggleSxComponent( - sx: BetterSystemStyleObject, + sx: BetterSystemStyleObject | undefined, // eslint-disable-next-line @typescript-eslint/no-explicit-any defaultAs: string | React.ComponentType, ) {