38 lines
1.3 KiB
TypeScript
38 lines
1.3 KiB
TypeScript
import React from 'react'
|
|
import { Card, Group, Stack, Text, ThemeIcon } from '@mantine/core'
|
|
|
|
export interface StatCardProps {
|
|
/** Metric label, e.g. "Open tasks". */
|
|
label: React.ReactNode
|
|
/** The big number / value. */
|
|
value: React.ReactNode
|
|
/** Optional Lucide icon component. */
|
|
icon?: React.ComponentType<{ size?: number; strokeWidth?: number }>
|
|
/** Theme color for the icon tile (Mantine color key). Defaults to primary. */
|
|
color?: string
|
|
}
|
|
|
|
// A single metric tile: label, large value, optional icon. Compose several in a
|
|
// StatGrid for a dashboard summary row.
|
|
export function StatCard({ label, value, icon: Icon, color }: StatCardProps) {
|
|
return (
|
|
<Card withBorder radius="lg" padding="lg">
|
|
<Group justify="space-between" align="flex-start" wrap="nowrap">
|
|
<Stack gap={4}>
|
|
<Text size="xs" c="dimmed" fw={550} tt="uppercase" style={{ letterSpacing: '0.04em' }}>
|
|
{label}
|
|
</Text>
|
|
<Text fz={30} fw={700} lh={1} style={{ letterSpacing: '-0.03em' }}>
|
|
{value}
|
|
</Text>
|
|
</Stack>
|
|
{Icon ? (
|
|
<ThemeIcon variant="light" color={color} radius="md" size={38}>
|
|
<Icon size={20} strokeWidth={1.8} />
|
|
</ThemeIcon>
|
|
) : null}
|
|
</Group>
|
|
</Card>
|
|
)
|
|
}
|