ArenaEmptyState.prompt.md
August 16, 2026 ยท View on GitHub
Arena empty state, a section or screen with nothing in it yet, and one clear way
forward. The action is projected, so the empty state places a control the consumer wrote
rather than carrying a second button implementation. The dashed border is what distinguishes it from
arena-error-state: nothing is wrong here, there is simply nothing yet. The action
wrapper only renders when an action is actually projected, an empty state with no
action ships no dead space for one.
title is required (input.required<string>(), per contracts/api/components/ArenaEmptyState.json),
say what is empty. icon is optional and, like arena-stat-card's, a Phosphor class name
Arena draws itself, not projected content.
<arena-empty-state icon="ph-bold ph-folder-open"
title="No projects yet"
message="A project groups deployments, logs and artifacts for one client.">
<arena-button action (click)="create()">Create a project</arena-button>
</arena-empty-state>
Members, in contract order and under this layer's own names. * marks a required one.
| Member | Form | Type | Default | What it is |
|---|---|---|---|---|
icon | primitive | string | A Phosphor class name for the glyph Arena draws, muted. | |
title* | primitive | string | The headline: what is empty. | |
headingLevel | enum | ArenaHeadingLevel | "h3" | Which rung of the document outline the title takes. Only the element changes: the title's class is the same at every value, so the render is identical and no appearance follows from it. It defaults to h3, the card rung of the title ladder, because an empty state fills the body of a region something above it already names, so its headline sits under that name rather than beside it. none is refused at runtime, the rule every component whose title is required follows: a title required because it names the thing it draws cannot also be told that the name is not one. |
message | primitive | string | A sentence of guidance under the title. | |
action | slot | A single call-to-action control, centred under the message. |
Import ArenaAction from @dravensoft/arena-angular alongside ArenaEmptyState in the
host component's imports,
action is a directive, not a plain attribute, because it is how the empty
state detects that an action was projected at all. ArenaAction is shared: every
primitive that projects a single action through [action] (ArenaEmptyState,
ArenaErrorState) imports the same directive rather than declaring its own.
Do / Don't
- Say what the thing is in the message, not just that there are none of it. An empty state is often the first time someone reads a definition.
- Give exactly one action. Two competing actions in an empty state is a decision the user has no information to make.
- Don't use an empty state for a failed load: that is
arena-error-state, and the difference matters: one invites, the other apologises and offers a retry. - Don't forget to import
ArenaActionwhen projecting an action. Without it, theactionattribute is inert and the action silently fails to render.
The rules of the language hold in the code you write from this page, and no gate reads your application to enforce them. An Arena component is not a styling surface: put no class of your own on it, read every value through its token rather than a raw colour or a bare 16px, and never wrap it in your router's own link. The rest of the rules are in ../../../../../skills/design/SKILL.md.