Empty State

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleApache-2.0
Installation mix mishka.ui.gen.headless empty_state
Source View Source

Overview of the Phoenix and LiveView Headless Empty State Component

The Mishka Chelekom Headless Empty State is a placeholder for Phoenix and LiveView views that have nothing to show yet: no search results, an empty inbox, a new project. It renders a plain div with no role and no styling. An optional indicator holds an icon or illustration, a body holds the title, the description and any extra content, and an optional actions row holds buttons or links.

title and description are plain-string shorthands. For richer text, put markup in the default slot, which renders after the description. align accepts left, center or right and is exposed as data-align on the root, so CSS can flip the layout. Every part has a class attribute: class, indicator_class, body_class, title_class, description_class and actions_class.

Base UI Empty State example - no results (Phoenix headless)

Base UI Empty State example - no results (Phoenix headless)

No results found
We couldn't find anything matching your search. Try a different keyword.
heex
<.empty_state
  id="baseui-empty-state-hero"
  title="No results found"
  description="We couldn't find anything matching your search. Try a different keyword."
  class="flex w-full max-w-72 flex-col items-center gap-3 text-center"
  indicator_class="flex size-12 items-center justify-center rounded-full bg-neutral-100 text-neutral-500 dark:bg-neutral-800 dark:text-neutral-400"
  body_class="flex flex-col gap-1"
  title_class="text-base font-semibold text-neutral-950 dark:text-white"
  description_class="text-sm text-neutral-600 dark:text-neutral-400"
>
  <:indicator>
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      stroke-width="1.5"
      stroke="currentColor"
      class="size-6"
    >
      <path
        stroke-linecap="round"
        stroke-linejoin="round"
        d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
      />
    </svg>
  </:indicator>
</.empty_state>

Base UI Empty State example - with actions (Phoenix headless)

Base UI Empty State example - with actions (Phoenix headless)

No projects yet
Create your first project to get started. It only takes a minute.
heex
<.empty_state
  id="baseui-empty-state-actions"
  align="left"
  title="No projects yet"
  description="Create your first project to get started. It only takes a minute."
  class="flex w-full max-w-80 flex-col items-start gap-3 text-left"
  indicator_class="flex size-12 items-center justify-center rounded-full bg-neutral-100 text-neutral-500 dark:bg-neutral-800 dark:text-neutral-400"
  body_class="flex flex-col gap-1"
  title_class="text-base font-semibold text-neutral-950 dark:text-white"
  description_class="text-sm text-neutral-600 dark:text-neutral-400"
  actions_class="mt-2 flex gap-2"
>
  <:indicator>
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      stroke-width="1.5"
      stroke="currentColor"
      class="size-6"
    >
      <path
        stroke-linecap="round"
        stroke-linejoin="round"
        d="M12 10.5v6m3-3H9m4.06-7.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z"
      />
    </svg>
  </:indicator>
  <:actions>
    <.button class="rounded-md bg-neutral-950 px-3 py-1.5 text-sm font-medium text-white hover:bg-neutral-800 dark:bg-white dark:text-neutral-950 dark:hover:bg-neutral-200">New project</.button>
    <.button class="rounded-md px-3 py-1.5 text-sm font-medium text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-800">Import</.button>
  </:actions>
</.empty_state>

Announcing a dynamic empty state

The root accepts any global attribute, so the live-region role goes straight on the component.

heex
<.empty_state
  :if={@results == []}
  role="status"
  title="No results found"
  description="Try a different keyword."
  class="..."
/>

Parts & data attributes

The root carries chelekom-empty-state and data-align. Each part has a data-part value and a chelekom-empty-state__* class.

  • indicator holds the :indicator slot. It is decorative and marked aria-hidden.
  • body wraps the title, the description, the default slot and the actions. It is rendered only when at least one of them is present.
  • title and description render from the matching attributes. The title is a div, not a heading. If your page outline needs a heading, leave title out and put one in the default slot.
  • actions holds the :actions slot after the body content.

Accessibility

An empty state has no formal WAI-ARIA pattern, so the root has no role by default. Keep the meaningful information in the title and description text, because the indicator is hidden from assistive technology.