registry:ui · General
empty — the no-data state, nothing more
The eight-state machine's no-data member (error/loading/404 are alert/result surfaces — ruled separate). Terminal illustration slot, title, description, actions. Zero JS.
$npx jixoai-ui add empty
https://ui.jixoai.com/r/empty.json
overview
Overview
A figure with three optional parts and one required line: the no-data state of the eight-state machine, deliberately nothing more.
Empty renders one composition: a dashed muted figure holding the terminal-box
illustration (the default is an empty directory listing — ls checks/, zero
items), and a figcaption carrying the title, an optional description, and an optional actions snippet. Zero JS, zero
state, zero transitions — the no-data state of the eight-state machine, and NOTHING
more: the antd ruling keeps error/loading/404 in the alert and result surfaces.
Composition is consumer-side by law: the illustration is a slot (bring any glyph — it
stays decorative, aria-hidden), and the actions snippet hosts the recovery
controls (usually a press-button). No component composes Empty today (grep receipt) —
pages own their no-data regions directly.
The eight axes resolve on the figure — density is the one axis that repaints (the named rung re-bases the rhythm channels), theme is the frozen pole (the paint reads no raw tokens, so an island changes nothing), and six stamp-and-supply. Per-axis below; the shared grammar lives on the universal props page.
usage
Usage
One required title; description and actions fill the caption; the illustration slot replaces the terminal default.
<Empty title="no checks yet" description="add the first check">
{#snippet actions()}<PressButton>add check</PressButton>{/snippet}
</Empty>empty
empty — the no-data state, nothing more
no checks yet
Add the first check to start the audit pipeline.
<Empty title="no checks yet" description="add the first check">
{#snippet actions()}<PressButton>add check</PressButton>{/snippet}
</Empty>examples
Composition
One required title and optional description, illustration and actions slots.
empty · composition
no artifacts
no checks
Add the first check.
<script lang="ts">
import Empty from '@ui/empty.svelte';
import PressButton from '@ui/press-button.svelte';
</script>
<div class="grid gap-4 md:grid-cols-2">
<Empty title="no artifacts" />
<Empty title="no checks" description="Add the first check.">
{#snippet actions()}<PressButton>add check</PressButton>{/snippet}
</Empty>
</div>api
Props
The table renders from the GENERATED meta + curation; the eight axis rows split into the shared section beneath.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| title * | string | — | The no-data heading — font-nav uppercase at the density channel's type voice. |
| description | string | — | Optional supporting copy, clamped to a 36ch measure under the title. |
| illustration | Snippet | — | Snippet replacing the default terminal listing (ls checks/ · 0 items) — bring any glyph; the art stays decorative (aria-hidden) either way. |
| actions | Snippet | — | Recovery actions under the caption — usually a press-button; the row wraps at the density gap. |
| class | string | '' | Forwarded to the root figure, after the family atoms. |
Universal props
| Property | Type | Default | Description |
|---|---|---|---|
| size | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | the base scale — root font-size; parts size in em |
| shape | 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto' | 'auto' · ambient scope | corner geometry (CSS corner-shape; §14 degrade table) |
| radius | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | corner size; auto = the concentric broadcast (§3) |
| density | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' · ambient scope | spacing/leading scale over the kernel channels (§4) |
| color | 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string | 'auto' · ambient scope | the hue axis of the fixed oklch primary system (§5) |
| theme | 'light' | 'dark' | 'system' | 'auto' | 'auto' · ambient scope | light/dark profile; system = the JS-mutable global (§6) |
| elevation | 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number | 'auto' · ambient scope | official M3 levels over the surface ladder (§7) |
| motion | 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number | 'auto' · ambient scope | intensity across the motion kernels (§8) |
axes
The eight axes on empty
empty is the frozen pole of the axis surface (census batch D): all eight lanes resolve no-own on the figure, density repaints the composition through its named rung, and the other seven stamp-and-supply without touching the paint. theme is the measured absence — the declaring-selector grep finds zero raw-token reads, so a resolved dark stamps .dark and nothing flips. The carriers stamp the figure (the promoted root is self-carried), greppable in the raw SSR.
Reading the table: Property is the axis, Type is the real carrier or consumption it drives on THIS family, Default is the lane default — the named steps, number unit, and consumption are in each description.
| Property | Type | Default | Description |
|---|---|---|---|
| size | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' | SUPPLY-ONLY — stamps --jx-size-effective; no family css reads it (grep receipt: zero readers in ui/empty/). The title and description read the fixed --jx-text/--jx-line channels and the art box is structural. Number unit: px. |
| shape | 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto' | 'auto' | SUPPLY-ONLY — stamps --jx-shape-effective and --jx-radius-factor-effective; no family css reads them (grep receipt: zero readers). The figure and art frames are 1px hairline boxes with no corner law. Number unit: none. |
| radius | 'small' | 'medium' | 'large' | 'auto' | number | 'auto' | SUPPLY-ONLY — stamps --jx-radius-effective; no family css reads it (grep receipt: zero readers) — the family composes no radius, concentric or otherwise. Number unit: px. |
| density | 'small' | 'medium' | 'large' | 'auto' | number (+ the five legacy spellings) | 'auto' | CONSUMED — the axis that repaints this state. The named rung stamps data-density on the figure and the scope block re-bases every channel the atoms read: --jx-stack (the figure/caption/art gaps), --jx-inset ×2 (the figure's air), --jx-text/--jx-line (title and description type), --jx-gap (the actions row) — the whole no-data composition breathes together. The NUMBER lane is inert: the coefficient stamps on the figure, but the channels compose at :root and the rung scopes — substitution runs at the declaring element (the declaring-element law). Number unit: coefficient. |
| color | 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string | 'auto' | SUPPLY-ONLY — stamps --jx-color-effective; no family css reads it (grep receipt: zero readers). The '0 items' ink rides --jx-primary — the theme's primary, never the hue carrier; hue that paints comes from the theme or the jx-hue-* injection. Number unit: hue degrees. |
| theme | 'light' | 'dark' | 'system' | 'auto' | 'auto' | THE FROZEN POLE, measured: a resolved dark stamps .dark on the figure and NOTHING flips — the declaring-selector grep finds zero raw-token reads in the family's paint (every voice is the stylex :root emission: --jx-border/--jx-muted/--jx-card/--jx-foreground/--jx-muted-foreground/--jx-primary/--jx-shadow-2xs, plus theme-free kernel channels). The no-data state keeps the page profile inside any island; consumers who want a dark empty state compose it inside their own dark scope. light and system stamp nothing — tree inheritance. |
| elevation | 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number | 'auto' | SUPPLY-ONLY — stamps --jx-elevation-effective; no family css reads it. The art box's one shadow is --jx-shadow-2xs — a fixed recipe token, not the §7 consumption pair. Number unit: dp. |
| motion | 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number | 'auto' | SUPPLY-ONLY — stamps --jx-motion-effective; no family css reads it. The component is zero-JS with zero transitions — nothing animates, so the axis has nothing to step. Number unit: coefficient. |
Deviations, cited: the adoption is the census batch D row (the long tail —
openspec/changes/explicit-props/research/migration-census.md); empty is a leaf (grep
receipt: no component mounts it), so the supply feeds only consumer compositions. The §1
collision rule: the figure is a <figure> with no native attribute
names at stake — every axis name is the family's own destructured lane.
<!-- density: the named rung re-bases the figure's rhythm —
the --jx-stack/--jx-inset/--jx-text/--jx-line channels the
figure, art and caption read -->
<Empty title="compact (sm rung)" density="small" />
<Empty title="touch (lg rung)" density="lg" />
<!-- theme: the FROZEN pole — no raw-token voice exists in the
family's paint, so a resolved dark stamps .dark and nothing
flips; the state keeps the page profile -->
<Empty title="dark island — byte-identical" theme="dark" />empty · the consumed lane and the frozen pole
compact (sm rung)
touch (lg rung)
light figure
dark island — byte-identical
The two bottom figures render byte-identical paint in either profile — the theme row's documented absence, not a bug: every painted voice is the stylex :root emission, and a scoped .dark never re-substitutes it.
<!-- density: the named rung re-bases the figure's rhythm —
the --jx-stack/--jx-inset/--jx-text/--jx-line channels the
figure, art and caption read -->
<Empty title="compact (sm rung)" density="small" />
<Empty title="touch (lg rung)" density="lg" />
<!-- theme: the FROZEN pole — no raw-token voice exists in the
family's paint, so a resolved dark stamps .dark and nothing
flips; the state keeps the page profile -->
<Empty title="dark island — byte-identical" theme="dark" /><script lang="ts">
import Empty from '@ui/empty.svelte';
import { query } from '@lib/universal-props-query.svelte';
import type { DensityLane } from '@lib/defaults.svelte';
</script>
<Empty
title="responsive figure"
density={query<{ sm: DensityLane }, DensityLane>({ sm: 'small' }, 'large')}
/>empty · query()
responsive figure
Media keys are min-width: below 40rem the base applies — the large rung, the roomy figure; at 40rem and wider the sm case wins and the composition compacts. Resize across 40rem.
<script lang="ts">
import Empty from '@ui/empty.svelte';
import { query } from '@lib/universal-props-query.svelte';
import type { DensityLane } from '@lib/defaults.svelte';
</script>
<Empty
title="responsive figure"
density={query<{ sm: DensityLane }, DensityLane>({ sm: 'small' }, 'large')}
/>| Token | Default | Source |
|---|---|---|
| --jx-stack | rung scale × coefficient | density |
| --jx-inset | rung scale × coefficient | density |
| --jx-text / --jx-line | 10 / 11 / 12 / 13 / 15px · 14 / 16 / 18 / 20 / 24px (2xs → lg) | density |
| --jx-gap | rung scale × coefficient | density |
| --jx-shadow-2xs | fixed recipe | structural |
a11y
Accessibility
ARIA
| Attribute | Value | Description |
|---|---|---|
| figure | empty root | Groups the no-data message. |
| figcaption | title + description | Keeps the message discoverable. |
| aria-hidden | illustration | Prevents decorative art from interrupting the message. |