No messages yet
When you receive a message, it will show up here.
import { InboxIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
export default function EmptyDemo() {
return (
<Empty className="border">
<EmptyHeader>
<EmptyMedia variant="icon">
<InboxIcon />
</EmptyMedia>
<EmptyTitle>No messages yet</EmptyTitle>
<EmptyDescription>
When you receive a message, it will show up here.
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button size="sm">Compose message</Button>
</EmptyContent>
</Empty>
)
}Installation
npx logic2b@latest add emptyWorking with an AI assistant? Copy this prompt into Claude Code, Cursor or Copilot — it carries the install steps, a no-CLI fallback and a verification checklist.
Add the "empty" item from the logic2b ui registry (https://ui.logic2b.com) to this project. Follow every step and verify at the end. ## Steps 1. If the project has no `components.json` yet, set up logic2b ui first: ```bash npx logic2b@latest init ``` 2. Install the item (the CLI resolves registry dependencies automatically): ```bash npx logic2b@latest add empty ``` 3. Install any npm dependencies the command prints. ## If the CLI is not available Do it manually from the registry payload: 1. Fetch https://ui.logic2b.com/r/empty.json. 2. Write every entry in `files[]` to its mapped project path (see below). 3. Repeat (recursively) for each name in `registryDependencies`. 4. Install every package listed in `dependencies` across those payloads. ## Registry reference - Index of every item: https://ui.logic2b.com/r/index.json - Item payload (full source): https://ui.logic2b.com/r/<name>.json - Usage examples per item: https://ui.logic2b.com/r/demos/index.json → https://ui.logic2b.com/r/demos/<demo>.json - Docs index for agents: https://ui.logic2b.com/llms.txt (full docs: https://ui.logic2b.com/llms-full.txt) - Every docs page is Markdown when you append `.md` to its URL. Registry file paths map to project paths like this: - `ui/*` → `@/components/ui/*` - `blocks/<name>/*` → `@/components/*` - `charts/*` → `@/components/charts/*` - `hooks/*` → `@/hooks/*` - `lib/utils.ts` → `@/lib/utils.ts` - `theme.css` → next to the project's Tailwind entry stylesheet ## Conventions (do not break these) - Tailwind CSS v4 (CSS-first config; no tailwind.config.js needed) and React 19. - All colors go through semantic tokens (`bg-primary`, `text-muted-foreground`, `border-border`, …). Never hardcode hex/oklch values in components. - Dark mode is class-based: toggle `.dark` on `<html>`. - Icons come from lucide-react. ## Verify before finishing 1. The dev server starts and the app renders without console errors. 2. TypeScript compiles (`tsc --noEmit` or the framework's check). 3. Components use the theme: a `<Button>` shows the primary token color, and toggling `.dark` on `<html>` switches the palette.
Install the dependencies:
npm install class-variance-authorityCopy into ui/empty.tsx:
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
function Empty({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="empty"
className={cn(
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
className
)}
{...props}
/>
)
}
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="empty-header"
className={cn(
"flex max-w-sm flex-col items-center gap-2 text-center",
className
)}
{...props}
/>
)
}
const emptyMediaVariants = cva(
"mb-2 flex shrink-0 items-center justify-center [&_svg:not([class*='size-'])]:size-6 [&_svg]:pointer-events-none",
{
variants: {
variant: {
default: "bg-transparent",
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
},
},
defaultVariants: {
variant: "default",
},
}
)
function EmptyMedia({
className,
variant = "default",
...props
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
return (
<div
data-slot="empty-media"
data-variant={variant}
className={cn(emptyMediaVariants({ variant, className }))}
{...props}
/>
)
}
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="empty-title"
className={cn("text-lg font-medium tracking-tight", className)}
{...props}
/>
)
}
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
return (
<p
data-slot="empty-description"
className={cn(
"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
className
)}
{...props}
/>
)
}
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="empty-content"
className={cn(
"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance",
className
)}
{...props}
/>
)
}
export {
Empty,
EmptyHeader,
EmptyTitle,
EmptyDescription,
EmptyContent,
EmptyMedia,
}Usage
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
<Empty>
<EmptyHeader>
<EmptyMedia variant="icon">
<InboxIcon />
</EmptyMedia>
<EmptyTitle>No messages yet</EmptyTitle>
<EmptyDescription>
When you receive a message, it will show up here.
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button size="sm">Compose message</Button>
</EmptyContent>
</Empty>
API
| Prop | Type | Default |
|---|---|---|
variant (EmptyMedia) |
default | icon |
default |
Examples
With Actions
No projects yet
Create your first project to get started.
import { CloudIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
export default function EmptyActionsDemo() {
return (
<Empty className="border">
<EmptyHeader>
<EmptyMedia variant="icon">
<CloudIcon />
</EmptyMedia>
<EmptyTitle>No projects yet</EmptyTitle>
<EmptyDescription>
Create your first project to get started.
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<div className="flex gap-2">
<Button size="sm">Create project</Button>
<Button size="sm" variant="outline">
Import
</Button>
</div>
</EmptyContent>
</Empty>
)
}Minimal
404 — Not Found
The page you are looking for does not exist. Go home.
import {
Empty,
EmptyDescription,
EmptyHeader,
EmptyTitle,
} from "@/components/ui/empty"
export default function EmptySimpleDemo() {
return (
<Empty className="border">
<EmptyHeader>
<EmptyTitle>404 — Not Found</EmptyTitle>
<EmptyDescription>
The page you are looking for does not exist. <a href="#">Go home</a>.
</EmptyDescription>
</EmptyHeader>
</Empty>
)
}