This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import type { ElementType, ReactNode } from 'react';
|
||||
import * as tailwindColors from 'tailwindcss/colors';
|
||||
import type { CSSProperties, ElementType, ReactNode } from 'react';
|
||||
|
||||
type ChipVariant = 'solid' | 'outlined';
|
||||
type ChipTone = 'neutral' | 'indigo' | 'cyan';
|
||||
|
||||
type ChipProps<T extends ElementType> = {
|
||||
variant?: ChipVariant;
|
||||
tone?: ChipTone;
|
||||
// Tailwind color token, e.g. "cyan-700", "indigo-500", "rose-600".
|
||||
tone?: string;
|
||||
as?: T;
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
@@ -16,21 +17,49 @@ const variantClassMap: Record<ChipVariant, string> = {
|
||||
outlined: 'chip-outlined'
|
||||
};
|
||||
|
||||
const toneClassMap: Record<ChipTone, string> = {
|
||||
neutral: 'chip-neutral',
|
||||
indigo: 'chip-indigo',
|
||||
cyan: 'chip-cyan'
|
||||
};
|
||||
type TailwindPalette = Record<string, string>;
|
||||
|
||||
function resolveTailwindToneColor(tone: string | undefined): string | null {
|
||||
const normalizedTone = tone?.trim().toLowerCase();
|
||||
if (normalizedTone == null || normalizedTone === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const colorSource = tailwindColors as Record<string, unknown>;
|
||||
const lastDashIndex = normalizedTone.lastIndexOf('-');
|
||||
|
||||
if (lastDashIndex === -1) {
|
||||
const direct = colorSource[normalizedTone];
|
||||
return typeof direct === 'string' ? direct : null;
|
||||
}
|
||||
|
||||
const colorName = normalizedTone.slice(0, lastDashIndex);
|
||||
const shade = normalizedTone.slice(lastDashIndex + 1);
|
||||
const palette = colorSource[colorName];
|
||||
|
||||
if (palette == null || typeof palette !== 'object') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const shadeColor = (palette as TailwindPalette)[shade];
|
||||
return typeof shadeColor === 'string' ? shadeColor : null;
|
||||
}
|
||||
|
||||
export function Chip<T extends ElementType = 'span'>({
|
||||
variant = 'solid',
|
||||
tone = 'neutral',
|
||||
tone,
|
||||
as,
|
||||
className = '',
|
||||
children
|
||||
}: Readonly<ChipProps<T>>) {
|
||||
const Component = as ?? 'span' as ElementType;
|
||||
const classes = `chip-root ${variantClassMap[variant]} ${toneClassMap[tone]} ${className}`.trim();
|
||||
const toneColor = resolveTailwindToneColor(tone);
|
||||
const toneStyle: CSSProperties | undefined = toneColor == null
|
||||
? undefined
|
||||
: variant === 'solid'
|
||||
? { borderColor: toneColor, backgroundColor: toneColor, color: '#ffffff' }
|
||||
: { borderColor: toneColor, color: toneColor };
|
||||
const classes = `chip-root ${variantClassMap[variant]} ${className}`.trim();
|
||||
|
||||
return <Component className={classes}>{children}</Component>;
|
||||
return <Component className={classes} style={toneStyle}>{children}</Component>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user