StatisticCard

free

StatisticCard is a bordered or inset card shell for composing a label, value, and supporting content such as trend indicators, charts, or progress bars.

Preview
Dark

1,862

vs yesterday+12.5%
import CloseButton from '@/components/ui/CloseButton'
import Dropdown from '@/components/ui/Dropdown'
import StatisticCard from '@/components/composites/StatisticCard';
import GrowShrinkTag from '@/components/composites/GrowShrinkTag';
import IconFrame from '@/components/composites/IconFrame';
import {
    PiCopy,
    PiCurrencyCircleDollar,
    PiDotsThreeVertical,
    PiEye,
    PiFilePlus,
} from 'react-icons/pi'

export default function UsageDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard>
        <div className="flex items-center justify-between">
          <IconFrame>
            <PiCurrencyCircleDollar className="text-xl" />
          </IconFrame>
          <Dropdown
            placement="bottom-end"
            renderTitle={
              <CloseButton >
                <PiDotsThreeVertical className="text-base" />
              </CloseButton>
            }
          >
            <Dropdown.Item eventKey="viewMore">
              <PiEye className="text-lg" />
              <span>View More</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="edit">
              <PiFilePlus className="text-lg" />
              <span>Edit</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="copy">
              <PiCopy className="text-lg" />
              <span>Copy</span>
            </Dropdown.Item>
          </Dropdown>
        </div>
        <div className="mt-4">
          <h4 className="text-xl font-semibold">1,862</h4>
          <div className="flex items-center gap-1">
            <span className="text-muted-foreground">vs yesterday</span>
            <span className="font-medium text-success">+12.5%</span>
          </div>
        </div>
      </StatisticCard>
    </div>
  );
}

Installation

Add this component with the NateUI CLI.

npx nateui@latest add StatisticCard

Examples

Basic

Preview
Dark

Open tickets

128

18.2%
import StatisticCard from '@/components/composites/StatisticCard';
import GrowShrinkTag from '@/components/composites/GrowShrinkTag';

export default function BasicDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard>
        <p className="text-muted-foreground">Open tickets</p>
        <div className="flex items-center justify-between mt-2">
          <h4 className="text-xl font-semibold">128</h4>
          <GrowShrinkTag
            value={18.2}
            suffix="%"
            className="bg-card border"
          />
        </div>
      </StatisticCard>
    </div>
  );
}
Preview
Dark
Database Throughput (TPS)

2,450

+450vs baseline
import Tag from '@/components/ui/Tag';
import Link from '@/components/ui/Link';
import StatisticCard from '@/components/composites/StatisticCard';
import { PiDatabase } from 'react-icons/pi'

export default function HeaderAndFooterDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard
        header={
          <div className="flex items-center gap-2">
            <span 
              className="flex items-center justify-center text-white bg-palette-blue size-6 rounded"
            >
              <PiDatabase />
            </span>
            <span className="font-medium">
              Database Throughput (TPS)
            </span>
          </div>
        }
      >
        <div className="mt-4">
          <h4 className="text-xl font-semibold">2,450</h4>
          <div className="flex items-center gap-1 mt-2">
            <Tag>+450</Tag>
            <span>vs baseline</span>
          </div>
        </div>
      </StatisticCard>
    </div>
  );
}
Preview
Dark
New Client

1,862

import Tag from '@/components/ui/Tag';
import Link from '@/components/ui/Link';
import StatisticCard from '@/components/composites/StatisticCard';
import IconFrame from '@/components/composites/IconFrame';
import GrowShrinkTag from '@/components/composites/GrowShrinkTag';
import { PiUserCircle } from 'react-icons/pi'

export default function HeaderAndFooterDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard
        footer={
          <span className="flex justify-between">
            <span className="flex items-center gap-1">
              <GrowShrinkTag value={12.5} suffix="%" />
            </span>
            <Link href="#">
              View report
            </Link>
          </span>
        }
      >
        <div className="flex items-center gap-2 mb-8">
          <IconFrame>
            <PiUserCircle className="text-xl" />
          </IconFrame>
          <span className="font-medium">New Client</span>
        </div>
        <div>
          <h4 className="text-xl font-semibold">1,862</h4>
          
        </div>
      </StatisticCard>
    </div>
  );
}

Inset

Preview
Dark
Total Client

1,862

vs yesterday+12.5%
import CloseButton from '@/components/ui/CloseButton'
import Dropdown from '@/components/ui/Dropdown'
import StatisticCard from '@/components/composites/StatisticCard';
import IconFrame from '@/components/composites/IconFrame';
import {
    PiCopy,
    PiCurrencyCircleDollar,
    PiDotsThreeVertical,
    PiEye,
    PiFilePlus,
} from 'react-icons/pi'

export default function InsetDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard inset>
        <div className="flex items-center justify-between">
          <div className="font-medium">Total Client</div>
          <Dropdown
            placement="bottom-end"
            renderTitle={
              <CloseButton >
                <PiDotsThreeVertical className="text-base" />
              </CloseButton>
            }
          >
            <Dropdown.Item eventKey="viewMore">
              <PiEye className="text-lg" />
              <span>View More</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="edit">
              <PiFilePlus className="text-lg" />
              <span>Edit</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="copy">
              <PiCopy className="text-lg" />
              <span>Copy</span>
            </Dropdown.Item>
          </Dropdown>
        </div>
        <div className="mt-4">
          <h4 className="text-xl font-semibold">1,862</h4>
          <div className="flex items-center gap-1">
            <span className="text-muted-foreground">vs yesterday</span>
            <span className="font-medium text-success">+12.5%</span>
          </div>
        </div>
    </StatisticCard>
    </div>
  );
}
Preview
Dark

1,862

Total Revenue
+12.5%vs last period
import CloseButton from '@/components/ui/CloseButton'
import Dropdown from '@/components/ui/Dropdown'
import StatisticCard from '@/components/composites/StatisticCard';
import GrowShrinkTag from '@/components/composites/GrowShrinkTag';
import IconFrame from '@/components/composites/IconFrame';
import {
    PiCopy,
    PiCurrencyCircleDollar,
    PiDotsThreeVertical,
    PiEye,
    PiFilePlus,
} from 'react-icons/pi'

export default function InsetDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard
        inset
        footer={
          <div className="flex items-center justify-between px-2">
            <span className="font-medium text-success">+12.5%</span>
            <span>vs last period</span>
          </div>
        }
      >
        <div className="flex items-center justify-between">
          <IconFrame>
            <PiCurrencyCircleDollar className="text-xl" />
          </IconFrame>
          <Dropdown
            placement="bottom-end"
            renderTitle={
              <CloseButton >
                <PiDotsThreeVertical className="text-base" />
              </CloseButton>
            }
          >
            <Dropdown.Item eventKey="viewMore">
              <PiEye className="text-lg" />
              <span>View More</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="edit">
              <PiFilePlus className="text-lg" />
              <span>Edit</span>
            </Dropdown.Item>
            <Dropdown.Item eventKey="copy">
              <PiCopy className="text-lg" />
              <span>Copy</span>
            </Dropdown.Item>
          </Dropdown>
        </div>
        <div className="mt-4">
          <h4 className="text-xl font-semibold">1,862</h4>
          <span className="text-muted-foreground">
            Total Revenue
          </span>
        </div>
      </StatisticCard>
    </div>
  );
}

With Chart

Preview
Dark
Weekly sessions

3,102

12.5%vs yesterday
import StatisticCard from '@/components/composites/StatisticCard';
import GrowShrinkTag from '@/components/composites/GrowShrinkTag';
import { AreaChart } from '@/components/composites/Chart';

const data = [
  { day: 1, sessions: 320 },
  { day: 2, sessions: 402 },
  { day: 3, sessions: 380 },
  { day: 4, sessions: 460 },
  { day: 5, sessions: 510 },
  { day: 6, sessions: 470 },
  { day: 7, sessions: 560 },
];

export default function WithChartDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard>
        <div className="flex flex-col gap-4">
          <div className="font-medium">
            Weekly sessions
          </div>
          <div className="space-y-2">
            <h4 className="text-xl font-semibold">
              3,102
            </h4>
            <div className="flex items-center gap-1">
              <GrowShrinkTag
                value={12.5}
                suffix="%"
                className="bg-card border"
              />
              <span className="text-muted-foreground">vs yesterday</span>
            </div>
          </div>
          <AreaChart
            data={data}
            height={80}
            areaConfig={[{ 
              dataKey: 'sessions', 
              fill: 'url(#gradient-fill)' 
            }]}
            xAxisConfig={{ hide: true }}
            yAxisConfig={{ hide: true }}
            cartesianGridConfig={{ horizontal: false }}
            tooltipContentConfig={{ hideLabel: true }}
            chartHorizontalSpace={0}
          >
            {({ colors }) => (
              <defs>
                <linearGradient
                  id="gradient-fill"
                  x1="0"
                  y1="0"
                  x2="0"
                  y2="1"
                >
                  <stop
                    offset="5%"
                    stopColor={colors[0]}
                    stopOpacity={0.8}
                  />
                  <stop
                    offset="95%"
                    stopColor={colors[0]}
                    stopOpacity={0.1}
                  />
                </linearGradient>
              </defs>
            )}
          </AreaChart>
        </div>
      </StatisticCard>
    </div>
  );
}

With Progress

Preview
Dark

Storage used

91%

18 GB left of 200 GB

import StatisticCard from '@/components/composites/StatisticCard';
import Progress from '@/components/ui/Progress';

export default function WithProgressDemo() {
  return (
    <div className="mx-auto w-full max-w-xs">
      <StatisticCard>
        <p className="text-muted-foreground">Storage used</p>
        <h4 className="text-xl font-semibold">91%</h4>
        <Progress
          percent={91}
          showInfo={false}
          strokeClass="bg-warning"
          className="mt-4"
        />
        <p className="mt-2 text-xs text-muted-foreground">
          18 GB left of 200 GB
        </p>
      </StatisticCard>
    </div>
  );
}

API

PropDescriptionTypeDefault
insetRenders the muted outer frame with an inset body, instead of the plain bordered card.booleanfalse
headerContent shown above the body, in its own bordered/padded region.ReactNode | string
footerContent shown below the body, in its own bordered/padded region.ReactNode | string
bodyClassClass names applied to the inner body. Only takes effect when inset is true.string
classNameClass names applied to the outermost element.string
childrenThe card's main content.ReactNode
...restNative div props.ComponentProps<'div'>