Cairnloop's shared operator-UI component library.
Stateless Phoenix.Component function components that render the design
system's .cl-* classes. The styling itself ships in priv/static/cairnloop.css
(self-contained, token-driven, themeable) — these components only emit markup, so
the CSS file is the single source of visual truth.
Import into a LiveView with import Cairnloop.Web.Components and compose:
<.cl_button variant="primary" phx-click="save">Save policy</.cl_button>
<.cl_chip variant="warning" label="Needs review" />
<.cl_card>…</.cl_card>Design rules enforced here (so screens can't re-introduce drift):
- Never state-by-color-alone (brand §7.5) —
cl_chip/cl_banneralways pair a status color with a distinct-silhouette icon and a text label. - Self-contained icons —
cl_iconis an inline SVG set, so the library never requires the host to install heroicons or an icon font. - Tokens only — components carry semantic
.cl-*classes; spacing/color/motion come from--cl-*custom properties, never inline hex.
Summary
Functions
Persistent, region-level status banner (use for actionable status, not transient confirmations).
Breadcrumb trail (renders after the user goes a level deep).
Primary/secondary/danger/ghost button. Buttons and inputs share token heights.
Surface card. Optional :header slot renders a bordered title row; route_active adds the copper rail marker.
Status chip — color + icon + text together (never color alone). label or an
inner block supplies the text; the icon is chosen from the variant unless overridden.
Calm, reassuring empty state. :icon slot optional; title + inner block carry the copy.
Self-contained inline-SVG icon. Distinct silhouettes so status reads without color
(colorblind-safe, grayscale-safe). 16px default; size overrides.
Persistent navigation shell. Pass current (a destination key) so the active link
gets a 3-cue "you are here" state (weight + copper underline + fill, never color alone).
destinations is a list of %{key, label, href, icon, count} maps.
Cockpit Home job card — a verb-led job, ONE actionable "needs-you" count, and a CTA.
calm? renders the count in the success hue (used for the all-caught-up zero state).
Functions
Persistent, region-level status banner (use for actionable status, not transient confirmations).
Attributes
variant(:string) - Defaults to"neutral". Must be one of"success","info","warning","danger","ai", or"neutral".icon(:string) - Defaults tonil.class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Breadcrumb trail (renders after the user goes a level deep).
Attributes
items(:list) (required) - list of %{label, href} (last item is current, no href).
Primary/secondary/danger/ghost button. Buttons and inputs share token heights.
Attributes
variant(:string) - Defaults to"default". Must be one of"default","primary","danger", or"ghost".size(:string) - Defaults to"md". Must be one of"sm","md", or"lg".type(:string) - Defaults to"button".class(:string) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["disabled", "form", "name", "value", "phx-click", "phx-value-id", "phx-disable-with", "data-confirm"].
Slots
inner_block(required)
Surface card. Optional :header slot renders a bordered title row; route_active adds the copper rail marker.
Attributes
class(:string) - Defaults tonil.route_active(:boolean) - Defaults tofalse.- Global attributes are accepted.
Slots
headerinner_block(required)
Status chip — color + icon + text together (never color alone). label or an
inner block supplies the text; the icon is chosen from the variant unless overridden.
Attributes
variant(:string) - Defaults to"neutral". Must be one of"success","info","warning","danger","ai", or"neutral".label(:string) - Defaults tonil.icon(:string) - Defaults tonil.class(:string) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block
Calm, reassuring empty state. :icon slot optional; title + inner block carry the copy.
Attributes
title(:string) (required)icon(:string) - Defaults to"compass".class(:string) - Defaults tonil.
Slots
inner_block
Self-contained inline-SVG icon. Distinct silhouettes so status reads without color
(colorblind-safe, grayscale-safe). 16px default; size overrides.
Attributes
name(:string) (required)size(:string) - Defaults to"16".class(:string) - Defaults tonil.- Global attributes are accepted.
Persistent navigation shell. Pass current (a destination key) so the active link
gets a 3-cue "you are here" state (weight + copper underline + fill, never color alone).
destinations is a list of %{key, label, href, icon, count} maps.
Attributes
current(:atom) - Defaults tonil.destinations(:list) (required)brand(:string) - Defaults to"Cairnloop".
Slots
inner_block(required)
Cockpit Home job card — a verb-led job, ONE actionable "needs-you" count, and a CTA.
calm? renders the count in the success hue (used for the all-caught-up zero state).
Attributes
job(:string) (required)count(:any) (required)meta(:string) - Defaults tonil.href(:string) - Defaults tonil.cta(:string) - Defaults tonil.icon(:string) - Defaults tonil.calm?(:boolean) - Defaults tofalse.- Global attributes are accepted.
Slots
inner_block