Files
web-ui/src/components/Chip.tsx
Beatrice Dellacà f1c7e245aa
All checks were successful
continuous-integration/drone/push Build is passing
update prettier
2026-02-23 14:23:37 +01:00

71 lines
2.1 KiB
TypeScript

import * as tailwindColors from 'tailwindcss/colors';
import type { CSSProperties, ElementType, ReactNode } from 'react';
type ChipVariant = 'solid' | 'outlined';
type ChipProps<T extends ElementType> = {
variant?: ChipVariant;
// Tailwind color token, e.g. "cyan-700", "indigo-500", "rose-600".
tone?: string;
as?: T;
className?: string;
children: ReactNode;
};
const variantClassMap: Record<ChipVariant, string> = {
solid: 'chip-solid',
outlined: 'chip-outlined',
};
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 unknown 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,
as,
className = '',
children,
}: Readonly<ChipProps<T>>) {
const Component = as ?? ('span' as ElementType);
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} style={toneStyle}>
{children}
</Component>
);
}