Skip to main content

Empty State — Maquina Components

Empty State component for Rails. Placeholder for no-data scenarios with icons and actions. ERB partial with Tailwind CSS. Copy, paste, customize.

Quick Reference

Helper Methods

Method Description
empty_state Simple API for common empty states
empty_search_state Pre-configured for search results
empty_list_state Pre-configured for empty lists/tables

Parts

Part Description
components/empty Root container
components/empty/header Groups media, title, and description
components/empty/media Icon or illustration container
components/empty/title Heading text
components/empty/description Supporting text
components/empty/actions CTA buttons container

Parameters

empty

Parameter Type Default Description
css_classes String "" Additional CSS classes
**html_options Hash {} HTML attributes

empty/media

Parameter Type Default Description
icon Symbol nil Icon name (uses icon_for helper)
icon_class String "size-10" Icon size classes
css_classes String "" Additional CSS classes

empty/title

Parameter Type Default Description
text String nil Title text (or use block)
css_classes String "" Additional CSS classes

empty/description

Parameter Type Default Description
text String nil Description text (or use block)
css_classes String "" Additional CSS classes

Data Attributes

Component Identifiers

Attribute Element Description
data-component="empty" Container div Main component identifier
data-empty-part="header" Header div Header section
data-empty-part="media" Media div Icon/illustration container
data-empty-part="title" Title element Heading
data-empty-part="description" Description element Supporting text
data-empty-part="actions" Actions div Buttons container

Basic Usage

<%= empty_state(
  icon: :inbox,
  title: "No messages",
  description: "Get started by sending your first message."
) do %>
  <%= link_to "Compose", new_message_path, data: { component: "button", variant: "primary" } %>
<% end %>

Using Partials

<%= render "components/empty" do %>
  <%= render "components/empty/header" do %>
    <%= render "components/empty/media", icon: :inbox %>
    <%= render "components/empty/title", text: "No messages" %>
    <%= render "components/empty/description", text: "Get started by sending your first message." %>
  <% end %>
  <%= render "components/empty/actions" do %>
    <%= link_to "Compose", new_message_path, data: { component: "button", variant: "primary" } %>
  <% end %>
<% end %>

Examples

Search Results Empty

<%= empty_search_state(query: @query) %>

Renders:

 No results found
We couldn't find anything matching "your query".

List/Table Empty

<%= empty_list_state(
  resource: "projects",
  new_path: new_project_path
) %>

Renders:

 No projects yet
Get started by creating your first project.
[Create Project]

With Custom Icon

<%= render "components/empty" do %>
  <%= render "components/empty/header" do %>
    <%= render "components/empty/media", icon: :users, icon_class: "size-12 text-primary" %>
    <%= render "components/empty/title", text: "No team members" %>
    <%= render "components/empty/description", text: "Invite people to collaborate." %>
  <% end %>
  <%= render "components/empty/actions" do %>
    <%= link_to "Invite", invite_path, data: { component: "button", variant: "primary" } %>
    <%= link_to "Learn more", help_path, data: { component: "button", variant: "outline" } %>
  <% end %>
<% end %>

With Illustration (Custom Media)

<%= render "components/empty" do %>
  <%= render "components/empty/header" do %>
    <%= render "components/empty/media" do %>
      <%= image_tag "illustrations/empty-inbox.svg", class: "w-48 h-48" %>
    <% end %>
    <%= render "components/empty/title", text: "Your inbox is empty" %>
    <%= render "components/empty/description", text: "Messages you receive will appear here." %>
  <% end %>
<% end %>

Minimal (No Actions)

<%= render "components/empty" do %>
  <%= render "components/empty/header" do %>
    <%= render "components/empty/media", icon: :check_circle, icon_class: "size-8 text-success" %>
    <%= render "components/empty/title", text: "All caught up!" %>
    <%= render "components/empty/description", text: "You have no pending tasks." %>
  <% end %>
<% end %>

Real-World Patterns

In a Table

<table data-component="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Role</th>
    </tr>
  </thead>
  <tbody>
    <% if @users.empty? %>
      <tr>
        <td colspan="3">
          <%= empty_list_state(resource: "users", new_path: new_user_path) %>
        </td>
      </tr>
    <% else %>
      <% @users.each do |user| %>
        <tr>...</tr>
      <% end %>
    <% end %>
  </tbody>
</table>
<% if @results.empty? %>
  <%= empty_search_state(query: params[:q]) do %>
    <%= link_to "Clear search", products_path, data: { component: "button", variant: "outline" } %>
  <% end %>
<% else %>
<% end %>

Conditional by State

<% if @projects.empty? && @filter == "archived" %>
  <%= empty_state(
    icon: :archive,
    title: "No archived projects",
    description: "Projects you archive will appear here."
  ) %>
<% elsif @projects.empty? %>
  <%= empty_list_state(resource: "projects", new_path: new_project_path) %>
<% end %>

Theme Variables

var(--muted-foreground)  /* Icon and description color */
var(--foreground)        /* Title color */

Customization

Compact Empty State

<%= render "components/empty", css_classes: "py-8" do %>
  <%= render "components/empty/header" do %>
    <%= render "components/empty/media", icon: :inbox, icon_class: "size-6" %>
    <%= render "components/empty/title", text: "No items", css_classes: "text-sm" %>
  <% end %>
<% end %>

Full-Page Empty State

<%= render "components/empty", css_classes: "min-h-[60vh]" do %>
<% end %>

Accessibility

  • Uses semantic structure (heading for title)
  • Icon has aria-hidden="true" (decorative)
  • Description provides context
  • Action buttons are keyboard accessible

File Structure

app/views/components/
├── _empty.html.erb
└── empty/
    ├── _header.html.erb
    ├── _media.html.erb
    ├── _title.html.erb
    ├── _description.html.erb
    └── _actions.html.erb

app/assets/stylesheets/empty.css
app/helpers/maquina_components/empty_helper.rb
docs/empty.md