feat: 공통 컴포넌트 추가 생성
This commit is contained in:
77
web-app/app/shared/components/radioGroup/RadioGroup.tsx
Normal file
77
web-app/app/shared/components/radioGroup/RadioGroup.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useId } from 'react';
|
||||
import type { RadioGroupProps as AriaRadioGroupProps, RadioProps as AriaRadioProps } from 'react-aria-components';
|
||||
import { Radio as AriaRadio, RadioGroup as AriaRadioGroup, composeRenderProps } from 'react-aria-components';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { tv } from 'tailwind-variants';
|
||||
|
||||
export type RadioOption = {
|
||||
value: string;
|
||||
label: ReactNode;
|
||||
isDisabled?: boolean;
|
||||
};
|
||||
|
||||
export interface RadioGroupProps extends AriaRadioGroupProps {
|
||||
items: RadioOption[];
|
||||
}
|
||||
|
||||
export const RadioGroup = (props: RadioGroupProps) => {
|
||||
const radioGroupId = useId();
|
||||
const { items, className, value, ...restProps } = props;
|
||||
return (
|
||||
<AriaRadioGroup
|
||||
className={clsx('flex gap-4 data-[orientation=vertical]:flex-col data-[orientation=vertical]:gap-3', className)}
|
||||
value={value === '' ? null : value}
|
||||
{...restProps}
|
||||
>
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<Radio key={`radio_group-${radioGroupId}-${item.value}`} value={item.value} isDisabled={item.isDisabled}>
|
||||
{item.label}
|
||||
</Radio>
|
||||
);
|
||||
})}
|
||||
</AriaRadioGroup>
|
||||
);
|
||||
};
|
||||
|
||||
interface RadioProps extends AriaRadioProps {}
|
||||
|
||||
const radioStyles = tv({
|
||||
base: 'shrink-0 w-4 h-4 box-border rounded-full border-[1.5px] border-dabeeo-gray-be bg-white transition-all',
|
||||
variants: {
|
||||
isSelected: {
|
||||
true: 'border-4 border-primary ',
|
||||
},
|
||||
isFocusVisible: {
|
||||
true: 'ring-2 ring-offset-2 ring-primary',
|
||||
},
|
||||
isInvalid: {
|
||||
true: 'border-dabeeo-red',
|
||||
},
|
||||
isDisabled: {
|
||||
true: 'border-dabeeo-gray-be',
|
||||
},
|
||||
},
|
||||
compoundVariants: [{ isDisabled: true, isSelected: false, className: 'bg-dabeeo-gray-eb' }],
|
||||
});
|
||||
export const Radio = (props: RadioProps) => {
|
||||
const { className, ...restProps } = props;
|
||||
return (
|
||||
<AriaRadio
|
||||
className={clsx(
|
||||
'inline-flex items-center gap-2.5 text-dabeeo-black-22 text-sm font-medium data-disabled:text-dabeeo-gray-be',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{composeRenderProps(props.children, (children, renderProps) => (
|
||||
<>
|
||||
<div className={radioStyles(renderProps)} />
|
||||
{children}
|
||||
</>
|
||||
))}
|
||||
</AriaRadio>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user