dodil/erp-ui

src/components/stat/Stat.tsx

/**
 * Stat — one number a person starts the day from ("3 overdue", "EUR 83,400.00 weighted"), with what it
 * means. A row of them is a StatGrid. Money arrives as text and is shown as text.
 */
import { Card, Flex, Grid, Text } from "@radix-ui/themes";
import type { ReactNode } from "react";

export interface StatProps {
  label: string;
  value: ReactNode;
  hint?: ReactNode;
  tone?: "neutral" | "danger" | "warning" | "success";
}

const COLOR = { neutral: undefined, danger: "red", warning: "amber", success: "green" } as const;

export function Stat({ label, value, hint, tone = "neutral" }: StatProps) {
  return (
    <Card>
      <Flex direction="column" gap="1">
        <Text size="2" color="gray">{label}</Text>
        <Text size="6" weight="bold" color={COLOR[tone]} style={{ fontVariantNumeric: "tabular-nums" }}>{value}</Text>
        {hint && <Text size="1" color="gray">{hint}</Text>}
      </Flex>
    </Card>
  );
}

export function StatGrid({ children, label }: { children: ReactNode; label?: string }) {
  return (
    <Grid columns={{ initial: "1", xs: "2", md: "4" }} gap="3" role="group" aria-label={label}>
      {children}
    </Grid>
  );
}