Stat Card
KPI display card with value, trend indicator, and change percentage.
Installation#
npx @aniui/cli add stat-cardWeb preview — components render natively on iOS & Android
import { StatCard } from "@/components/ui/stat-card";
export function MyScreen() {
return (
<View className="flex-row gap-4 p-4">
<StatCard
label="Revenue"
value="$12,345"
change={12.5}
trend="up"
className="flex-1"
/>
<StatCard
label="Users"
value="1,234"
change={-3.2}
trend="down"
className="flex-1"
/>
</View>
);
}Usage#
app/index.tsx
import { StatCard } from "@/components/ui/stat-card";
export function MyScreen() {
return (
<View className="flex-row gap-4 p-4">
<StatCard
label="Revenue"
value="$12,345"
change={12.5}
trend="up"
className="flex-1"
/>
<StatCard
label="Users"
value="1,234"
change={-3.2}
trend="down"
className="flex-1"
/>
</View>
);
}Props#
PropTypeDefault
labelstring-valuestring | number-changenumber-trend"up" | "down" | "neutral"-iconReact.ReactNode-classNamestring-Also accepts all View props.
Accessibility#
accessibilityRole="summary"for KPI display.- Value, trend, and change percentage are announced together for context.
Source#
components/ui/stat-card.tsx
import React from "react";
import { View, Text } from "react-native";
import { cn } from "@/lib/utils";
export interface StatCardProps extends React.ComponentPropsWithoutRef<typeof View> {
className?: string;
label: string;
value: string | number;
change?: number;
trend?: "up" | "down" | "neutral";
icon?: React.ReactNode;
}
export function StatCard({ className, label, value, change, trend, icon, ...props }: StatCardProps) {
const trendColor =
trend === "up" ? "text-green-500" : trend === "down" ? "text-destructive" : "text-muted-foreground";
const trendArrow = trend === "up" ? "↑" : trend === "down" ? "↓" : "";
return (
<View
className={cn("rounded-lg border border-border bg-card p-4", className)}
accessibilityRole="summary"
{...props}
>
<View className="flex-row items-center justify-between mb-2">
<Text className="text-sm text-muted-foreground">{label}</Text>
{icon && <View>{icon}</View>}
</View>
<Text className="text-2xl font-bold text-card-foreground">{value}</Text>
{change !== undefined && (
<View className="flex-row items-center mt-1 gap-1">
<Text className={cn("text-sm font-medium", trendColor)}>
{trendArrow} {change > 0 ? "+" : ""}{change}%
</Text>
</View>
)}
</View>
);
}