49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
'use client'
|
|
|
|
import { HugeiconsIcon } from '@hugeicons/react'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
type HugeiconDef = React.ComponentProps<typeof HugeiconsIcon>['icon']
|
|
|
|
interface EmptyStateProps {
|
|
icon?: HugeiconDef
|
|
title: string
|
|
description?: string
|
|
action?: React.ReactNode
|
|
className?: string
|
|
}
|
|
|
|
/**
|
|
* Centered empty-state for lists and tables. Soft icon in a ringed circle,
|
|
* tight title and a muted one-liner underneath. Caller can slot an action button.
|
|
*/
|
|
export function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {
|
|
return (
|
|
<div className={cn('flex flex-col items-center justify-center gap-3 px-6 py-16 text-center', className)}>
|
|
{icon && (
|
|
<div
|
|
className="relative flex h-14 w-14 items-center justify-center rounded-full
|
|
bg-gradient-to-b from-muted/60 to-muted/20
|
|
ring-1 ring-border/60
|
|
shadow-[inset_0_0_0_1px_rgba(255,255,255,0.03)]"
|
|
>
|
|
<div
|
|
className="absolute inset-0 rounded-full opacity-70 blur-xl"
|
|
style={{ background: 'radial-gradient(closest-side, rgba(255,255,255,0.06), transparent 70%)' }}
|
|
/>
|
|
<HugeiconsIcon icon={icon} size={22} className="relative text-muted-foreground/80" />
|
|
</div>
|
|
)}
|
|
<div className="space-y-1">
|
|
<p className="text-sm font-medium text-foreground">{title}</p>
|
|
{description && (
|
|
<p className="text-xs text-muted-foreground max-w-sm mx-auto leading-relaxed">
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{action && <div className="mt-2">{action}</div>}
|
|
</div>
|
|
)
|
|
}
|