restructure project, add claudemd

This commit is contained in:
2026-07-08 16:36:17 -04:00
parent a7964f9410
commit 2a5fbffaa2
315 changed files with 81075 additions and 0 deletions

53
web/kit/Badges.tsx Normal file
View File

@@ -0,0 +1,53 @@
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-neutral-400 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>;
}