Sigra.Admin.Components (Sigra v1.1.0)

Copy Markdown View Source

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

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

applied_chip(assigns)

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 &times; 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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

audit_row(assigns)

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:

  • AuditIndexLive mobile card list (show_detail: true, show_codes: true)
  • AuditUserLive mobile 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 to false.
  • show_codes (:boolean) - renders the event id and action code lines (on in explorers, off in compact block). Defaults to false.
  • class (:any) - additional CSS classes merged onto the root element. Defaults to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

empty_state(assigns)

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 to nil.
  • 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).

field_help(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

Slots

  • inner_block (required) - plain explanatory tooltip copy.

notice(assigns)

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 to nil. Must be one of :ok, :warn, :risk, :info, or nil.
  • class (:any) - additional CSS classes merged onto the root element. Defaults to nil.
  • 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.

notice_link(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root link.

Slots

  • inner_block (required) - the notice action label.

page_back(assigns)

Renders a single-step back-to-list ghost button with a fixed &larr; 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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

scope_ribbon(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

skeleton(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

stat(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

stat_link(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

summary_chip(assigns)

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 to nil.
  • label (:string) (required) - the term / KPI label.
  • value (:integer) (required) - the numeric KPI value.
  • icon (:string) - optional built-in metric icon name. Defaults to nil.
  • value_unit (:string) - optional unit rendered tight against the number. Defaults to nil.
  • value_suffix (:string) - optional second-line label for the number. Defaults to nil.
  • subvalue (:string) - optional secondary metric context. Defaults to nil.
  • help (:string) - optional short explanatory help copy. Defaults to nil.
  • tone (:string) - optional metric tone (risk, warn, ok, info). Defaults to nil.
  • class (:any) - additional CSS classes merged onto the root element. Defaults to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.

task_card(assigns)

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 to nil.
  • Global attributes are accepted. arbitrary HTML attributes added to the root element.