No Projects Yet
You haven't created any projects yet. Get started by creating your first project.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import FolderCodeIcon from "@tabler/icons-svelte/icons/folder-code";
import ArrowUpRightIcon from "@lucide/svelte/icons/arrow-up-right";
</script>
<Empty.Root>
<Empty.Header>
<Empty.Media variant="icon">
<FolderCodeIcon />
</Empty.Media>
<Empty.Title>No Projects Yet</Empty.Title>
<Empty.Description>
You haven't created any projects yet. Get started by creating your first
project.
</Empty.Description>
</Empty.Header>
<Empty.Content>
<div class="flex gap-2">
<Button>Create Project</Button>
<Button variant="outline">Import Project</Button>
</div>
</Empty.Content>
<Button variant="link" class="text-muted-foreground" size="sm">
<a href="/docs">
Learn More <ArrowUpRightIcon class="inline" />
</a>
</Button>
</Empty.Root> Installation
pnpm dlx shadcn-svelte@latest add empty Copy and paste the following code into your project.
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="empty-content"
class={cn(
'flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-zinc-300 text-balance',
className
)}
{...restProps}
>
{@render children?.()}
</div>
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="empty-description"
class={cn(
'mt-0.5 text-sm/relaxed text-zinc-500 [&>a]:text-[#d0e891] [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-[#d0e891]',
className
)}
{...restProps}
>
{@render children?.()}
</div>
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="empty-header"
class={cn('flex max-w-sm flex-col items-center gap-2', className)}
{...restProps}
>
{@render children?.()}
</div>
<script lang="ts" module>
import { tv, type VariantProps } from 'tailwind-variants';
export const emptyMediaVariants = tv({
base: 'mb-2 flex shrink-0 items-center justify-center text-zinc-400 [&_svg]:pointer-events-none [&_svg]:shrink-0',
variants: {
variant: {
default: 'bg-transparent',
icon: "flex size-10 shrink-0 items-center justify-center border border-zinc-800 bg-zinc-950 text-[#d0e891] [&_svg:not([class*='size-'])]:size-5"
}
},
defaultVariants: {
variant: 'default'
}
});
export type EmptyMediaVariant = VariantProps<typeof emptyMediaVariants>['variant'];
</script>
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
variant = 'default',
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { variant?: EmptyMediaVariant } = $props();
</script>
<div
bind:this={ref}
data-slot="empty-icon"
data-variant={variant}
class={cn(emptyMediaVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</div>
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="empty-title"
class={cn('font-mono text-lg font-semibold tracking-[0.14em] text-zinc-100 uppercase', className)}
{...restProps}
>
{@render children?.()}
</div>
<script lang="ts">
import { cn, type WithElementRef } from '$UTILS$.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="empty"
class={cn(
'flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 border border-dashed border-zinc-800 bg-background p-12 text-center text-zinc-100 text-balance',
className
)}
{...restProps}
>
{@render children?.()}
</div>
import Root from './empty.svelte';
import Header from './empty-header.svelte';
import Media from './empty-media.svelte';
import Title from './empty-title.svelte';
import Description from './empty-description.svelte';
import Content from './empty-content.svelte';
export {
Root,
Header,
Media,
Title,
Description,
Content,
//
Root as Empty,
Header as EmptyHeader,
Media as EmptyMedia,
Title as EmptyTitle,
Description as EmptyDescription,
Content as EmptyContent
};
Usage
<script lang="ts">
import * as Empty from '$lib/components/ui/empty/index.js';
import FolderCodeIcon from '@tabler/icons-svelte/icons/folder-code';
</script> <Empty.Root>
<Empty.Header>
<Empty.Media variant="icon">
<FolderCodeIcon />
</Empty.Media>
<Empty.Title>No data</Empty.Title>
<Empty.Description>No data found</Empty.Description>
</Empty.Header>
<Empty.Content>
<Button>Add data</Button>
</Empty.Content>
</Empty.Root> Examples
Outline
Use the border utility class to create an outline empty state.
Cloud Storage Empty
Upload files to your cloud storage to access them anywhere.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import CloudIcon from "@tabler/icons-svelte/icons/cloud";
</script>
<Empty.Root class="border border-dashed">
<Empty.Header>
<Empty.Media variant="icon">
<CloudIcon />
</Empty.Media>
<Empty.Title>Cloud Storage Empty</Empty.Title>
<Empty.Description>
Upload files to your cloud storage to access them anywhere.
</Empty.Description>
</Empty.Header>
<Empty.Content>
<Button variant="outline" size="sm">Upload Files</Button>
</Empty.Content>
</Empty.Root> Background
Use the bg-* and bg-gradient-* utilities to add a background to the empty state.
No Notifications
You're all caught up. New notifications will appear here.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import BellIcon from "@tabler/icons-svelte/icons/bell";
import RefreshCcwIcon from "@lucide/svelte/icons/refresh-ccw";
</script>
<Empty.Root
class="from-muted/50 to-background h-full bg-gradient-to-b from-30%"
>
<Empty.Header>
<Empty.Media variant="icon">
<BellIcon />
</Empty.Media>
<Empty.Title>No Notifications</Empty.Title>
<Empty.Description
>You're all caught up. New notifications will appear here.</Empty.Description
>
</Empty.Header>
<Empty.Content>
<Button variant="outline" size="sm">
<RefreshCcwIcon />
Refresh
</Button>
</Empty.Content>
</Empty.Root> Avatar
Use the EmptyMedia component to display an avatar in the empty state.
LR
User Offline
This user is currently offline. You can leave a message to notify them or try again later.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import * as Avatar from "$lib/components/ui/avatar/index.js";
</script>
<Empty.Root>
<Empty.Header>
<Empty.Media variant="default">
<Avatar.Root class="size-12">
<Avatar.Image src="https://github.com/shadcn.png" class="grayscale" />
<Avatar.Fallback>LR</Avatar.Fallback>
</Avatar.Root>
</Empty.Media>
<Empty.Title>User Offline</Empty.Title>
<Empty.Description>
This user is currently offline. You can leave a message to notify them or
try again later.
</Empty.Description>
</Empty.Header>
<Empty.Content>
<Button size="sm">Leave Message</Button>
</Empty.Content>
</Empty.Root> Avatar Group
Use the EmptyMedia component to display an avatar group in the empty state.
CN
LR
ER
No Team Members
Invite your team to collaborate on this project.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import * as Avatar from "$lib/components/ui/avatar/index.js";
import PlusIcon from "@lucide/svelte/icons/plus";
</script>
<Empty.Root class="flex-none border">
<Empty.Header>
<Empty.Media>
<Avatar.Group class="grayscale">
<Avatar.Root>
<Avatar.Image src="https://github.com/shadcn.png" alt="@shadcn" />
<Avatar.Fallback>CN</Avatar.Fallback>
</Avatar.Root>
<Avatar.Root>
<Avatar.Image
src="https://github.com/maxleiter.png"
alt="@maxleiter"
/>
<Avatar.Fallback>LR</Avatar.Fallback>
</Avatar.Root>
<Avatar.Root>
<Avatar.Image
src="https://github.com/evilrabbit.png"
alt="@evilrabbit"
/>
<Avatar.Fallback>ER</Avatar.Fallback>
</Avatar.Root>
</Avatar.Group>
</Empty.Media>
<Empty.Title>No Team Members</Empty.Title>
<Empty.Description
>Invite your team to collaborate on this project.</Empty.Description
>
</Empty.Header>
<Empty.Content>
<Button size="sm">
<PlusIcon />
Invite Members
</Button>
</Empty.Content>
</Empty.Root> InputGroup
You can add an InputGroup component to the EmptyContent component.
404 - Not Found
The page you're looking for doesn't exist. Try searching for what you need below.
/
Need help? Contact support
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import * as InputGroup from "$lib/components/ui/input-group/index.js";
import * as Kbd from "$lib/components/ui/kbd/index.js";
import SearchIcon from "@lucide/svelte/icons/search";
</script>
<Empty.Root>
<Empty.Header>
<Empty.Title>404 - Not Found</Empty.Title>
<Empty.Description>
The page you're looking for doesn't exist. Try searching for what you need
below.
</Empty.Description>
</Empty.Header>
<Empty.Content>
<InputGroup.Root class="sm:w-3/4">
<InputGroup.Input placeholder="Try searching for pages..." />
<InputGroup.Addon>
<SearchIcon />
</InputGroup.Addon>
<InputGroup.Addon align="inline-end">
<Kbd.Root>/</Kbd.Root>
</InputGroup.Addon>
</InputGroup.Root>
<Empty.Description>
Need help? <a href="/docs">Contact support</a>
</Empty.Description>
</Empty.Content>
</Empty.Root>