Stat Card
Production-ready stat card with extensive token integration, state management, and semantic HTML.
Overview
The Stat Card component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.
Why this exists
Stat cards (KPI widgets) are the backbone of any dashboard. They surface key metrics at a glance with trends and comparisons.
Mental model
A stat card shows a single metric: a label, a large value, and optionally a trend indicator (up/down with percentage). It is designed for scanning.
When to use
When not to use
Basic example
The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.
Total Subscribers
71,897
Avg. Open Rate
58.16%
4.14% from last month
Monthly Revenue
$24,500
import { StatCard } from '@byteion/react';
export default function StatCardDemo() {
return (
<div className="grid gap-4 p-6 md:grid-cols-3">
<StatCard label="Revenue" value="$24,500" trend={{ value: '+12%', direction: 'up' }} />
<StatCard label="Active users" value="1,284" trend={{ value: '+4.2%', direction: 'up' }} />
<StatCard label="Churn" value="2.1%" trend={{ value: '-0.3%', direction: 'down' }} tone="danger" />
</div>
);
}
<script setup lang="ts">
import { StatCard } from '@byteion/vue';
</script>
<template>
<div class="grid gap-4 p-6 md:grid-cols-3">
<StatCard label="Revenue" value="$24,500" :trend="{ value: '+12%', direction: 'up' }" />
<StatCard label="Active users" value="1,284" :trend="{ value: '+4.2%', direction: 'up' }" />
<StatCard label="Churn" value="2.1%" :trend="{ value: '-0.3%', direction: 'down' }" tone="danger" />
</div>
</template>
Variants
Each variant communicates a different meaning. Choose based on priority, not aesthetics.
Single default variant.
Sizes
Size should match the importance and context of the component.
- md — md size.
States
This component reacts seamlessly to the following interaction and data states:
- default — Resting appearance before interaction.
- hover — Pointer is over the element — visual feedback via color or shadow.
- focus — Keyboard or tab focus — shows ring indicator for accessibility.
- active — Currently selected or in use.
- disabled — Non-interactive — grayed out, cursor not-allowed.
- loading — Action in progress — spinner replaces icon, button is disabled.
Anatomy
Usage guidelines
- Use consistent number formatting.
- Show trend direction clearly.
- Keep to one metric per card.
Do and Don't
Do
- Format numbers consistently.
- Show trend.
- One metric per card.
Don't
- Do not show multiple metrics per card.
- Do not omit units.
- Do not use ambiguous trend colors.
Accessibility
Value should be readable by screen readers. Trend should include text description ("up 12%").
Role:stat-card
Customization
Layout and color follow card tokens.
Compose with React cva()
Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.
import { cva, cn, type VariantProps } from '@byteion/react';
const myStatCard = cva('base classes…', {
variants: {
accent: { soft:'border-primary-200', loud:'border-primary-500' },
},
defaultVariants: { accent:'soft' },
});
type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myStatCard>;
Compose with Vue cva()
Use the exportedcva() +cn() utilities inside standard Vue setup blocks.
<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';
interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();
const myStatCard = cva('base classes…', {
variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});
const cls = computed(() => myStatCard({ accent: props.accent, class: attrs.class as string | undefined }));
</script>
Runtime events
Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.
HTML / JS events
No HTML runtime events are declared by this adapter.
React callbacks
No React callback events are declared by this adapter.
Vue emits
No Vue emitted events are declared by this adapter.
Remote / AJAX
This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.
API Reference
Static HTML composition.
HTML Data Attributes
No custom data attributes required.
React Props · StatCardProps
Extracted directly fromreact/src/components/StatCard.tsx.
export interface StatCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'title'> {
label: ReactNode;
value: ReactNode;
trend?: StatCardTrend;
icon?: ReactNode;
iconTone?: 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'danger' | 'violet' | 'info' | 'neutral';
description?: ReactNode;
}
Vue Props · StatCardProps
Extracted directly fromvue/src/components/StatCard.vue.
export interface StatCardProps {
label: string;
value: string | number;
trend?: StatCardTrend;
iconTone?: StatCardIconTone;
description?: string;
}
Developer tips
trend.tone override.
• Use semantic trend meaning, not only direction.
• Use dashboard grid layout to keep cards aligned.
• Link each stat to a detail page only when users need drill-down.
• Show Skeleton while loading and "No data" for unavailable metrics.Common mistakes
- Missing units.
- Missing comparison period.
- Treating "up" as always positive.
- Showing multiple metrics in one card.
- Formatting numbers inconsistently.
- Showing 0 while data is still loading.
- Using trend colour without text.
- Making a KPI clickable without a clear destination.
- Using raw colours instead of tokens.
Production usage tips
- Test loading, empty, zero, negative, very large, and missing values.
- Test long labels and localised number formats.
- Test currency, percentage, count, and duration formats.
- Test positive, negative, and neutral trends.
- Test dark mode and branded themes.
- For Laravel or server-rendered dashboards, format values server-side or through a shared helper.
- For React or Vue SPAs, format values before rendering and keep fetch, loading, and error state outside the presentational Stat-card.
- Coordinate Stat-card with Card, Badge, Progress, Skeleton, Empty state, Chart or Sparkline, and DataTable where needed.
Premium examples
Advanced patterns available in Byteion Pro:
Related components
- Kpi-widget — alternative KPI layout
- Card — richer content surfaces
- Progress — goal completion
- Badge — inline status labels
- Skeleton — loading placeholder
- Empty state — no data state
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.
Explore Pro Components