54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import { JSXElement } from "solid-js";
|
|
|
|
export const BADGE_GREEN = "green";
|
|
export const BADGE_RED = "red";
|
|
export const BADGE_BLUE = "blue";
|
|
export const BADGE_AMBER = "amber";
|
|
export const BADGE_NEUTRAL = "neutral";
|
|
export const BADGE_MUTED = "muted";
|
|
|
|
const BASE = "inline-flex items-center gap-1 text-xs font-semibold py-0.5 px-2 rounded-default whitespace-nowrap";
|
|
|
|
const COLORS: Record<string, string> = {
|
|
"green": "text-white bg-green-700",
|
|
"red": "text-white bg-red-700",
|
|
"blue": "text-white bg-sky-800",
|
|
"amber": "text-white bg-amber-700",
|
|
"neutral": "text-white bg-neutral-500",
|
|
"muted": "text-ink-faint bg-transparent",
|
|
};
|
|
|
|
interface BadgeProps {
|
|
color?: string;
|
|
pill?: boolean;
|
|
// When provided, the badge renders as a `<button>` with the given
|
|
// click handler — same visuals, just interactive.
|
|
onclick?: () => void;
|
|
disabled?: boolean;
|
|
title?: string;
|
|
// Extra utility classes appended after the base styling — useful
|
|
// for overriding e.g. the default `font-semibold` (use
|
|
// `!font-normal`) on specific instances.
|
|
class?: string;
|
|
children?: JSXElement;
|
|
}
|
|
|
|
export function Badge(props: BadgeProps) {
|
|
const cls = () => {
|
|
let c = BASE;
|
|
if (props.pill) c += " rounded-full";
|
|
c += " " + (COLORS[props.color!] || COLORS["neutral"]);
|
|
if (props.onclick) c += " cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed border-0";
|
|
if (props.class) c += " " + props.class;
|
|
return c;
|
|
};
|
|
|
|
if (props.onclick) {
|
|
return (
|
|
<button type="button" class={cls()} onclick={() => props.onclick!()} disabled={props.disabled} title={props.title}>{props.children}</button>
|
|
);
|
|
}
|
|
|
|
return <span class={cls()} title={props.title}>{props.children}</span>;
|
|
}
|