feat: 공통 컴포넌트 추가 생성

This commit is contained in:
2026-04-13 15:27:25 +09:00
parent 01c3590682
commit 52f8c30b2e
14 changed files with 500 additions and 1 deletions

View 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>
);
};