UNPKG

@spaced-out/ui-design-system

Version:
95 lines (85 loc) 2.19 kB
// @flow strict import * as React from 'react'; import type {GroupAlign} from '../../types/common'; import classify from '../../utils/classify'; import {BodySmall} from '../Text/Text'; import css from './RadioGroup.module.css'; /** * Note: * Do not wrap Radio in a label. For simplicity's sake, Radio uses an * internal label tag to handle click delegation to the hidden input, and * nesting labels is a bad idea. */ type ClassNames = $ReadOnly<{ wrapper?: string, radioGroup?: string, errorText?: string, }>; export type RadioGroupProps = { align?: GroupAlign, name: string, value?: string, onChange?: (value: string) => mixed, children?: React.Node, classNames?: ClassNames, error?: boolean, errorText?: string, }; export const RadioGroup: React$AbstractComponent< RadioGroupProps, HTMLDivElement, > = React.forwardRef<RadioGroupProps, HTMLDivElement>( ( { align = 'vertical', name, value, onChange, children, classNames, error = false, errorText = '', }: RadioGroupProps, forwardRef, ): React.Node => { const onChangeHandler = (value) => { if (onChange) { onChange(value); } }; const childrenWithProps = React.Children.map(children, (child) => { if (React.isValidElement(child)) { return React.cloneElement(child, { name, selectedValue: value, onChange: onChangeHandler, align, error, }); } return child; }); return ( <div className={classify(css.radioGroupContainer, classNames?.wrapper)}> <div className={classify( { [css.vertical]: align === 'vertical', [css.horizontal]: align === 'horizontal-fixed', [css.horizontalFluid]: align === 'horizontal-fluid', }, classNames?.radioGroup, )} ref={forwardRef} > {childrenWithProps} </div> {error && ( <BodySmall color="danger" className={classNames?.errorText}> {errorText} </BodySmall> )} </div> ); }, );