Skip to content

Commit

Permalink
Convert radio to CSS modules
Browse files Browse the repository at this point in the history
Co-authored-by: Josh Black <[email protected]>
Co-authored-by: Randall Krauskopf <[email protected]>
Co-authored-by: Hussam Ghazzi <[email protected]>
  • Loading branch information
4 people committed Oct 29, 2024
1 parent 6713e72 commit 9a9d220
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 26 deletions.
18 changes: 18 additions & 0 deletions packages/react/src/Radio/Radio.dev.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Box as="form">
<FormControl>
<Radio name="default-radio-name" value="default" sx={{backgroundColor: 'red'}} />
<FormControl.Label>Label</FormControl.Label>
</FormControl>
</Box>
)
}
34 changes: 34 additions & 0 deletions packages/react/src/Radio/Radio.module.css
Original file line number Diff line number Diff line change
@@ -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;
}
}
77 changes: 51 additions & 26 deletions packages/react/src/Radio/Radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
/**
Expand Down Expand Up @@ -42,47 +47,63 @@ export type RadioProps = {
} & InputHTMLAttributes<HTMLInputElement> &
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<HTMLInputElement, RadioProps>(
(
{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<HTMLInputElement> = e => {
radioGroupContext?.onChange && radioGroupContext.onChange(e)
onChange && onChange(e)
Expand Down Expand Up @@ -110,6 +131,10 @@ const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
aria-invalid={validationStatus === 'error' ? 'true' : 'false'}
sx={sxProp}
onChange={handleOnChange}
className={clsx(className, {
[sharedClasses.Input]: enabled,
[classes.Radio]: enabled,
})}
{...rest}
/>
)
Expand Down

0 comments on commit 9a9d220

Please sign in to comment.