Empty state
UI::EmptyStateWhat a page shows when it has nothing to list yet, with a way to add the first thing.
# VelvetKit
## Empty state (`UI::EmptyState`)
What a page shows when it has nothing to list yet, with a way to add the first thing.
Add it: `bin/rails generate velvetkit:add empty_state`
Also adds: `icon`
### Arguments
```ruby
UI::EmptyState.new(title: nil, description: nil, icon: nil, variant: :default, heading_level: 3, class: nil, **html_attrs)
```
Slots: `with_media`
### Notes
What a page shows in place of a list with nothing in it: an icon, a title,
a line saying why, and the buttons that get someone started. The block is
the actions row; `with_media` replaces the icon with an avatar, image or
anything else.
`variant: :outline` draws a dashed border, for an empty area inside a page
rather than the whole page. `heading_level:` sets the title's <h1>–<h6> so
it fits the page's outline (default 3).
### Example: With Actions
```erb
<%= render(UI::EmptyState.new(icon: "folder-kanban", title: "No projects yet", description: "You haven't created any projects. Start one from scratch or import an existing repository.")) do %>
<%= render(UI::Button.new) do |btn| %><% btn.with_leading_icon(name: "plus") %>Create project<% end %>
<%= render(UI::Button.new(variant: :outline)) { "Import" } %>
<% end %>
```
### Example: Outline
```erb
<%= render(UI::EmptyState.new(icon: "upload", variant: :outline, title: "No files", description: "Upload a contract, invoice or receipt to keep it with this client.")) do %>
<%= render(UI::Button.new(variant: :outline, size: :sm)) { "Upload a file" } %>
<% end %>
```
### Example: No Search Results
```erb
<%= render(UI::EmptyState.new(icon: "search", title: "No results for “invoce”", description: "Check the spelling, or try a shorter search.")) do %>
<%= render(UI::Button.new(variant: :ghost, size: :sm)) { "Clear search" } %>
<% end %>
```
### Example: With an Avatar
```erb
<%= render(UI::EmptyState.new(title: "Nobody else is here", description: "Invite your team to share projects and reply to customers together.")) do |empty| %>
<% empty.with_media do %>
<%= render(UI::AvatarGroup.new(size: :lg)) do |group| %>
<% %w[JD AS RM].each { |initials| group.with_avatar { initials } } %>
<% end %>
<% end %>
<%= render(UI::Button.new(size: :sm)) do |btn| %><% btn.with_leading_icon(name: "users") %>Invite people<% end %>
<% end %>
```
### Example: In a Card
```erb
<div class="max-w-md">
<%= render(UI::Card.new) do |card| %>
<% card.with_content do %>
<%= render(UI::EmptyState.new(icon: "bell", heading_level: 4, class: "md:p-8", title: "No notifications", description: "We'll let you know when a build fails or someone mentions you.")) %>
<% end %>
<% end %>
</div>
```
bin/rails generate velvetkit:add empty_state
- Also adds
- Icon
- Stimulus
- None, it's server-rendered
- Installs
- Nothing
Examples
With Actions
No projects yet
You haven't created any projects. Start one from scratch or import an existing repository.
with_actions.html.erb
<%= render(UI::EmptyState.new(icon: "folder-kanban", title: "No projects yet", description: "You haven't created any projects. Start one from scratch or import an existing repository.")) do %>
<%= render(UI::Button.new) do |btn| %><% btn.with_leading_icon(name: "plus") %>Create project<% end %>
<%= render(UI::Button.new(variant: :outline)) { "Import" } %>
<% end %>
Outline
No files
Upload a contract, invoice or receipt to keep it with this client.
outline.html.erb
<%= render(UI::EmptyState.new(icon: "upload", variant: :outline, title: "No files", description: "Upload a contract, invoice or receipt to keep it with this client.")) do %>
<%= render(UI::Button.new(variant: :outline, size: :sm)) { "Upload a file" } %>
<% end %>
No Search Results
No results for “invoce”
Check the spelling, or try a shorter search.
no_results.html.erb
<%= render(UI::EmptyState.new(icon: "search", title: "No results for “invoce”", description: "Check the spelling, or try a shorter search.")) do %>
<%= render(UI::Button.new(variant: :ghost, size: :sm)) { "Clear search" } %>
<% end %>
With an Avatar
Nobody else is here
Invite your team to share projects and reply to customers together.
with_media.html.erb
<%= render(UI::EmptyState.new(title: "Nobody else is here", description: "Invite your team to share projects and reply to customers together.")) do |empty| %>
<% empty.with_media do %>
<%= render(UI::AvatarGroup.new(size: :lg)) do |group| %>
<% %w[JD AS RM].each { |initials| group.with_avatar { initials } } %>
<% end %>
<% end %>
<%= render(UI::Button.new(size: :sm)) do |btn| %><% btn.with_leading_icon(name: "users") %>Invite people<% end %>
<% end %>
In a Card
No notifications
We'll let you know when a build fails or someone mentions you.
in_card.html.erb
<div class="max-w-md">
<%= render(UI::Card.new) do |card| %>
<% card.with_content do %>
<%= render(UI::EmptyState.new(icon: "bell", heading_level: 4, class: "md:p-8", title: "No notifications", description: "We'll let you know when a build fails or someone mentions you.")) %>
<% end %>
<% end %>
</div>
API
Arguments
UI::EmptyState.new(title: nil, description: nil, icon: nil, variant: :default, heading_level: 3, class: nil, **html_attrs)
Slots:
with_media
Notes
What a page shows in place of a list with nothing in it: an icon, a title,
a line saying why, and the buttons that get someone started. The block is
the actions row; `with_media` replaces the icon with an avatar, image or
anything else.
`variant: :outline` draws a dashed border, for an empty area inside a page
rather than the whole page. `heading_level:` sets the title's <h1>–<h6> so
it fits the page's outline (default 3).