Init Commit
quality / commitlint (push) Skipped
CD / update-wiki (push) Failing after 7s
quality / changes (push) Successful in 4s
quality / docker-check (push) Skipped
quality / web (push) Failing after 38s
quality / api (push) Successful in 49s
CD / quality (push) Failing after 1m36s
CD / publish (push) Skipped
quality / commitlint (push) Skipped
CD / update-wiki (push) Failing after 7s
quality / changes (push) Successful in 4s
quality / docker-check (push) Skipped
quality / web (push) Failing after 38s
quality / api (push) Successful in 49s
CD / quality (push) Failing after 1m36s
CD / publish (push) Skipped
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { InboxIcon, type LucideIcon } from 'lucide-react'
|
||||
import { IconStack } from '@/components/reui/icon-stack'
|
||||
import { IconTile } from '@/components/reui/icon-tile'
|
||||
import {
|
||||
Empty,
|
||||
EmptyContent,
|
||||
EmptyDescription,
|
||||
EmptyHeader,
|
||||
EmptyMedia,
|
||||
EmptyTitle,
|
||||
} from '@cdnmanager/ui/components/empty'
|
||||
import { cn } from '@cdnmanager/ui/lib/utils'
|
||||
|
||||
interface EmptyStateProps {
|
||||
icon?: LucideIcon
|
||||
title: string
|
||||
description?: string
|
||||
action?: React.ReactNode
|
||||
className?: string
|
||||
/** Use IconStack media (empty-state-12). Default true. */
|
||||
stackedIcon?: boolean
|
||||
/**
|
||||
* Center in available width/height (empty-state-12).
|
||||
* Preview: https://reui.io/preview/base/empty-state-12
|
||||
* Set false for tight panels/sheets.
|
||||
*/
|
||||
centered?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* ReUI Empty + IconStack — Frame-friendly empty-state-14 / empty-state-12.
|
||||
* Preview: https://reui.io/preview/base/empty-state-14 · https://reui.io/preview/base/empty-state-12
|
||||
*/
|
||||
export function EmptyState({
|
||||
icon: Icon = InboxIcon,
|
||||
title,
|
||||
description,
|
||||
action,
|
||||
className,
|
||||
stackedIcon = true,
|
||||
centered = true,
|
||||
}: EmptyStateProps) {
|
||||
const body = (
|
||||
<Empty
|
||||
className={cn(
|
||||
'max-w-md flex-none border-0 bg-transparent p-0',
|
||||
!centered && className,
|
||||
)}
|
||||
>
|
||||
<EmptyHeader className={cn('text-center', stackedIcon ? 'gap-5' : 'gap-3')}>
|
||||
<EmptyMedia className="mb-0">
|
||||
{stackedIcon ? (
|
||||
<IconStack aria-hidden="true" className="h-14 w-12">
|
||||
<Icon strokeWidth={1.9} aria-hidden="true" className="size-5" />
|
||||
</IconStack>
|
||||
) : (
|
||||
<IconTile
|
||||
variant="elevated"
|
||||
className="size-10.5 text-muted-foreground"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Icon />
|
||||
</IconTile>
|
||||
)}
|
||||
</EmptyMedia>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<EmptyTitle
|
||||
className={cn(
|
||||
'font-semibold tracking-tight',
|
||||
stackedIcon ? 'text-base' : 'text-sm',
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</EmptyTitle>
|
||||
{description ? (
|
||||
<EmptyDescription className="max-w-sm text-sm/relaxed">
|
||||
{description}
|
||||
</EmptyDescription>
|
||||
) : null}
|
||||
</div>
|
||||
</EmptyHeader>
|
||||
{action ? (
|
||||
<EmptyContent className="mt-1 items-center justify-center">
|
||||
{action}
|
||||
</EmptyContent>
|
||||
) : null}
|
||||
</Empty>
|
||||
)
|
||||
|
||||
if (!centered) return body
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-full flex-1 items-center justify-center py-14 sm:py-16',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{body}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user