analytics page styling

This commit is contained in:
Yared Yemane 2026-04-14 01:47:00 -07:00
parent e46e0314ed
commit d308719d18

View File

@ -70,21 +70,26 @@ function KpiCard({
className?: string className?: string
}) { }) {
return ( return (
<Card className={cn("shadow-none transition-shadow hover:shadow-md", className)}> <Card
<CardContent className="p-4"> className={cn(
"border-grayScale-100/90 bg-white shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md",
className,
)}
>
<CardContent className="p-5">
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div className="min-w-0"> <div className="min-w-0">
<div className="text-xs font-medium text-grayScale-500">{label}</div> <div className="text-xs font-semibold uppercase tracking-wide text-grayScale-400">{label}</div>
<div className="mt-1 text-2xl font-semibold tracking-tight">{value}</div> <div className="mt-1.5 text-[1.75rem] font-semibold leading-none tracking-tight text-grayScale-800">{value}</div>
</div> </div>
<div className="grid h-10 w-10 shrink-0 place-items-center rounded-xl bg-brand-100 text-brand-600"> <div className="grid h-11 w-11 shrink-0 place-items-center rounded-xl bg-gradient-to-br from-brand-50 to-brand-100 text-brand-600 ring-1 ring-brand-100">
<Icon className="h-5 w-5" /> <Icon className="h-5 w-5" />
</div> </div>
</div> </div>
{sub && ( {sub && (
<div <div
className={cn( className={cn(
"mt-2 flex items-center gap-1 text-xs font-medium", "mt-3 flex items-center gap-1 text-xs font-medium",
trend === "up" && "text-mint-500", trend === "up" && "text-mint-500",
trend === "down" && "text-destructive", trend === "down" && "text-destructive",
(!trend || trend === "neutral") && "text-grayScale-400", (!trend || trend === "neutral") && "text-grayScale-400",
@ -244,16 +249,16 @@ function Section({
const [open, setOpen] = useState(defaultOpen) const [open, setOpen] = useState(defaultOpen)
return ( return (
<div className="rounded-xl border bg-white"> <div className="rounded-2xl border border-grayScale-100 bg-white shadow-sm">
<button <button
type="button" type="button"
onClick={() => setOpen((v) => !v)} onClick={() => setOpen((v) => !v)}
className="flex w-full items-center gap-3 px-5 py-3.5 text-left transition-colors hover:bg-grayScale-50" className="flex w-full items-center gap-3 px-6 py-4 text-left transition-colors hover:bg-grayScale-50/80"
> >
<div className="grid h-8 w-8 shrink-0 place-items-center rounded-lg bg-brand-100 text-brand-600"> <div className="grid h-9 w-9 shrink-0 place-items-center rounded-lg bg-gradient-to-br from-brand-50 to-brand-100 text-brand-600 ring-1 ring-brand-100">
<Icon className="h-4 w-4" /> <Icon className="h-4 w-4" />
</div> </div>
<span className="flex-1 text-sm font-semibold text-grayScale-800">{title}</span> <span className="flex-1 text-sm font-semibold tracking-wide text-grayScale-800">{title}</span>
{count !== undefined && ( {count !== undefined && (
<Badge variant="secondary" className="mr-2 text-[10px]"> <Badge variant="secondary" className="mr-2 text-[10px]">
{count} {count}
@ -273,7 +278,7 @@ function Section({
)} )}
> >
<div className="overflow-hidden"> <div className="overflow-hidden">
<div className="px-5 pb-5 pt-1">{children}</div> <div className="border-t border-grayScale-100 px-6 pb-6 pt-4">{children}</div>
</div> </div>
</div> </div>
</div> </div>
@ -305,9 +310,9 @@ export function AnalyticsPage() {
if (loading) { if (loading) {
return ( return (
<div className="mx-auto w-full max-w-6xl"> <div className="mx-auto w-full max-w-[1280px] px-2 sm:px-4">
<div className="mb-4 text-sm font-semibold text-grayScale-500">Analytics</div> <div className="mb-6 text-xs font-semibold uppercase tracking-wide text-grayScale-400">Analytics</div>
<div className="flex flex-col items-center justify-center gap-3 py-20"> <div className="flex flex-col items-center justify-center gap-3 rounded-2xl border border-grayScale-100 bg-white py-24 shadow-sm">
<img src={spinnerSrc} alt="" className="h-10 w-10 animate-spin" /> <img src={spinnerSrc} alt="" className="h-10 w-10 animate-spin" />
<span className="text-sm font-medium text-grayScale-400">Loading analytics</span> <span className="text-sm font-medium text-grayScale-400">Loading analytics</span>
</div> </div>
@ -317,9 +322,9 @@ export function AnalyticsPage() {
if (error || !dashboard) { if (error || !dashboard) {
return ( return (
<div className="mx-auto w-full max-w-6xl"> <div className="mx-auto w-full max-w-[1280px] px-2 sm:px-4">
<div className="mb-4 text-sm font-semibold text-grayScale-500">Analytics</div> <div className="mb-6 text-xs font-semibold uppercase tracking-wide text-grayScale-400">Analytics</div>
<div className="flex flex-col items-center justify-center gap-3 py-20"> <div className="flex flex-col items-center justify-center gap-3 rounded-2xl border border-red-100 bg-red-50/30 py-24">
<img src={alertSrc} alt="" className="h-12 w-12" /> <img src={alertSrc} alt="" className="h-12 w-12" />
<span className="text-sm text-destructive">Failed to load analytics data.</span> <span className="text-sm text-destructive">Failed to load analytics data.</span>
<Button variant="outline" size="sm" onClick={fetchData}> <Button variant="outline" size="sm" onClick={fetchData}>
@ -375,12 +380,12 @@ export function AnalyticsPage() {
}) })
return ( return (
<div className="mx-auto w-full max-w-6xl"> <div className="mx-auto w-full max-w-[1280px] px-2 pb-6 sm:px-4">
{/* Header */} {/* Header */}
<div className="mb-5 flex items-end justify-between"> <div className="mb-7 flex flex-wrap items-end justify-between gap-4">
<div> <div>
<div className="mb-1 text-sm font-semibold text-grayScale-500">Analytics</div> <div className="mb-1 text-xs font-semibold uppercase tracking-wide text-grayScale-400">Analytics</div>
<h1 className="text-2xl font-semibold tracking-tight">Platform Overview</h1> <h1 className="text-3xl font-semibold tracking-tight text-grayScale-900">Platform Overview</h1>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="text-xs text-grayScale-400">Generated {generatedAt}</span> <span className="text-xs text-grayScale-400">Generated {generatedAt}</span>
@ -392,7 +397,7 @@ export function AnalyticsPage() {
</div> </div>
{/* Summary Tabs */} {/* Summary Tabs */}
<div className="mb-4 border-b border-grayScale-200"> <div className="mb-6 rounded-2xl border border-grayScale-100 bg-white px-5 pt-4 shadow-sm">
<div className="-mb-px flex gap-6"> <div className="-mb-px flex gap-6">
<button <button
onClick={() => setActiveSummaryTab("key")} onClick={() => setActiveSummaryTab("key")}
@ -433,7 +438,7 @@ export function AnalyticsPage() {
</div> </div>
</div> </div>
<div className="space-y-4"> <div className="space-y-5">
{activeSummaryTab === "key" && ( {activeSummaryTab === "key" && (
<> <>
{/* ─── Key Metrics ─── */} {/* ─── Key Metrics ─── */}