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({
|
export const radioTheme = tv({
|
||||||
slots: {
|
slots: {
|
||||||
root: ['flex', 'gap-3', 'flex-wrap'],
|
root: ['flex', 'gap-3'],
|
||||||
wrapper: ['flex', 'items-center', 'gap-2', 'group'],
|
wrapper: ['flex', 'items-center', 'gap-2', 'group'],
|
||||||
label: ['text-sm', 'tracking-[-0.006em]', 'text-elements-high-em'],
|
label: ['text-sm', 'tracking-[-0.006em]', 'text-elements-high-em'],
|
||||||
radio: [
|
radio: [
|
||||||
@ -39,15 +39,34 @@ export const radioTheme = tv({
|
|||||||
'after:data-[state=checked]:group-hover:bg-elements-on-primary',
|
'after:data-[state=checked]:group-hover:bg-elements-on-primary',
|
||||||
'after:data-[state=checked]:group-focus-visible:bg-elements-on-primary',
|
'after:data-[state=checked]:group-focus-visible:bg-elements-on-primary',
|
||||||
],
|
],
|
||||||
|
icon: ['w-[18px]', 'h-[18px]'],
|
||||||
},
|
},
|
||||||
variants: {
|
variants: {
|
||||||
orientation: {
|
orientation: {
|
||||||
vertical: { root: ['flex-col'] },
|
vertical: { root: ['flex-col'] },
|
||||||
horizontal: { root: ['flex-row'] },
|
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: {
|
defaultVariants: {
|
||||||
orientation: 'vertical',
|
orientation: 'vertical',
|
||||||
|
variant: 'unstyled',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -49,14 +49,15 @@ export const Radio = ({
|
|||||||
className,
|
className,
|
||||||
options,
|
options,
|
||||||
orientation,
|
orientation,
|
||||||
|
variant,
|
||||||
...props
|
...props
|
||||||
}: RadioProps) => {
|
}: RadioProps) => {
|
||||||
const { root } = radioTheme({ orientation });
|
const { root } = radioTheme({ orientation, variant });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RadixRoot {...props} className={root({ className })}>
|
<RadixRoot {...props} className={root({ className })}>
|
||||||
{options.map((option) => (
|
{options.map((option) => (
|
||||||
<RadioItem key={option.value} {...option} />
|
<RadioItem key={option.value} variant={variant} {...option} />
|
||||||
))}
|
))}
|
||||||
</RadixRoot>
|
</RadixRoot>
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import React, { ComponentPropsWithoutRef } from 'react';
|
import React, { ReactNode, ComponentPropsWithoutRef } from 'react';
|
||||||
import {
|
import {
|
||||||
Item as RadixRadio,
|
Item as RadixRadio,
|
||||||
Indicator as RadixIndicator,
|
Indicator as RadixIndicator,
|
||||||
RadioGroupItemProps,
|
RadioGroupItemProps,
|
||||||
RadioGroupIndicatorProps,
|
RadioGroupIndicatorProps,
|
||||||
} from '@radix-ui/react-radio-group';
|
} 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.
|
* The wrapper props of the radio item.
|
||||||
* You can use this prop to customize the wrapper props.
|
* 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.
|
* The id of the radio item.
|
||||||
*/
|
*/
|
||||||
id?: string;
|
id?: string;
|
||||||
|
/**
|
||||||
|
* The left icon of the radio item.
|
||||||
|
*/
|
||||||
|
leftIcon?: ReactNode;
|
||||||
/**
|
/**
|
||||||
* The label of the radio item.
|
* The label of the radio item.
|
||||||
*/
|
*/
|
||||||
@ -41,18 +48,26 @@ export const RadioItem = ({
|
|||||||
wrapperProps,
|
wrapperProps,
|
||||||
labelProps,
|
labelProps,
|
||||||
indicatorProps,
|
indicatorProps,
|
||||||
|
leftIcon,
|
||||||
label,
|
label,
|
||||||
id,
|
id,
|
||||||
|
variant,
|
||||||
...props
|
...props
|
||||||
}: RadioItemProps) => {
|
}: 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
|
// 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 kebabCaseLabel = label?.toLowerCase().replace(/\s+/g, '-');
|
||||||
const componentId = id ?? kebabCaseLabel;
|
const componentId = id ?? kebabCaseLabel;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={wrapper({ className: wrapperProps?.className })}>
|
<label className={wrapper({ className: wrapperProps?.className })}>
|
||||||
<RadixRadio {...props} className={radio({ className })} id={componentId}>
|
<RadixRadio {...props} className={radio({ className })} id={componentId}>
|
||||||
<RadixIndicator
|
<RadixIndicator
|
||||||
forceMount
|
forceMount
|
||||||
@ -60,15 +75,17 @@ export const RadioItem = ({
|
|||||||
className={indicator({ className: indicatorProps?.className })}
|
className={indicator({ className: indicatorProps?.className })}
|
||||||
/>
|
/>
|
||||||
</RadixRadio>
|
</RadixRadio>
|
||||||
|
{leftIcon &&
|
||||||
|
cloneIcon(leftIcon, { className: icon(), 'aria-hidden': true })}
|
||||||
{label && (
|
{label && (
|
||||||
<label
|
<label
|
||||||
{...labelProps}
|
{...labelProps}
|
||||||
className={labelClass({ className: labelProps?.className })}
|
|
||||||
htmlFor={componentId}
|
htmlFor={componentId}
|
||||||
|
className={labelClass({ className: labelProps?.className })}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
</div>
|
</label>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user