From 9a9d2209b29fc9552cde49d4fa91e02547794fce Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Tue, 29 Oct 2024 16:28:24 +0000 Subject: [PATCH 1/3] Convert radio to CSS modules Co-authored-by: Josh Black Co-authored-by: Randall Krauskopf Co-authored-by: Hussam Ghazzi --- .../react/src/Radio/Radio.dev.stories.tsx | 18 +++++ packages/react/src/Radio/Radio.module.css | 34 ++++++++ packages/react/src/Radio/Radio.tsx | 77 ++++++++++++------- 3 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 packages/react/src/Radio/Radio.dev.stories.tsx create mode 100644 packages/react/src/Radio/Radio.module.css diff --git a/packages/react/src/Radio/Radio.dev.stories.tsx b/packages/react/src/Radio/Radio.dev.stories.tsx new file mode 100644 index 00000000000..56dcf214241 --- /dev/null +++ b/packages/react/src/Radio/Radio.dev.stories.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import {Box, FormControl, Radio} from '..' + +export default { + title: 'Components/Radio/Dev', + component: Radio, +} + +export const SxProp = () => { + return ( + + + + Label + + + ) +} diff --git a/packages/react/src/Radio/Radio.module.css b/packages/react/src/Radio/Radio.module.css new file mode 100644 index 00000000000..ccfb83ac5e7 --- /dev/null +++ b/packages/react/src/Radio/Radio.module.css @@ -0,0 +1,34 @@ +.Radio { + border-radius: var(--borderRadius-full, 100vh); + transition: + background-color, + border-color 80ms cubic-bezier(0.33, 1, 0.68, 1); /* checked -> unchecked - add 120ms delay to fully see animation-out */ + + &:checked { + /* stylelint-disable-next-line primer/colors */ + background-color: var(--control-checked-fgColor-rest); + + /* using bgColor here to avoid a border change in dark high contrast */ + /* stylelint-disable-next-line primer/colors */ + border-color: var(--control-checked-bgColor-rest); + border-width: var(--borderWidth-thicker); + + &:disabled { + cursor: not-allowed; + /* stylelint-disable-next-line primer/colors */ + background-color: var(--fgColor-muted); + /* stylelint-disable-next-line primer/colors */ + border-color: var(--fgColor-muted); + } + } + + &:focus, + &:focus-within { + @mixin focusOutline 2px; + } + + @media (forced-colors: active) { + background-color: canvastext; + border-color: canvastext; + } +} diff --git a/packages/react/src/Radio/Radio.tsx b/packages/react/src/Radio/Radio.tsx index 4ddcb346d5d..6040ad4fd20 100644 --- a/packages/react/src/Radio/Radio.tsx +++ b/packages/react/src/Radio/Radio.tsx @@ -8,6 +8,11 @@ import {RadioGroupContext} from '../RadioGroup/RadioGroup' import getGlobalFocusStyles from '../internal/utils/getGlobalFocusStyles' import {get} from '../constants' import {sharedCheckboxAndRadioStyles} from '../internal/utils/sharedCheckboxAndRadioStyles' +import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {useFeatureFlag} from '../FeatureFlags' +import {clsx} from 'clsx' +import classes from './Radio.module.css' +import sharedClasses from '../Checkbox/shared.module.css' export type RadioProps = { /** @@ -42,47 +47,63 @@ export type RadioProps = { } & InputHTMLAttributes & SxProp -const StyledRadio = styled.input` - ${sharedCheckboxAndRadioStyles}; - border-radius: var(--borderRadius-full, 100vh); - transition: - background-color, - border-color 80ms cubic-bezier(0.33, 1, 0.68, 1); /* checked -> unchecked - add 120ms delay to fully see animation-out */ +const StyledRadio = toggleStyledComponent( + 'primer_react_css_modules_team', + 'input', + styled.input` + ${sharedCheckboxAndRadioStyles}; + border-radius: var(--borderRadius-full, 100vh); + transition: + background-color, + border-color 80ms cubic-bezier(0.33, 1, 0.68, 1); /* checked -> unchecked - add 120ms delay to fully see animation-out */ - &:checked { - border-width: var(--base-size-4, 4px); - border-color: var( - --control-checked-bgColor-rest, - ${get('colors.accent.fg')} - ); /* using bgColor here to avoid a border change in dark high contrast */ - background-color: var(--control-checked-fgColor-rest, ${get('colors.fg.onEmphasis')}); + &:checked { + border-width: var(--base-size-4, 4px); + border-color: var( + --control-checked-bgColor-rest, + ${get('colors.accent.fg')} + ); /* using bgColor here to avoid a border change in dark high contrast */ + background-color: var(--control-checked-fgColor-rest, ${get('colors.fg.onEmphasis')}); - &:disabled { - cursor: not-allowed; - border-color: ${get('colors.fg.muted')}; - background-color: ${get('colors.fg.muted')}; + &:disabled { + cursor: not-allowed; + border-color: ${get('colors.fg.muted')}; + background-color: ${get('colors.fg.muted')}; + } } - } - ${getGlobalFocusStyles()}; + ${getGlobalFocusStyles()}; - @media (forced-colors: active) { - background-color: canvastext; - border-color: canvastext; - } + @media (forced-colors: active) { + background-color: canvastext; + border-color: canvastext; + } - ${sx} -` + ${sx} + `, +) /** * An accessible, native radio component for selecting one option from a list. */ const Radio = React.forwardRef( ( - {checked, disabled, name: nameProp, onChange, sx: sxProp, required, validationStatus, value, ...rest}: RadioProps, + { + checked, + disabled, + name: nameProp, + onChange, + sx: sxProp, + required, + validationStatus, + value, + className, + ...rest + }: RadioProps, ref, ): ReactElement => { const radioGroupContext = useContext(RadioGroupContext) + const enabled = useFeatureFlag('primer_react_css_modules_team') const handleOnChange: ChangeEventHandler = e => { radioGroupContext?.onChange && radioGroupContext.onChange(e) onChange && onChange(e) @@ -110,6 +131,10 @@ const Radio = React.forwardRef( aria-invalid={validationStatus === 'error' ? 'true' : 'false'} sx={sxProp} onChange={handleOnChange} + className={clsx(className, { + [sharedClasses.Input]: enabled, + [classes.Radio]: enabled, + })} {...rest} /> ) From b6a7bde3c8b05150ce1c26bdd161f0761b845e08 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Tue, 29 Oct 2024 12:22:41 -0700 Subject: [PATCH 2/3] Create fifty-suns-smoke.md --- .changeset/fifty-suns-smoke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fifty-suns-smoke.md diff --git a/.changeset/fifty-suns-smoke.md b/.changeset/fifty-suns-smoke.md new file mode 100644 index 00000000000..749aa264863 --- /dev/null +++ b/.changeset/fifty-suns-smoke.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Convert Radio to css modules behind feature flag From cfbd044491b5da32f8cb802b90ff3a76438c2659 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Wed, 30 Oct 2024 12:07:50 -0700 Subject: [PATCH 3/3] Update CSS selector for checked state --- packages/react/src/Radio/Radio.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/Radio/Radio.module.css b/packages/react/src/Radio/Radio.module.css index ccfb83ac5e7..2032cb8a697 100644 --- a/packages/react/src/Radio/Radio.module.css +++ b/packages/react/src/Radio/Radio.module.css @@ -4,7 +4,7 @@ background-color, border-color 80ms cubic-bezier(0.33, 1, 0.68, 1); /* checked -> unchecked - add 120ms delay to fully see animation-out */ - &:checked { + &:where(:checked) { /* stylelint-disable-next-line primer/colors */ background-color: var(--control-checked-fgColor-rest);