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

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