Card

v0.0.10

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

Overview of the Phoenix and LiveView Headless Card Component

The Mishka Chelekom Headless Card is a block of content with an optional figure, a title, a body and a row of actions. It has no JavaScript and no styling. What it adds is markup that is easy to get wrong by hand: the :title slot renders a real heading, an h3 unless you pick another level, and the root points at that heading with aria-labelledby.

Add href, navigate or patch and the whole card becomes a link. That is the correct markup for a card that is one big click target, and it has a single focus stop. In a Phoenix app with LiveView, navigate and patch behave like the same attributes on .link. Each part takes its own class attribute: class for the root, then figure_class, body_class, title_class, content_class and actions_class.

Base UI Card example - titled card with an action (Phoenix headless)

Base UI Card example - titled card with an action (Phoenix headless)

Weekly digest

A summary of everything that changed since Monday.
heex
<.card
  id="baseui-card-hero"
  class="w-full max-w-80 rounded-lg border border-neutral-200 bg-white text-neutral-950 dark:border-neutral-800 dark:bg-neutral-950 dark:text-white"
  body_class="flex flex-col gap-2 p-4"
  title_class="text-base font-medium"
  actions_class="flex justify-end pt-2"
>
  <:title>Weekly digest</:title>
  <span class="text-sm text-neutral-600 dark:text-neutral-400">
    A summary of everything that changed since Monday.
  </span>
  <:actions>
    <button type="button" class="inline-flex items-center justify-center gap-2 rounded-md border px-3 py-1.5 text-sm font-medium border-neutral-200 text-neutral-950 dark:border-neutral-800 dark:text-white hover:bg-neutral-100 dark:hover:bg-neutral-800 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-950 dark:focus-visible:outline-white">Read</button>
  </:actions>
</.card>

Parts & data attributes

Each part carries a stable data-part and a chelekom-card__* class you can target. The root also has data-figure-position with the value start or end.

Partdata-partState / ARIAPurpose
Rootrootaria-labelledby, data-figure-positionA div, or an a when href, navigate or patch is set.
Figurefigure-A figure element, before or after the body per figure_position. Rendered only when the slot is given.
Bodybody-Wraps the title, content and actions.
Titletitleid (the target of aria-labelledby)A heading at title_level. Rendered only when the slot is given.
Contentcontent-The inner block. Rendered only when there is content.
Actionsactions-Buttons or links at the end of the body. Rendered only when the slot is given.

Accessibility

A card has no WAI-ARIA pattern of its own: the heading carries the meaning. With an id and a :title slot, the root gets aria-labelledby pointing at the heading, so a card read on its own says what it is. A card that is a link takes that title as its accessible name, is one tab stop, and Enter follows it. An anchor cannot hold buttons or other links, so leave the :actions slot out of a card that is a link.