diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-30 19:44:37 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-31 23:15:11 +0200 |
| commit | 994ad1bec193b2d1a6e0d38d6ef3f3d2bd66c3ea (patch) | |
| tree | 53df625928d50ef11ceca6b4d0937d433b576aec /src/components/molecules/forms/radio-group.tsx | |
| parent | ae384aec5084b9fb9f02166890686a37d1260ef2 (diff) | |
chore: add a RadioGroup component
Diffstat (limited to 'src/components/molecules/forms/radio-group.tsx')
| -rw-r--r-- | src/components/molecules/forms/radio-group.tsx | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/components/molecules/forms/radio-group.tsx b/src/components/molecules/forms/radio-group.tsx new file mode 100644 index 0000000..68a8adf --- /dev/null +++ b/src/components/molecules/forms/radio-group.tsx @@ -0,0 +1,89 @@ +import Fieldset, { type FieldsetProps } from '@components/atoms/forms/fieldset'; +import { ChangeEvent, FC, useState } from 'react'; +import LabelledBooleanField, { + type LabelledBooleanFieldProps, +} from './labelled-boolean-field'; +import styles from './radio-group.module.scss'; + +export type RadioGroupOption = Pick< + LabelledBooleanFieldProps, + 'id' | 'label' | 'name' | 'value' +>; + +export type RadioGroupProps = Pick< + FieldsetProps, + 'className' | 'legend' | 'legendClassName' +> & + Pick<LabelledBooleanFieldProps, 'labelPosition' | 'labelSize'> & { + /** + * The default option value. + */ + initialChoice: string; + /** + * The legend position. Default: inline. + */ + legendPosition?: FieldsetProps['legendPosition']; + /** + * The options. + */ + options: RadioGroupOption[]; + }; + +/** + * RadioGroup component + * + * Render a group of labelled radio buttons. + */ +const RadioGroup: FC<RadioGroupProps> = ({ + className, + initialChoice, + labelPosition, + labelSize, + legendPosition = 'inline', + options, + ...props +}) => { + const [selectedChoice, setSelectedChoice] = useState<string>(initialChoice); + const wrapperModifier = `wrapper--${legendPosition}`; + + /** + * Update the selected choice based on the change event target. + * + * @param {ChangeEvent<HTMLInputElement>} e - The change event. + */ + const updateChoice = (e: ChangeEvent<HTMLInputElement>) => { + setSelectedChoice(e.target.value); + }; + + /** + * Retrieve an array of radio buttons. + * + * @returns {JSX.Element[]} The radio buttons. + */ + const getOptions = (): JSX.Element[] => { + return options.map((option) => ( + <LabelledBooleanField + key={option.id} + checked={selectedChoice === option.value} + className={styles.option} + labelPosition={labelPosition} + labelSize={labelSize} + onChange={updateChoice} + type="radio" + {...option} + /> + )); + }; + + return ( + <Fieldset + className={`${styles.wrapper} ${styles[wrapperModifier]} ${className}`} + legendPosition={legendPosition} + {...props} + > + {getOptions()} + </Fieldset> + ); +}; + +export default RadioGroup; |
