Installation
Install the dependencies
pnpm add cn class-variance-authorityCopy the component
Copy the following files into src/lib/components/ui/empty.
<script lang="ts">
import type { EmptyProps } from './types.js';
import { cn } from 'cn';
let { children, class: classProp, ...props }: EmptyProps = $props();
</script>
<div data-slot="empty" {...props} class={cn('gap-4 rounded-xl border-dashed p-6 flex w-full min-w-0 flex-1 flex-col items-center justify-center text-center text-balance', classProp)}>
{@render children?.()}
</div><script lang="ts">
import type { EmptyContentProps } from './types.js';
import { cn } from 'cn';
let { children, class: classProp, ...props }: EmptyContentProps = $props();
</script>
<div data-slot="empty-content" {...props} class={cn('gap-2.5 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance', classProp)}>
{@render children?.()}
</div><script lang="ts">
import type { EmptyDescriptionProps } from './types.js';
import { cn } from 'cn';
let { children, class: classProp, ...props }: EmptyDescriptionProps = $props();
</script>
<div data-slot="empty-description" {...props} class={cn('text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary', classProp)}>
{@render children?.()}
</div><script lang="ts">
import type { EmptyHeaderProps } from './types.js';
import { cn } from 'cn';
let { children, class: classProp, ...props }: EmptyHeaderProps = $props();
</script>
<div data-slot="empty-header" {...props} class={cn('gap-2 flex max-w-sm flex-col items-center', classProp)}>
{@render children?.()}
</div><script lang="ts">
import type { EmptyMediaProps } from './types.js';
import { cn } from 'cn';
import { emptyMediaVariants } from './variants.js';
let { children, class: classProp, variant = 'default', ...props }: EmptyMediaProps = $props();
</script>
<div data-slot="empty-icon" data-variant={variant} {...props} class={cn(emptyMediaVariants({ variant, class: classProp }))}>
{@render children?.()}
</div><script lang="ts">
import type { EmptyTitleProps } from './types.js';
import { cn } from 'cn';
let { children, class: classProp, ...props }: EmptyTitleProps = $props();
</script>
<div data-slot="empty-title" {...props} class={cn('text-sm font-medium tracking-tight', classProp)}>
{@render children?.()}
</div>import type { HTMLAttributes } from 'svelte/elements';
import type { EmptyMediaVariants } from './variants.js';
type NativeEmptyProps = HTMLAttributes<HTMLDivElement>;
export type EmptyProps = NativeEmptyProps;
export type EmptyHeaderProps = NativeEmptyProps;
export type EmptyTitleProps = NativeEmptyProps;
export type EmptyDescriptionProps = NativeEmptyProps;
export type EmptyContentProps = NativeEmptyProps;
export type EmptyMediaProps = NativeEmptyProps & EmptyMediaVariants;// Adapted from shadcn-ui/ui d75a96ab; MIT: packages/ui/THIRD_PARTY_NOTICES.md.
import { cva } from 'class-variance-authority';
import type { VariantProps } from 'class-variance-authority';
export const emptyMediaVariants = cva('mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0', {
variants: { variant: { default: 'bg-transparent', icon: "bg-muted text-foreground flex size-8 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-4" } },
defaultVariants: { variant: 'default' },
});
export type EmptyMediaVariants = VariantProps<typeof emptyMediaVariants>;export { default as Empty } from './Empty.svelte';
export { default as EmptyHeader } from './EmptyHeader.svelte';
export { default as EmptyTitle } from './EmptyTitle.svelte';
export { default as EmptyDescription } from './EmptyDescription.svelte';
export { default as EmptyContent } from './EmptyContent.svelte';
export { default as EmptyMedia } from './EmptyMedia.svelte';
export type { EmptyProps, EmptyHeaderProps, EmptyTitleProps, EmptyDescriptionProps, EmptyContentProps, EmptyMediaProps } from './types.js';Update the import paths
Change the imports to match your project setup.
Usage
<script lang="ts">
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '$lib/components/ui/empty';
</script><Empty>
<EmptyHeader>
<EmptyMedia variant="icon">
<FolderIcon />
</EmptyMedia>
<EmptyTitle>No data</EmptyTitle>
<EmptyDescription>No data found</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button>Add data</Button>
</EmptyContent>
</Empty>