Lib-owned canonical admin component set for Sigra's admin LiveViews.
Provides 13 flat, stateless Phoenix.Component function components that consolidate
the duplicated admin chrome across LiveViews. Security-critical design and a11y fixes
propagate to host apps via mix deps.update (D-05).
Each component emits only sg-* CSS classes defined by the design contract.
See the Admin Design Contract for the authoritative per-component markup, class, and ARIA specification.
Components
stat_link/1— Numeric KPI with a nav destination (always<a>)stat/1— Read-only numeric KPI, no navtask_card/1— Verb-first action prompt with CTAsummary_chip/1— Non-interactive aggregate posture badgeapplied_chip/1— Active filter indicator with remove affordanceempty_state/1— Dashed centred zero-rows placeholderpage_back/1— Single-step back to listscope_ribbon/1— Persistent in-body scope indicatornotice/1— Block-level toned contextual alertnotice_link/1— Inline notice action linkfield_help/1— Label-adjacent explanatory tooltip triggerskeleton/1— Loading-shape placeholderaudit_row/1— Audit event card (sg-list-row) with unified tone and date formatting
Summary
Functions
Renders an active-filter indicator with a remove affordance.
Renders an audit event card (sg-list-row) with a pill cluster, actor summary,
optional detail lines, and a formatted timestamp.
Renders a centred zero-rows placeholder with a variable body block.
Renders a compact label-adjacent help trigger with a non-interactive tooltip.
Renders a block-level toned contextual alert.
Renders an inline navigation action for use inside notice/1 copy.
Renders a single-step back-to-list ghost button with a fixed ← glyph prefix.
Renders a persistent in-body scope indicator as a decorative inline span.
Renders a loading-shape placeholder.
Renders a read-only numeric KPI with no navigation affordance.
Renders a numeric KPI stat with a navigation destination (always an <a> element).
Renders a non-interactive aggregate posture badge using definition-list semantics.
Renders a verb-first action prompt card with a call-to-action link.
Functions
Renders an active-filter indicator with a remove affordance.
The chip label is displayed inline; the remove link carries an aria-label for
screen readers and a visually hidden fallback. The × glyph is aria-hidden.
Examples
<.applied_chip label="Active" remove_href="/admin/users?status=" />Attributes
label(:string) (required) - the filter label shown inside the chip.remove_href(:string) (required) - the URL to navigate to in order to remove this filter.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders an audit event card (sg-list-row) with a pill cluster, actor summary,
optional detail lines, and a formatted timestamp.
This is the single shared component for all three audit surfaces:
AuditIndexLivemobile card list (show_detail: true,show_codes: true)AuditUserLivemobile card list (show_detail: true,show_codes: true)UserShowLive"Recent Audit" compact block (defaults:show_detail: false,show_codes: false)
Tone is derived from row.outcome and row.action_badge via the single internal
audit_tone/1 helper, which is the authoritative source replacing the divergent
row_tone/1 helpers previously present in AuditIndexLive and AuditUserLive.
The format_date/1 helper handles %DateTime{} and %NaiveDateTime{} values,
renders nil as "—", and raises ArgumentError on any other type (D-09 fix).
Examples
<.audit_row row={row} />
<.audit_row row={row} show_detail show_codes />Attributes
row(:map) (required) - the presenter row map for the audit event.show_detail(:boolean) - renders the Actor and Effective user detail lines (on in explorers, off in compact block). Defaults tofalse.show_codes(:boolean) - renders the event id and action code lines (on in explorers, off in compact block). Defaults tofalse.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a centred zero-rows placeholder with a variable body block.
The title attr provides the primary heading. The inner_block slot accepts the
variable body (e.g., filter-specific messaging or a CTA).
Examples
<.empty_state title="No users match this view">
<p class="sg-muted sg-text-sm">Try adjusting your filters.</p>
</.empty_state>Attributes
title(:string) (required) - the primary heading shown in the empty state.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Slots
inner_block- the variable body rendered below the title (e.g., CTA or filter copy).
Renders a compact label-adjacent help trigger with a non-interactive tooltip.
Use this for admin form fields whose effect is not obvious from the label alone. Keep the tooltip copy brief and plain-language; the panel should not contain links or other interactive content.
Examples
<span class="sg-field-label-row">
<label class="sg-field-label" for="branding-logo-url">Logo URL</label>
<.field_help id="branding-logo-url-help" label="Logo URL">
Shown on generated auth screens and email headers when set.
</.field_help>
</span>Attributes
id(:string) (required) - stable id for the tooltip panel.label(:string) (required) - field label used in the trigger's accessible name.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Slots
inner_block(required) - plain explanatory tooltip copy.
Renders a block-level toned contextual alert.
Ships the final sg-notice form per the design contract (D-07). The data-tone attribute
drives visual treatment via CSS. No live-region role is applied by default (D-08):
Load-present content makes any live-region role inert (WAI-ARIA APG), and adding one
risks duplicate announcements on LiveView re-render. A live-region role is opt-in
per call site via :rest for genuinely post-load dynamic notices.
See the Admin Design Contract for the full rationale (D-07/D-08/D-09).
Examples
<.notice tone={:warn}>
Password reset email could not be delivered.
</.notice>
<.notice tone={:ok}>
Email address verified successfully.
</.notice>Attributes
tone(:atom) - the visual tone applied via data-tone; renders as a string in the HTML attribute. Defaults tonil. Must be one of:ok,:warn,:risk,:info, ornil.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes (e.g., a live-region role for opt-in post-load notices).
Slots
inner_block(required) - the notice message content.
Renders an inline navigation action for use inside notice/1 copy.
This remains a native link and keeps notice content sentence-shaped. Use it
when the notice names a concrete next step; use task_card/1 or sg-btn
variants for standalone primary actions.
Examples
<.notice tone={:risk}>
3 accounts need review —
<.notice_link href="/admin/users?needs_review=true">Review accounts</.notice_link>
</.notice>Attributes
href(:string) (required) - the URL the notice action navigates to.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root link.
Slots
inner_block(required) - the notice action label.
Renders a single-step back-to-list ghost button with a fixed ← glyph prefix.
The label (e.g., "Back to users") is supplied by the caller. The arrow glyph is
always rendered aria-hidden so screen readers read only the label text.
Examples
<.page_back return_to={~p"/admin/users"} label="Back to users" />Attributes
return_to(:string) (required) - the URL the button navigates back to.label(:string) (required) - the visible button label (e.g., "Back to users").class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a persistent in-body scope indicator as a decorative inline span.
The copy is caller-supplied (e.g., the result of scope_copy/1). The component
emits the stable hook class sg-scope-ribbon (consumed by Playwright, per D-07)
alongside the visual utility classes sg-muted sg-text-sm.
Examples
<.scope_ribbon copy={scope_copy(@admin_scope)} />Attributes
copy(:string) (required) - the scope indicator copy (e.g., "Platform admin").class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a loading-shape placeholder.
Shimmer motion is owned entirely by the CSS layer (app.css) and is stripped by
the universal prefers-reduced-motion rule. No inline motion or transition style
is added by this component.
Examples
<.skeleton class="h-8 w-32" />Attributes
class(:any) - additional CSS classes merged onto the root element (e.g., height/width). Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a read-only numeric KPI with no navigation affordance.
Unlike stat_link/1, this component renders no <a> element and introduces no
dedicated component class. It reuses the existing sg-metric* utility classes.
Examples
<.stat label="Active sessions" value={42} />Attributes
label(:string) (required) - the human-readable KPI label.value(:integer) (required) - the numeric KPI value.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a numeric KPI stat with a navigation destination (always an <a> element).
Examples
<.stat_link label="Total users" value={1_234} href="/admin/users" />Attributes
href(:string) (required) - the URL the stat link navigates to.label(:string) (required) - the human-readable KPI label.value(:integer) (required) - the numeric KPI value.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a non-interactive aggregate posture badge using definition-list semantics.
The basic form preserves the original compact <dt>/<dd> output. Optional
icon, value_suffix, subvalue, tone, and help assigns opt into the richer
posture-summary treatment used by list page headers.
Examples
<.summary_chip label="MFA enabled" value={7} />
<.summary_chip
id="users-metric-mfa"
icon="mfa"
label="MFA enrolled"
value={42}
value_unit="%"
value_suffix="MFA coverage"
subvalue="7 users with MFA"
help="These users have multifactor authentication enabled. Higher coverage lowers account takeover risk."
/>Attributes
id(:string) - optional root id; also seeds the help id. Defaults tonil.label(:string) (required) - the term / KPI label.value(:integer) (required) - the numeric KPI value.icon(:string) - optional built-in metric icon name. Defaults tonil.value_unit(:string) - optional unit rendered tight against the number. Defaults tonil.value_suffix(:string) - optional second-line label for the number. Defaults tonil.subvalue(:string) - optional secondary metric context. Defaults tonil.help(:string) - optional short explanatory help copy. Defaults tonil.tone(:string) - optional metric tone (risk, warn, ok, info). Defaults tonil.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.
Renders a verb-first action prompt card with a call-to-action link.
Examples
<.task_card
title="Invite your team"
body="Add teammates so they can access the admin panel."
href="/admin/users/invite"
action="Send invitations"
/>Attributes
title(:string) (required) - the card heading.body(:string) (required) - the card description copy.href(:string) (required) - the URL the CTA button navigates to.action(:string) (required) - the CTA button label.class(:any) - additional CSS classes merged onto the root element. Defaults tonil.- Global attributes are accepted. arbitrary HTML attributes added to the root element.