84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import { LucideIcon } from 'lucide-react';
|
|
import React, { ReactNode } from 'react';
|
|
import { Box } from './Box';
|
|
import { Icon } from './Icon';
|
|
import { Stack } from './Stack';
|
|
|
|
export interface BadgeProps {
|
|
children: ReactNode;
|
|
variant?: 'primary' | 'secondary' | 'success' | 'warning' | 'critical' | 'info' | 'outline' | 'default' | 'danger';
|
|
size?: 'xs' | 'sm' | 'md';
|
|
icon?: LucideIcon;
|
|
rounded?: string;
|
|
bg?: string;
|
|
color?: string;
|
|
borderColor?: string;
|
|
transform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase' | string;
|
|
}
|
|
|
|
/** @internal */
|
|
interface InternalBadgeProps extends BadgeProps {
|
|
style?: React.CSSProperties;
|
|
}
|
|
|
|
export const Badge = ({
|
|
children,
|
|
variant = 'primary',
|
|
size = 'md',
|
|
style: styleProp,
|
|
icon,
|
|
rounded,
|
|
bg,
|
|
color,
|
|
borderColor,
|
|
transform
|
|
}: InternalBadgeProps) => {
|
|
const variantClasses = {
|
|
primary: 'bg-[var(--ui-color-intent-primary)] text-white',
|
|
secondary: 'bg-[var(--ui-color-bg-surface)] text-[var(--ui-color-text-med)] border border-[var(--ui-color-border-default)]',
|
|
success: 'bg-[var(--ui-color-intent-success)] text-[var(--ui-color-bg-base)]',
|
|
warning: 'bg-[var(--ui-color-intent-warning)] text-[var(--ui-color-bg-base)]',
|
|
critical: 'bg-[var(--ui-color-intent-critical)] text-white',
|
|
danger: 'bg-[var(--ui-color-intent-critical)] text-white',
|
|
info: 'bg-[var(--ui-color-intent-telemetry)] text-[var(--ui-color-bg-base)]',
|
|
outline: 'bg-transparent text-[var(--ui-color-text-med)] border border-[var(--ui-color-border-default)]',
|
|
default: 'bg-[var(--ui-color-bg-surface-muted)] text-[var(--ui-color-text-med)]',
|
|
};
|
|
|
|
const sizeClasses = {
|
|
xs: 'px-1 py-0 text-[9px]',
|
|
sm: 'px-1.5 py-0.5 text-[10px]',
|
|
md: 'px-2 py-0.5 text-xs',
|
|
};
|
|
|
|
const classes = [
|
|
'inline-flex items-center justify-center font-bold uppercase tracking-wider',
|
|
variantClasses[variant],
|
|
sizeClasses[size],
|
|
rounded ? (rounded === 'full' ? 'rounded-full' : `rounded-${rounded}`) : 'rounded-none',
|
|
bg?.startsWith('bg-') ? bg : '',
|
|
color?.startsWith('text-') ? color : '',
|
|
].join(' ');
|
|
|
|
const style: React.CSSProperties = {
|
|
...styleProp,
|
|
...(bg ? { backgroundColor: bg.startsWith('bg-') ? undefined : bg } : {}),
|
|
...(color ? { color: color.startsWith('text-') ? undefined : color } : {}),
|
|
...(borderColor ? { borderColor: borderColor.startsWith('border-') ? undefined : borderColor, borderStyle: 'solid', borderWidth: '1px' } : {}),
|
|
...(transform ? { textTransform: transform as any } : {}),
|
|
};
|
|
|
|
const content = icon ? (
|
|
<Stack direction="row" align="center" gap={1}>
|
|
<Icon icon={icon} size={3} />
|
|
{children}
|
|
</Stack>
|
|
) : children;
|
|
|
|
return (
|
|
<Box as="span" className={classes} style={style}>
|
|
{content}
|
|
</Box>
|
|
);
|
|
};
|