import type { ReactNode } from "react";
/**
* Public-site design system, faithful to AtomCMS's "atom" theme. The signature
* element is the content-card: a surface card with a primary-tinted header
* (icon circle + title + subtitle) and a padded body. These mirror the atom
* Blade components (content-card, stat blocks, empty states) so every public
* page shares one consistent, themeable look.
*/
export function ContentCard({
icon,
title,
subtitle,
action,
children,
className,
padded = true,
}: {
icon?: string;
title?: ReactNode;
subtitle?: ReactNode;
action?: ReactNode;
children?: ReactNode;
className?: string;
padded?: boolean;
}) {
const hasHead =
title != null || icon != null || subtitle != null || action != null;
return (
{hasHead ? (
{icon ? (
{icon}
) : null}
{title != null ? (
{title}
) : null}
{subtitle != null ? (
{subtitle}
) : null}
{action ?
{action}
: null}
) : null}
{children}
);
}
/** A value + label tile (profile stats, rare-value summaries, …). */
export function StatBlock({
value,
label,
icon,
}: {
value: ReactNode;
label: string;
icon?: string;
}) {
return (
{icon ? {icon} : null}
{value}
{label}
);
}
/** Friendly empty state with an icon and a muted line. */
export function EmptyState({
icon = "📭",
children,
}: {
icon?: string;
children: ReactNode;
}) {
return (
);
}
/** Online / offline pill with a status dot. */
export function OnlineBadge({ online }: { online: boolean }) {
return (
{online ? "Online" : "Offline"}
);
}
/** Leaderboard rank chip — medals for the top three, number otherwise. */
export function RankBadge({ position }: { position: number }) {
const medal =
position === 1
? "🥇"
: position === 2
? "🥈"
: position === 3
? "🥉"
: null;
return (
{medal ?? `#${position}`}
);
}
/* ── Skeleton loaders ────────────────────────────────────────── */
export function Skeleton({
className,
style,
}: {
className?: string;
style?: React.CSSProperties;
}) {
return (
);
}
export function SkeletonCard({ lines = 3 }: { lines?: number }) {
return (
{Array.from({ length: lines }, (_, i) => i).map((n) => (
))}
);
}