123 lines
4.0 KiB
TypeScript
123 lines
4.0 KiB
TypeScript
import { cva, type VariantProps } from 'class-variance-authority';
|
|
import { PropsWithChildren } from 'react';
|
|
|
|
import { AutomationTestingProps } from '@/types';
|
|
|
|
import { Icon, IconProps } from '@@/Icon';
|
|
|
|
const badge = cva(
|
|
'inline-flex w-fit items-center gap-1 font-medium [&>a]:hover:text-inherit [&>a]:text-inherit',
|
|
{
|
|
variants: {
|
|
type: {
|
|
success:
|
|
'bg-success-2 text-success-9 th-dark:bg-success-10 th-dark:text-success-3 th-highcontrast:bg-success-10 th-highcontrast:text-success-3',
|
|
warn: 'bg-warning-2 text-warning-9 th-dark:bg-warning-10 th-dark:text-warning-3 th-highcontrast:bg-warning-10 th-highcontrast:text-warning-3',
|
|
danger:
|
|
'bg-error-2 text-error-9 th-dark:bg-error-10 th-dark:text-error-3 th-highcontrast:bg-error-10 th-highcontrast:text-error-3',
|
|
info: 'bg-blue-2 text-blue-9 th-dark:bg-blue-10 th-dark:text-blue-3 th-highcontrast:bg-blue-10 th-highcontrast:text-blue-3',
|
|
// the secondary classes are a bit darker in light mode and a bit lighter in dark mode
|
|
successSecondary:
|
|
'bg-success-3 text-success-9 th-dark:bg-success-9 th-dark:text-success-3 th-highcontrast:bg-success-9 th-highcontrast:text-success-3',
|
|
warnSecondary:
|
|
'bg-warning-3 text-warning-9 th-dark:bg-warning-9 th-dark:text-warning-3 th-highcontrast:bg-warning-9 th-highcontrast:text-warning-3',
|
|
dangerSecondary:
|
|
'bg-error-3 text-error-9 th-dark:bg-error-9 th-dark:text-error-3 th-highcontrast:bg-error-9 th-highcontrast:text-error-3',
|
|
infoSecondary:
|
|
'bg-blue-3 text-blue-9 th-dark:bg-blue-9 th-dark:text-blue-3 th-highcontrast:bg-blue-9 th-highcontrast:text-blue-3',
|
|
muted:
|
|
'bg-gray-3 text-gray-9 th-dark:bg-gray-9 th-dark:text-gray-3 th-highcontrast:bg-gray-9 th-highcontrast:text-gray-3',
|
|
accent:
|
|
'bg-indigo-2 text-indigo-9 th-dark:bg-indigo-10 th-dark:text-indigo-3 th-highcontrast:bg-indigo-10 th-highcontrast:text-indigo-3',
|
|
custom: '',
|
|
},
|
|
shape: {
|
|
pill: 'rounded-full',
|
|
rect: 'rounded',
|
|
},
|
|
size: {
|
|
sm: 'px-1.5 py-px text-[10px]',
|
|
md: '!text-xs px-2 py-0.5',
|
|
},
|
|
bordered: {
|
|
true: '!border border-solid th-highcontrast:border-white',
|
|
},
|
|
},
|
|
compoundVariants: [
|
|
{
|
|
type: ['success', 'successSecondary'],
|
|
bordered: true,
|
|
className: 'border-success-4 th-dark:border-success-8',
|
|
},
|
|
{
|
|
type: ['warn', 'warnSecondary'],
|
|
bordered: true,
|
|
className: 'border-warning-4 th-dark:border-warning-8',
|
|
},
|
|
{
|
|
type: ['danger', 'dangerSecondary'],
|
|
bordered: true,
|
|
className: 'border-error-4 th-dark:border-error-8',
|
|
},
|
|
{
|
|
type: ['info', 'infoSecondary'],
|
|
bordered: true,
|
|
className: 'border-blue-4 th-dark:border-blue-8',
|
|
},
|
|
{
|
|
type: 'muted',
|
|
bordered: true,
|
|
className: 'border-gray-4 th-dark:border-gray-8',
|
|
},
|
|
{
|
|
type: 'accent',
|
|
bordered: true,
|
|
className: 'border-indigo-4 th-dark:border-indigo-8',
|
|
},
|
|
],
|
|
defaultVariants: {
|
|
type: 'info',
|
|
shape: 'pill',
|
|
size: 'md',
|
|
},
|
|
}
|
|
);
|
|
|
|
export type BadgeType = NonNullable<
|
|
Exclude<VariantProps<typeof badge>['type'], 'custom'>
|
|
>;
|
|
export type BadgeShape = NonNullable<VariantProps<typeof badge>['shape']>;
|
|
export type BadgeSize = NonNullable<VariantProps<typeof badge>['size']>;
|
|
|
|
export type Props = {
|
|
shape?: BadgeShape;
|
|
size?: BadgeSize;
|
|
bordered?: boolean;
|
|
icon?: IconProps['icon'];
|
|
} & (
|
|
| { type?: BadgeType; className?: string }
|
|
| { type: 'custom'; className: string }
|
|
);
|
|
|
|
export function Badge({
|
|
type = 'info',
|
|
shape,
|
|
size,
|
|
className,
|
|
bordered,
|
|
icon,
|
|
children,
|
|
'data-cy': dataCy,
|
|
}: PropsWithChildren<Props> & Partial<AutomationTestingProps>) {
|
|
return (
|
|
<span
|
|
className={badge({ type, shape, size, bordered, className })}
|
|
role="status"
|
|
data-cy={dataCy}
|
|
>
|
|
{icon && <Icon icon={icon} />}
|
|
{children}
|
|
</span>
|
|
);
|
|
}
|