Dice UI
Components

Stat

A flexible component for displaying key metrics and statistics with support for trends, indicators, and descriptions.

API
import {
  ArrowDown,
  ArrowUp,
  DollarSign,
  MoreHorizontal,
  ShoppingCart,
} from "lucide-react";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  Stat,
  StatIndicator,
  StatLabel,
  StatTrend,
  StatValue,
} from "@/components/ui/stat";
 
export function StatDemo() {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      <Stat>
        <StatLabel>Total Revenue</StatLabel>
        <StatIndicator variant="icon" color="success">
          <DollarSign />
        </StatIndicator>
        <StatValue>$45,231</StatValue>
        <StatTrend trend="up">
          <ArrowUp />
          +20.1% from last month
        </StatTrend>
      </Stat>
 
      <Stat>
        <StatLabel>Active Users</StatLabel>
        <StatIndicator variant="badge" color="info">
          +24
        </StatIndicator>
        <StatValue>2,350</StatValue>
        <StatTrend trend="up">
          <ArrowUp />
          +180 from last week
        </StatTrend>
      </Stat>
 
      <Stat>
        <StatLabel>Total Orders</StatLabel>
        <StatIndicator variant="icon" color="warning">
          <ShoppingCart />
        </StatIndicator>
        <StatValue>1,234</StatValue>
        <StatTrend trend="down">
          <ArrowDown />
          -4.3% from last month
        </StatTrend>
      </Stat>
 
      <Stat>
        <StatLabel>Conversion Rate</StatLabel>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <StatIndicator variant="action">
              <MoreHorizontal />
            </StatIndicator>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem>View details</DropdownMenuItem>
            <DropdownMenuItem>Export data</DropdownMenuItem>
            <DropdownMenuItem>Share</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
        <StatValue>3.2%</StatValue>
        <StatTrend trend="neutral">No change from last week</StatTrend>
      </Stat>
    </div>
  );
}

Installation

CLI

npx shadcn@latest add @diceui/stat

Manual

Copy and paste the following code into your project.

import { cva, type VariantProps } from "class-variance-authority";
import type * as React from "react";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
 
function Stat({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="stat"
      className={cn(
        "grid grid-cols-[1fr_auto] gap-x-4 gap-y-1 rounded-lg border bg-card p-4 text-card-foreground shadow-sm",
        "**:data-[slot=stat-label]:col-span-1 **:data-[slot=stat-value]:col-span-1",
        "**:data-[slot=stat-indicator]:col-start-2 **:data-[slot=stat-indicator]:row-span-2 **:data-[slot=stat-indicator]:row-start-1 **:data-[slot=stat-indicator]:self-start",
        "**:data-[slot=stat-description]:col-span-2 **:data-[slot=stat-separator]:col-span-2 **:data-[slot=stat-trend]:col-span-2",
        className,
      )}
      {...props}
    />
  );
}
 
function StatLabel({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="stat-label"
      className={cn("font-medium text-muted-foreground text-sm", className)}
      {...props}
    />
  );
}
 
const statIndicatorVariants = cva(
  "flex shrink-0 items-center justify-center [&_svg]:pointer-events-none",
  {
    variants: {
      variant: {
        default: "text-muted-foreground [&_svg:not([class*='size-'])]:size-5",
        icon: "size-8 rounded-md border [&_svg:not([class*='size-'])]:size-3.5",
        badge:
          "h-6 min-w-6 rounded-sm border px-1.5 font-medium text-xs [&_svg:not([class*='size-'])]:size-3",
        action:
          "size-8 cursor-pointer rounded-md transition-colors hover:bg-muted/50 [&_svg:not([class*='size-'])]:size-4",
      },
      color: {
        default: "bg-muted text-muted-foreground",
        success:
          "border-green-500/20 bg-green-500/10 text-green-600 dark:text-green-400",
        info: "border-blue-500/20 bg-blue-500/10 text-blue-600 dark:text-blue-400",
        warning:
          "border-orange-500/20 bg-orange-500/10 text-orange-600 dark:text-orange-400",
        error: "border-destructive/20 bg-destructive/10 text-destructive",
      },
    },
    defaultVariants: {
      variant: "default",
      color: "default",
    },
  },
);
 
interface StatIndicatorProps
  extends Omit<React.ComponentProps<"div">, "color">,
    VariantProps<typeof statIndicatorVariants> {}
 
function StatIndicator({
  className,
  variant = "default",
  color = "default",
  ...props
}: StatIndicatorProps) {
  return (
    <div
      data-slot="stat-indicator"
      data-variant={variant}
      data-color={color}
      className={cn(statIndicatorVariants({ variant, color, className }))}
      {...props}
    />
  );
}
 
function StatValue({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="stat-value"
      className={cn("font-semibold text-2xl tracking-tight", className)}
      {...props}
    />
  );
}
 
function StatTrend({
  className,
  trend,
  ...props
}: React.ComponentProps<"div"> & { trend?: "up" | "down" | "neutral" }) {
  return (
    <div
      data-slot="stat-trend"
      data-trend={trend}
      className={cn(
        "inline-flex items-center gap-1 font-medium text-xs [&_svg:not([class*='size-'])]:size-3 [&_svg]:pointer-events-none [&_svg]:shrink-0",
        {
          "text-green-600 dark:text-green-400": trend === "up",
          "text-red-600 dark:text-red-400": trend === "down",
          "text-muted-foreground": trend === "neutral" || !trend,
        },
        className,
      )}
      {...props}
    />
  );
}
 
function StatSeparator({ ...props }: React.ComponentProps<typeof Separator>) {
  return <Separator data-slot="stat-separator" className="my-2" {...props} />;
}
 
function StatDescription({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="stat-description"
      className={cn("text-muted-foreground text-xs", className)}
      {...props}
    />
  );
}
 
export {
  Stat,
  StatLabel,
  StatIndicator,
  StatValue,
  StatTrend,
  StatSeparator,
  StatDescription,
};

Layout

Import the parts, and compose them together.

import {
  Stat,
  StatLabel,
  StatValue,
  StatIndicator,
  StatTrend,
  StatDescription,
  StatSeparator,
} from "@/components/ui/stat";

return (
  <Stat>
    <StatLabel>Total Revenue</StatLabel>
    <StatIndicator variant="icon" color="success">
      <DollarSign />
    </StatIndicator>
    <StatValue>$45,231</StatValue>
    <StatTrend trend="up">
      <ArrowUp />
      +20.1% from last month
    </StatTrend>
    <StatSeparator />
    <StatDescription>
      Total revenue generated in the current billing period
    </StatDescription>
  </Stat>
);

Examples

Variants

Explore different indicator variants and color themes.

import { DollarSign, TrendingUp } from "lucide-react";
import {
  Stat,
  StatIndicator,
  StatLabel,
  StatTrend,
  StatValue,
} from "@/components/ui/stat";
 
export function StatVariantsDemo() {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      <Stat>
        <StatLabel>Default Indicator</StatLabel>
        <StatValue>2,350</StatValue>
        <StatIndicator>
          <TrendingUp />
        </StatIndicator>
      </Stat>
 
      <Stat>
        <StatLabel>Icon Variant</StatLabel>
        <StatValue>$45,231</StatValue>
        <StatIndicator variant="icon" color="success">
          <DollarSign />
        </StatIndicator>
      </Stat>
 
      <Stat>
        <StatLabel>Badge Variant</StatLabel>
        <StatValue>1,234</StatValue>
        <StatIndicator variant="badge" color="info">
          +24
        </StatIndicator>
      </Stat>
 
      <Stat>
        <StatLabel>Warning Color</StatLabel>
        <StatValue>89%</StatValue>
        <StatIndicator variant="icon" color="warning">
          <TrendingUp />
        </StatIndicator>
        <StatTrend trend="down">Capacity threshold reached</StatTrend>
      </Stat>
    </div>
  );
}

Layout Options

Combine different stat components to create rich statistical displays.

import { ArrowUp, Users } from "lucide-react";
import {
  Stat,
  StatDescription,
  StatIndicator,
  StatLabel,
  StatSeparator,
  StatTrend,
  StatValue,
} from "@/components/ui/stat";
 
export function StatLayoutDemo() {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      <Stat>
        <StatLabel>Active Subscribers</StatLabel>
        <StatValue>2,847</StatValue>
        <StatIndicator variant="icon" color="success">
          <Users />
        </StatIndicator>
        <StatDescription>
          Total number of active subscribers as of today
        </StatDescription>
      </Stat>
 
      <Stat>
        <StatLabel>Monthly Revenue</StatLabel>
        <StatValue>$12,450</StatValue>
        <StatIndicator variant="icon" color="info">
          <ArrowUp />
        </StatIndicator>
        <StatSeparator />
        <StatTrend trend="up">
          <ArrowUp />
          +15.3% from last month
        </StatTrend>
        <StatDescription>
          Revenue generated in the current billing period
        </StatDescription>
      </Stat>
    </div>
  );
}

API Reference

Stat

The main container component that provides a card-style layout for displaying statistics.

Prop

Type

StatLabel

A label component for the statistic title or category.

Prop

Type

StatIndicator

A visual indicator component that can display icons, badges, or action buttons with various color themes.

Prop

Type

Data AttributeValue
[data-variant]"default" | "icon" | "badge" | "action"
[data-color]"default" | "success" | "info" | "warning" | "error"

StatValue

Displays the primary statistic value with emphasized typography.

Prop

Type

StatTrend

Displays trend information with directional styling (up, down, or neutral).

Prop

Type

Data AttributeValue
[data-trend]"up" | "down" | "neutral"

StatSeparator

A horizontal separator for dividing content within the stat card.

Prop

Type

StatDescription

Additional descriptive text for providing context about the stat.

On this page