A responsive empty-state surface with media, concise guidance, and a dedicated action area.
All caught up
New requests will appear here. Invite a teammate to start collaborating.
import { Inbox } from "lucide-react"
import {
Empty,
EmptyMedia,
EmptyTitle,
EmptyDescription,
EmptyAction,
} from "@/components/ballmac/empty"
import { buttonVariants } from "@/components/ballmac/button"
export default function EmptyDemo() {
return (
<Empty className="max-w-md">
<EmptyMedia>
<Inbox />
</EmptyMedia>
<EmptyTitle>All caught up</EmptyTitle>
<EmptyDescription>
New requests will appear here. Invite a teammate to start collaborating.
</EmptyDescription>
<EmptyAction>
<a href="#invite" className={buttonVariants({ size: "sm" })}>
Invite teammate
</a>
</EmptyAction>
</Empty>
)
}Installation
$ pnpm dlx shadcn@latest add @ballmac/emptyCopy the source into your project.
components/ballmac/empty.tsx// Ballmac UI: Empty. https://ui.ballmac.com/components/empty // Based on shadcn/ui Empty (MIT, Copyright (c) 2023 shadcn), adding a compact surface and an explicit action slot. import * as React from "react" import { cn } from "@/lib/utils" type EmptyProps = React.ComponentProps<"div"> & { /** Reduce vertical space when the empty state sits inside a panel. */ compact?: boolean } function Empty({ className, compact = false, ...props }: EmptyProps) { return ( <div data-slot="empty" data-compact={compact} className={cn( "flex w-full min-w-0 flex-col items-center justify-center rounded-xl border border-dashed border-border bg-card/50 px-5 py-10 text-center data-[compact=true]:py-6", className, )} {...props} /> ) } function EmptyMedia({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="empty-media" aria-hidden="true" className={cn( "bg-muted text-muted-foreground mb-4 flex size-11 items-center justify-center rounded-xl [&>svg]:size-5", className, )} {...props} /> ) } function EmptyTitle({ className, ...props }: React.ComponentProps<"h3">) { return ( <h3 data-slot="empty-title" className={cn("text-foreground text-sm font-semibold", className)} {...props} /> ) } function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) { return ( <p data-slot="empty-description" className={cn( "text-muted-foreground mt-1 max-w-sm text-sm leading-relaxed", className, )} {...props} /> ) } function EmptyAction({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="empty-action" className={cn( "mt-5 flex flex-wrap items-center justify-center gap-2", className, )} {...props} /> ) } export { Empty, EmptyMedia, EmptyTitle, EmptyDescription, EmptyAction, type EmptyProps, }Update the import paths to match your project setup.
Usage
import { Empty, EmptyMedia, EmptyTitle, EmptyDescription, EmptyAction } from "@/components/ballmac/empty"The full example is in the Code tab above.
Examples
States and variants
No results for “quarterly”
Try a different term or clear your filters.
import { Search } from "lucide-react"
import {
Empty,
EmptyMedia,
EmptyTitle,
EmptyDescription,
} from "@/components/ballmac/empty"
export default function EmptyStates() {
return (
<Empty compact className="max-w-sm">
<EmptyMedia>
<Search />
</EmptyMedia>
<EmptyTitle>No results for “quarterly”</EmptyTitle>
<EmptyDescription>
Try a different term or clear your filters.
</EmptyDescription>
</Empty>
)
}API reference
| Prop | Type | Default |
|---|---|---|
compactReduce vertical space when the empty state sits inside a panel. | boolean | false |
Also accepts the standard attributes of its root element.
Accessibility
| Key | Action |
|---|---|
| Tab | reaches actions in the empty state |
Use with AI
A responsive empty-state surface with media, concise guidance, and a dedicated action area. With the shadcn MCP server set up (guide), ask your agent:
Add the Ballmac UI Empty (@ballmac/empty) to this project with the shadcn MCP, then use it where it fits.
Use it for
- Explain why a list has no content
- Give the next step after a search yields no results
Not for
- Use a skeleton while loading
Registry JSON: https://ui.ballmac.com/r/empty.json
Credits
Based on shadcn/ui Empty, adapted by Ballmac. Free to use in personal and commercial projects.
- npm
- None
- Registry
- shadcn/utils
Pairs well with
Button
A button with six variants, three sizes, a pill shape and a built-in loading state. buttonVariants() styles links the same way.
Alert Dialog
Focus-managed confirmation for consequential actions, with a clear cancel path, optional media, and a token-based destructive action.
Alert
A semantic callout with five theme-aware tones, clear icon placement, an action row, and opt-in urgent announcements.
Banner
A page-wide announcement with semantic tones, optional action, and controlled or local dismissal.