Fluxon.Components.Badge (Fluxon v3.1.1)

A compact inline marker for status labels, category tags, and notification counts.

Badges render as <span> elements that combine a semantic color, a visual variant, and a size to call out a small piece of metadata next to other content. They are pure markup with no client-side behavior, so they can sit inside table cells, navigation rows, card headers, or button labels without any setup. All styles adapt to light and dark modes through the design system's color tokens.

Choosing between badge, alert, and tooltip

Pick the component that matches the visual weight and lifetime of the message:

ComponentPlacementUse Case
<.badge>Inline next to contentShort status labels, counts, tags ("Active", "12", "Beta")
<.alert>Block in document flowPersistent feedback that needs the full row ("Saved", "Error")
<.tooltip>Floating on hover/focusSecondary detail revealed only on demand

Badges are not interactive by default. They become clickable when you pass phx-click or wrap them in a link, but they do not ship with focus styles or keyboard activation on their own; for primary actions reach for Fluxon.Components.Button instead.

Usage

The simplest badge is a single piece of text:

<.badge>Default</.badge>

The default variant is surface and the default color is primary. Pair color with the meaning of the label:

<.badge color="success">Active</.badge>
<.badge color="warning">Pending</.badge>
<.badge color="danger">Failed</.badge>

Override variant and size to scale visual weight up or down:

<.badge variant="solid" color="primary">Featured</.badge>
<.badge variant="ghost" color="info" size="sm">Beta</.badge>
<.badge variant="dashed" color="warning" size="lg">Draft</.badge>

Visual Variants

The variant attribute selects how the badge renders its background and border. Each variant produces a distinct emphasis level so a row of badges can mix high-priority and background labels without visual noise.

<.badge variant="solid" color="success">Solid</.badge>
<.badge variant="soft" color="info">Soft</.badge>
<.badge variant="surface" color="warning">Surface</.badge>
<.badge variant="outline" color="primary">Outline</.badge>
<.badge variant="dashed" color="warning">Dashed</.badge>
<.badge variant="ghost" color="primary">Ghost</.badge>
VariantTreatmentUse Case
solidFilled background, strongest visual weightHigh-priority status that must read at a glance ("Live", "New")
softTinted background without borderInformational labels that should sit calmly inline
surfaceTinted background with a matching borderDefault. Contained status indicators in dense layouts
outlineBordered with no fillGeneral-purpose tags where the label color does the work
dashedDashed border with no fillDraft, placeholder, or "add" states
ghostNo background or borderSubtle inline indicators inside busy rows or button labels

Semantic Colors

The color attribute sets a coordinated foreground, background, and border palette for each variant. Pick the color that matches the meaning of the label, not just the visual preference; this keeps badges consistent across the app and reusable across themes.

<.badge color="primary">Featured</.badge>
<.badge color="info">Information</.badge>
<.badge color="success">Completed</.badge>
<.badge color="warning">Pending</.badge>
<.badge color="danger">Failed</.badge>
ColorUse Case
primaryBranded or featured content (featured, new, promoted)
infoInformational labels (beta, note, version tag)
successPositive status (active, completed, verified, paid)
warningAttention-needed status (pending, expiring, review)
dangerCritical or negative status (failed, error, overdue, blocked)

Each color combines with each variant to produce a tuned background and text token, so the same label color reads correctly whether it is filled (solid), tinted (soft, surface), or transparent (outline, dashed, ghost).

Sizes

The size attribute scales the badge height, padding, font size, border radius, and inline icon size together. Choose a size that matches the surrounding text scale:

<.badge size="xs">XS</.badge>
<.badge size="sm">SM</.badge>
<.badge size="md">MD</.badge>
<.badge size="lg">LG</.badge>
<.badge size="xl">XL</.badge>
SizeHeightText sizeIcon sizeUse Case
xs16px10px10pxCounters and dot-style markers next to icons
sm20pxxs12pxInline labels in table cells and navigation rows
md22pxsm on mobile, xs on desktop14pxDefault. Comfortable in most contexts
lg24pxsm16pxEmphasized labels in card headers
xl28pxbase18pxProminent status indicators in heroes or empty states

Icons

The badge slot accepts arbitrary inline content, so you can place a Fluxon icon next to the label. Add the icon class to <.icon> so the badge can size and align it from the outside; the size token then follows the badge's size attribute automatically.

<.badge color="success">
  <.icon name="hero-check-circle" class="icon" /> Verified
</.badge>

<.badge color="warning" size="sm">
  <.icon name="hero-clock" class="icon" /> Pending
</.badge>

<.badge color="danger" variant="ghost">
  <.icon name="hero-x-circle" class="icon" /> Failed
</.badge>

The icon class is required

Icons inside a badge must carry the icon class for the badge's size and alignment rules to apply. Without it the icon keeps its native dimensions and breaks the row, particularly at xs and sm. Always add the class:

<!-- Correct: the badge sizes and aligns the icon -->
<.badge color="success">
  <.icon name="hero-check" class="icon" /> Done
</.badge>

<!-- Wrong: missing "icon" class, the glyph renders at its native size -->
<.badge color="success">
  <.icon name="hero-check" /> Done
</.badge>

Custom Classes and Attributes

The class attribute is merged with the variant, color, and size styles, so utilities you pass through override defaults where they conflict. Any other HTML attribute is forwarded to the underlying <span> through the :rest global, which makes badges easy to wire up to LiveView events:

<.badge color="primary" class="cursor-pointer" phx-click="open_filter">
  Filter
</.badge>

<.badge color="info" data-testid="status-badge" aria-label="Build status: passing">
  Passing
</.badge>

Examples

Status indicator next to a label

<div class="flex items-center gap-2">
  <span class="text-sm font-medium">Database</span>
  <.badge variant="solid" color="success">
    <.icon name="hero-check-circle" class="icon" /> Online
  </.badge>
</div>

Notification count in a navigation row

<.link navigate={~p"/inbox"} class="flex items-center justify-between">
  <span>Messages</span>
  <.badge color="info">{@unread_count}</.badge>
</.link>

Removable filter chips driven by LiveView

<div class="flex flex-wrap gap-2">
  <.badge
    :for={tag <- @active_filters}
    variant="dashed"
    color="primary"
    phx-click="remove_filter"
    phx-value-tag={tag}
    class="cursor-pointer"
    aria-label={"Remove filter #{tag}"}
  >
    <.icon name="hero-x-mark" class="icon" /> {tag}
  </.badge>
</div>
def handle_event("remove_filter", %{"tag" => tag}, socket) do
  {:noreply, update(socket, :active_filters, &List.delete(&1, tag))}
end

Toggleable category in a tag picker

Switch the variant and the icon based on selection state. Toggle styling through data- attributes rather than computing classes when possible; in this example the attribute-based approach lives at the call site since the badge has no built-in selection state:

<.badge
  color={if @selected, do: "primary", else: "info"}
  variant={if @selected, do: "solid", else: "dashed"}
  phx-click="toggle_category"
  phx-value-id={@category.id}
  class="cursor-pointer"
>
  <.icon :if={@selected} name="hero-check" class="icon" />
  {@category.name}
</.badge>

Inline label inside a button

Badges compose cleanly inside other components. Use ghost or soft to stay subtle next to the button label:

<.button variant="outline" navigate={~p"/changelog"}>
  Changelog
  <.badge variant="soft" color="info" size="xs">3 new</.badge>
</.button>

Table cell status

<.table rows={@invoices}>
  <:col :let={invoice} label="Number">{invoice.number}</:col>
  <:col :let={invoice} label="Status">
    <.badge color={invoice_color(invoice.status)} size="sm">
      {String.capitalize(invoice.status)}
    </.badge>
  </:col>
</.table>
defp invoice_color("paid"), do: "success"
defp invoice_color("pending"), do: "warning"
defp invoice_color("overdue"), do: "danger"
defp invoice_color(_), do: "info"

Summary

Components

Renders a compact inline badge as a <span> element.

Components

badge(assigns)

Renders a compact inline badge as a <span> element.

Use this component to attach a short status label, count, or tag to surrounding content. The visual weight is controlled by variant, the meaning by color, and the scale by size. The slot accepts arbitrary inline content, including text and Fluxon icons; icons marked with the icon class are sized automatically to match the badge.

Custom classes passed through class are merged with the variant, color, and size styles, and any other HTML attribute is forwarded to the underlying span.

Attributes

  • class (:any) - Additional CSS classes merged with the badge's base, variant, color, and size styles. Use this to add cursor styles when the badge is clickable, to widen the badge, or to override a specific token while keeping the rest of the theme intact.

    Defaults to nil.

  • color (:string) - The semantic color of the badge. Sets the foreground, background, and border tokens together as a coordinated palette for the chosen variant.

    • primary: branded or featured content (featured, new, promoted).
    • info: informational labels (beta, note, version tag).
    • success: positive status (active, completed, verified, paid).
    • warning: attention-needed status (pending, expiring, review).
    • danger: critical or negative status (failed, error, overdue).

    Defaults to "primary". Must be one of "primary", "info", "success", "warning", or "danger".

  • size (:string) - Controls the badge height, horizontal padding, font size, border radius, and the size of any nested icon carrying the icon class. Defaults to md. Use smaller sizes inside dense layouts (table cells, inline counters) and larger sizes for prominent status indicators.

    Defaults to "md". Must be one of "xs", "sm", "md", "lg", or "xl".

  • variant (:string) - The visual style of the badge. Determines emphasis level and how the background and border are rendered.

    • solid: filled background, strongest visual weight. Use for high-priority status.
    • soft: tinted background without border. Use for calm informational labels.
    • surface: tinted background with matching border. Default; works in most contexts.
    • outline: bordered with no fill. Use for general-purpose tags.
    • dashed: dashed border with no fill. Use for draft or placeholder states.
    • ghost: no background or border. Use for subtle inline indicators.

    Defaults to "surface". Must be one of "solid", "soft", "surface", "outline", "dashed", or "ghost".

  • Global attributes are accepted. Any additional HTML attribute (for example phx-click, data-*, aria-label, title) forwarded to the underlying <span> element. Useful for wiring badges to LiveView events or attaching test hooks.

Slots

  • inner_block (required) - The badge content. Accepts plain text, numbers, or rich inline content such as Fluxon icons. Icons rendered with the icon class are sized and spaced automatically to match the badge's size attribute; without it the icon falls back to its native dimensions.