From a9fab150de2a33552d932c3e91f13d819198d3b1 Mon Sep 17 00:00:00 2001 From: Kelly Phan Date: Mon, 16 Dec 2024 16:34:39 +0100 Subject: [PATCH] refactor: migrate radio to tailwind (#1923) * refactor: migrate radio to tailwind * refactor: extract icon * fix: improve semantic by using label instead of div --- src/components/form/Radio/Radio.tsx | 112 ++++------------------- src/components/form/Radio/RadioField.tsx | 2 +- src/components/form/Radio/RadioIcon.tsx | 76 +++++++++++++++ src/public/icons/forms/radio-checked.svg | 5 - src/public/icons/forms/radio.svg | 4 - 5 files changed, 93 insertions(+), 106 deletions(-) create mode 100644 src/components/form/Radio/RadioIcon.tsx delete mode 100644 src/public/icons/forms/radio-checked.svg delete mode 100644 src/public/icons/forms/radio.svg diff --git a/src/components/form/Radio/Radio.tsx b/src/components/form/Radio/Radio.tsx index 68bd920ea..6c53267bb 100644 --- a/src/components/form/Radio/Radio.tsx +++ b/src/components/form/Radio/Radio.tsx @@ -1,13 +1,10 @@ -/* eslint-disable tailwindcss/no-custom-classname */ -import { cx } from 'class-variance-authority' import { isBoolean } from 'lodash' import { forwardRef, ReactNode, useId, useRef, useState } from 'react' -import styled from 'styled-components' import { Typography, TypographyProps } from '~/components/designSystem' -import RadioCheckedIcon from '~/public/icons/forms/radio-checked.svg' -import RadioIcon from '~/public/icons/forms/radio.svg' -import { theme } from '~/styles' +import { tw } from '~/styles/utils' + +import { RadioIcon } from './RadioIcon' export interface RadioProps { name?: string @@ -20,7 +17,7 @@ export interface RadioProps { onChange?: (value: string | number | boolean) => void } -export const Radio = forwardRef( +export const Radio = forwardRef( ( { name, checked, label, labelVariant, sublabel, disabled, value, onChange }: RadioProps, ref, @@ -31,39 +28,33 @@ export const Radio = forwardRef( const [focused, setFocused] = useState(false) return ( - inputRef.current?.click()} - className={cx({ - 'radio--disabled': disabled, - 'radio--focused': focused, - 'radio--checked': checked, - 'radio--unchecked': !checked, - })} + htmlFor={componentId} + className={tw('flex w-full items-start', !disabled && 'group/radio-icon cursor-pointer')} > - +
onChange && onChange(value)} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} + className="absolute m-0 size-0 p-0 opacity-0" /> - {checked ? ( - - ) : ( - - )} - - + +
+
+ ) }, ) Radio.displayName = 'Radio' - -const Container = styled.div` - width: 100%; - display: flex; - align-items: flex-start; - cursor: pointer; - - > * { - cursor: pointer; - } - - &.radio--checked { - .radio-coloured, - .radio-checked-coloured { - fill: ${theme.palette.primary[700]}; - } - } - - &.radio--disabled { - > * { - cursor: default; - } - .radio-coloured, - .radio-checked-coloured { - fill: ${theme.palette.grey[400]}; - } - } - - &.radio--focused .radio-icon { - box-shadow: 0px 0px 0px 4px ${theme.palette.primary[200]}; - border-radius: 50%; - } - - &:hover:not(.radio--disabled) { - &.radio--checked .radio-inner { - fill: ${theme.palette.primary[100]}; - } - &.radio--unchecked .radio-inner { - fill: ${theme.palette.grey[200]}; - } - } - - &:active:not(.radio--disabled) { - &.radio--checked .radio-inner { - fill: ${theme.palette.primary[200]}; - } - &.radio--unchecked .radio-inner { - fill: ${theme.palette.grey[300]}; - } - } -` - -const RadioContainer = styled.div` - margin-right: ${theme.spacing(3)}; - display: flex; - align-items: flex-start; - padding-top: 4px; - - input { - opacity: 0; - position: absolute; - width: 0; - height: 0; - margin: 0; - padding: 0; - } -` - -const RadioLabelWrapper = styled.div` - width: 100%; -` diff --git a/src/components/form/Radio/RadioField.tsx b/src/components/form/Radio/RadioField.tsx index 518c7610b..141b92667 100644 --- a/src/components/form/Radio/RadioField.tsx +++ b/src/components/form/Radio/RadioField.tsx @@ -12,7 +12,7 @@ export interface RadioFieldProps extends Omit { } export const RadioField = memo( - forwardRef( + forwardRef( ({ name, value, formikProps, ...props }: RadioFieldProps, ref) => { const { values, setFieldValue } = formikProps diff --git a/src/components/form/Radio/RadioIcon.tsx b/src/components/form/Radio/RadioIcon.tsx new file mode 100644 index 000000000..d95abc35f --- /dev/null +++ b/src/components/form/Radio/RadioIcon.tsx @@ -0,0 +1,76 @@ +import { FC } from 'react' + +import { tw } from '~/styles/utils' + +interface RadioIconProps { + focused?: boolean + disabled?: boolean +} + +const RadioCheckedIcon: FC = ({ focused, disabled }) => { + return ( + + + + + + ) +} + +const RadioUncheckedIcon: FC = ({ focused, disabled }) => { + return ( + + + + + ) +} + +export const RadioIcon: FC<{ checked: boolean } & RadioIconProps> = ({ + checked, + ...radioIconProps +}) => { + return checked ? ( + + ) : ( + + ) +} diff --git a/src/public/icons/forms/radio-checked.svg b/src/public/icons/forms/radio-checked.svg deleted file mode 100644 index f309f1e21..000000000 --- a/src/public/icons/forms/radio-checked.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/public/icons/forms/radio.svg b/src/public/icons/forms/radio.svg deleted file mode 100644 index f2b1b51ae..000000000 --- a/src/public/icons/forms/radio.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -