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:
| Component | Placement | Use Case |
|---|---|---|
<.badge> | Inline next to content | Short status labels, counts, tags ("Active", "12", "Beta") |
<.alert> | Block in document flow | Persistent feedback that needs the full row ("Saved", "Error") |
<.tooltip> | Floating on hover/focus | Secondary 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>| Variant | Treatment | Use Case |
|---|---|---|
solid | Filled background, strongest visual weight | High-priority status that must read at a glance ("Live", "New") |
soft | Tinted background without border | Informational labels that should sit calmly inline |
surface | Tinted background with a matching border | Default. Contained status indicators in dense layouts |
outline | Bordered with no fill | General-purpose tags where the label color does the work |
dashed | Dashed border with no fill | Draft, placeholder, or "add" states |
ghost | No background or border | Subtle 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>| Color | Use Case |
|---|---|
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, 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>| Size | Height | Text size | Icon size | Use Case |
|---|---|---|---|---|
xs | 16px | 10px | 10px | Counters and dot-style markers next to icons |
sm | 20px | xs | 12px | Inline labels in table cells and navigation rows |
md | 22px | sm on mobile, xs on desktop | 14px | Default. Comfortable in most contexts |
lg | 24px | sm | 16px | Emphasized labels in card headers |
xl | 28px | base | 18px | Prominent 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))}
endToggleable 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
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 chosenvariant.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 theiconclass. Defaults tomd. 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 theiconclass are sized and spaced automatically to match the badge'ssizeattribute; without it the icon falls back to its native dimensions.