forked from cerc-io/snowballtools-base
⚡️ feat: implement card style for radio
This commit is contained in:
parent
d9392c095d
commit
a8ad6c6eec
@ -2,7 +2,7 @@ import { VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
export const radioTheme = tv({
|
||||
slots: {
|
||||
root: ['flex', 'gap-3', 'flex-wrap'],
|
||||
root: ['flex', 'gap-3'],
|
||||
wrapper: ['flex', 'items-center', 'gap-2', 'group'],
|
||||
label: ['text-sm', 'tracking-[-0.006em]', 'text-elements-high-em'],
|
||||
radio: [
|
||||
@ -39,15 +39,34 @@ export const radioTheme = tv({
|
||||
'after:data-[state=checked]:group-hover:bg-elements-on-primary',
|
||||
'after:data-[state=checked]:group-focus-visible:bg-elements-on-primary',
|
||||
],
|
||||
icon: ['w-[18px]', 'h-[18px]'],
|
||||
},
|
||||
variants: {
|
||||
orientation: {
|
||||
vertical: { root: ['flex-col'] },
|
||||
horizontal: { root: ['flex-row'] },
|
||||
},
|
||||
variant: {
|
||||
unstyled: {},
|
||||
card: {
|
||||
wrapper: [
|
||||
'px-4',
|
||||
'py-3',
|
||||
'rounded-lg',
|
||||
'border',
|
||||
'border-border-interactive',
|
||||
'bg-controls-tertiary',
|
||||
'shadow-button',
|
||||
'w-full',
|
||||
'cursor-pointer',
|
||||
],
|
||||
label: ['select-none', 'cursor-pointer'],
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
orientation: 'vertical',
|
||||
variant: 'unstyled',
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -49,14 +49,15 @@ export const Radio = ({
|
||||
className,
|
||||
options,
|
||||
orientation,
|
||||
variant,
|
||||
...props
|
||||
}: RadioProps) => {
|
||||
const { root } = radioTheme({ orientation });
|
||||
const { root } = radioTheme({ orientation, variant });
|
||||
|
||||
return (
|
||||
<RadixRoot {...props} className={root({ className })}>
|
||||
{options.map((option) => (
|
||||
<RadioItem key={option.value} {...option} />
|
||||
<RadioItem key={option.value} variant={variant} {...option} />
|
||||
))}
|
||||
</RadixRoot>
|
||||
);
|
||||
|
@ -1,13 +1,16 @@
|
||||
import React, { ComponentPropsWithoutRef } from 'react';
|
||||
import React, { ReactNode, ComponentPropsWithoutRef } from 'react';
|
||||
import {
|
||||
Item as RadixRadio,
|
||||
Indicator as RadixIndicator,
|
||||
RadioGroupItemProps,
|
||||
RadioGroupIndicatorProps,
|
||||
} from '@radix-ui/react-radio-group';
|
||||
import { radioTheme } from './Radio.theme';
|
||||
import { RadioTheme, radioTheme } from './Radio.theme';
|
||||
import { cloneIcon } from 'utils/cloneIcon';
|
||||
|
||||
export interface RadioItemProps extends RadioGroupItemProps {
|
||||
export interface RadioItemProps
|
||||
extends RadioGroupItemProps,
|
||||
Pick<RadioTheme, 'variant'> {
|
||||
/**
|
||||
* The wrapper props of the radio item.
|
||||
* You can use this prop to customize the wrapper props.
|
||||
@ -27,6 +30,10 @@ export interface RadioItemProps extends RadioGroupItemProps {
|
||||
* The id of the radio item.
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* The left icon of the radio item.
|
||||
*/
|
||||
leftIcon?: ReactNode;
|
||||
/**
|
||||
* The label of the radio item.
|
||||
*/
|
||||
@ -41,18 +48,26 @@ export const RadioItem = ({
|
||||
wrapperProps,
|
||||
labelProps,
|
||||
indicatorProps,
|
||||
leftIcon,
|
||||
label,
|
||||
id,
|
||||
variant,
|
||||
...props
|
||||
}: RadioItemProps) => {
|
||||
const { wrapper, label: labelClass, radio, indicator } = radioTheme();
|
||||
const {
|
||||
wrapper,
|
||||
label: labelClass,
|
||||
radio,
|
||||
indicator,
|
||||
icon,
|
||||
} = radioTheme({ variant });
|
||||
|
||||
// Generate a unique id for the radio item from the label if the id is not provided
|
||||
const kebabCaseLabel = label?.toLowerCase().replace(/\s+/g, '-');
|
||||
const componentId = id ?? kebabCaseLabel;
|
||||
|
||||
return (
|
||||
<div className={wrapper({ className: wrapperProps?.className })}>
|
||||
<label className={wrapper({ className: wrapperProps?.className })}>
|
||||
<RadixRadio {...props} className={radio({ className })} id={componentId}>
|
||||
<RadixIndicator
|
||||
forceMount
|
||||
@ -60,15 +75,17 @@ export const RadioItem = ({
|
||||
className={indicator({ className: indicatorProps?.className })}
|
||||
/>
|
||||
</RadixRadio>
|
||||
{leftIcon &&
|
||||
cloneIcon(leftIcon, { className: icon(), 'aria-hidden': true })}
|
||||
{label && (
|
||||
<label
|
||||
{...labelProps}
|
||||
className={labelClass({ className: labelProps?.className })}
|
||||
htmlFor={componentId}
|
||||
className={labelClass({ className: labelProps?.className })}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user