Empty
Displays an empty state with media, title, description, and action content.
No JavaScript Required
No documents found
Upload a document to get started.
empty/default
<%= render Shadcn::Empty.new(class_name: "w-full rounded-lg border border-dashed") do |empty| %>
<% empty.with_header do |header| %>
<% header.with_media(variant: :icon) do %>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<path d="M7 10l5 5 5-5" />
<path d="M12 15V3" />
</svg>
<% end %>
<% header.with_title { "No documents found" } %>
<% header.with_description { "Upload a document to get started." } %>
<% end %>
<% empty.with_content do %>
<%= render Shadcn::Button.new { "Upload document" } %>
<% end %>
<% end %>
Installation
Add the component to your project:
rails generate shadcn:add empty
Usage
<%= render Shadcn::Empty.new(class_name: "w-full rounded-lg border border-dashed") do |empty| %>
<% empty.with_header do |header| %>
<% header.with_media(variant: :icon) do %>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<path d="M7 10l5 5 5-5" />
<path d="M12 15V3" />
</svg>
<% end %>
<% header.with_title { "No documents found" } %>
<% header.with_description { "Upload a document to get started." } %>
<% end %>
<% empty.with_content do %>
<%= render Shadcn::Button.new { "Upload document" } %>
<% end %>
<% end %>
Examples
Outline Style
Use a dashed border for a more subtle empty state.
Cloud Storage Empty
Upload files to your cloud storage to access them anywhere.
<%= render Shadcn::EmptyComponent.new(class_name: "border border-dashed rounded-lg") do |empty| %>
<% empty.with_header do |header| %>
<% header.with_media(variant: :icon) do %>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/></svg>
<% end %>
<% header.with_title { "Cloud Storage Empty" } %>
<% header.with_description { "Upload files to your cloud storage to access them anywhere." } %>
<% end %>
<% empty.with_content do %>
<%= render Shadcn::ButtonComponent.new(variant: :outline, size: :sm) { "Upload Files" } %>
<% end %>
<% end %>
Background Gradient
Add a subtle gradient background for visual interest.
No Notifications
You're all caught up. New notifications will appear here.
<%= render Shadcn::Empty.new(class_name: "bg-gradient-to-b from-muted/50 to-background from-30% rounded-lg") do |empty| %>
<% empty.with_header do |header| %>
<% header.with_media(variant: :icon) do %>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" />
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" />
</svg>
<% end %>
<% header.with_title { "No Notifications" } %>
<% header.with_description { "You're all caught up. New notifications will appear here." } %>
<% end %>
<% empty.with_content do %>
<%= render Shadcn::Button.new(variant: :outline, size: :sm) do %>
<svg class="mr-2 h-4 w-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" />
<path d="M21 3v5h-5" />
</svg>
Refresh
<% end %>
<% end %>
<% end %>
With Avatar
Use the default media variant to display an avatar or image.
User Offline
This user is currently offline. You can leave a message or try again later.
<%= render Shadcn::EmptyComponent.new do |empty| %>
<% empty.with_header do |header| %>
<% header.with_media do %>
<%= render Shadcn::AvatarComponent.new(
src: "https://github.com/shadcn.png",
alt: "User",
size: :lg,
class_name: "grayscale"
) %>
<% end %>
<% header.with_title { "User Offline" } %>
<% header.with_description { "This user is currently offline. You can leave a message or try again later." } %>
<% end %>
<% empty.with_content do %>
<%= render Shadcn::ButtonComponent.new(size: :sm) { "Leave Message" } %>
<% end %>
<% end %>
404 Page
Use for error pages with a search input.
404 - Not Found
The page you're looking for doesn't exist. Try searching below.
Need help? Contact support
<%= render Shadcn::EmptyComponent.new do |empty| %>
<% empty.with_header do |header| %>
<% header.with_title { "404 - Not Found" } %>
<% header.with_description { "The page you're looking for doesn't exist. Try searching below." } %>
<% end %>
<% empty.with_content do %>
<div class="w-full max-w-sm">
<%= render Shadcn::InputGroupComponent.new do |group| %>
<% group.with_input(placeholder: "Try searching for pages...") %>
<% group.with_suffix do %>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
<% end %>
<% end %>
</div>
<p class="text-sm text-muted-foreground">
Need help? <a href="#" class="text-primary underline-offset-4 hover:underline">Contact support</a>
</p>
<% end %>
<% end %>
API Reference
EmptyComponent
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| class_name |
String
|
nil
|
Additional CSS classes to apply |
EmptyMediaComponent
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| variant |
Symbol
|
:default
|
Media variant - :default or :icon |
| class_name |
String
|
nil
|
Additional CSS classes to apply |
Slots
| Slot | Description |
|---|---|
| with_header | Header section containing media, title, and description |
| with_media(variant:) | Media slot for icons, avatars, or images. Use variant: :icon for icon styling. |
| with_title | Title text for the empty state |
| with_description | Description text explaining the empty state |
| with_content | Action content area (buttons, inputs, etc.) |
Accessibility
- Empty states should provide clear guidance on what the user can do next
- Use appropriate heading levels for the title based on page context
- Ensure action buttons are keyboard accessible
- Consider using aria-live regions if the empty state appears dynamically
On This Page