GUILD OF GLEKS UIv21.19.0

gog-empty-state

Empty State 21.18.0

What a region says when it has nothing to show. The empty states that matter are answers — a search that matched nothing, a filter that excluded everything, the last item removed — and on screen they are obvious while a screen reader hears nothing at all. This one announces itself when it appears, and again whenever its message changes while it stays on screen.

Overview

typescript
import {
  EmptyStateComponent,
  GogEmptyStateActionsDirective,
  GogEmptyStateMediaDirective,
} from '@guildofgleks/ui';

@Component({
  // ...
  imports: [EmptyStateComponent, GogEmptyStateActionsDirective, GogEmptyStateMediaDirective],
})

A title, a description, and what the reader can do about it:

No messages

Messages your team sends you land here.
<gog-empty-state iconName="mail" heading="No messages" live="off">
  Messages your team sends you land here.
  <div gogEmptyStateActions>
    <gog-button variant="secondary">Write one</gog-button>
  </div>
</gog-empty-state>

Examples

Sizes

Five steps of icon, title, description and padding. It draws no border or fill — put it in a card, a panel, or in place of a table.

No results

xsm

No results

sm

No results

md

No results

lg

No results

slg
@for (size of sizes; track size) {
  <gog-empty-state iconName="search" heading="No results" live="off" [size]="size">
    {{ size }}
  </gog-empty-state>
}

An illustration

gogEmptyStateMedia replaces the icon with your own <svg> or <img>, hidden from assistive tech. An illustration drawn in currentColor takes the icon's muted colour.

Your board is empty

Add a column to start planning.
<gog-card>
  <gog-empty-state heading="Your board is empty" live="off">
    <svg gogEmptyStateMedia width="96" height="64" viewBox="0 0 96 64" fill="none">
      <rect x="4" y="8" width="24" height="48" rx="4" stroke="currentColor" stroke-width="2" />
      <rect x="36" y="8" width="24" height="32" rx="4" stroke="currentColor" stroke-width="2" />
      <rect x="68" y="8" width="24" height="40" rx="4" stroke="currentColor" stroke-width="2" />
    </svg>
    Add a column to start planning.
  </gog-empty-state>
</gog-card>

An empty state as an answer

The element and its text arrive in one insertion, and a live region created together with its own text is routinely skipped. The component mounts its region empty and fills it one render later — the mechanism gog-alert uses — and keeps it in step with the message.

A search that matches nothing

Type "zz", then "zzz". With a screen reader on, the first says "No invoices found, Nothing matches zz", and the second says the new query — the empty state never left the page, so only a region that watches its own message could say it. "Clear search" is not read out: actions are found, not heard.

INV-1041 Acme

INV-1042 Globex

INV-1043 Initech

<gog-inputfield label="Search invoices" [(value)]="query" />
<gog-card>
  @if (matches().length) {
    @for (invoice of matches(); track invoice) {
      <p>{{ invoice }}</p>
    }
  } @else {
    <gog-empty-state iconName="search" heading="No invoices found" size="sm">
      Nothing matches "{{ query() }}".
      <div gogEmptyStateActions>
        <gog-button variant="secondary" size="sm" (gogClick)="query.set('')"
          >Clear search</gog-button
        >
      </div>
    </gog-empty-state>
  }
</gog-card>

The last item removed

Remove the project. The title here is a real <h4>, because the card's own heading is an <h3>: headingLevel places it in the outline, and unset the title is styled text. Where focus goes after the last item vanishes by its own button is your app's call — usually the empty state's action.

Projects

Website refresh

<gog-card>
  <h3 gogCardHeader>Projects</h3>
  @for (project of projects(); track project; let i = $index) {
    <p>
      {{ project }}
      <gog-button variant="ghost" size="sm" (gogClick)="remove(i)">Remove</gog-button>
    </p>
  } @empty {
    <gog-empty-state iconName="plus" heading="No projects" [headingLevel]="4" size="sm">
      Projects group the work your team tracks.
      <div gogEmptyStateActions>
        <gog-button size="sm" (gogClick)="add()">New project</gog-button>
      </div>
    </gog-empty-state>
  }
</gog-card>

In a table, an empty state goes in gog-table's gogTableEmpty template 21.19.0, where it replaces the table's own "No data" row — which is text in a cell and is never announced. See Table, An empty state of your own.

Accessibility

Announced when it answers something; quiet when it was always there.

  • A polite region — role="status", mounted empty, filled with the title and description after the first render and again on every change to them. Never assertive: nothing being empty justifies an interruption.
  • live="off" — for an empty state the page loads with ("You have no projects yet"), where the reader is reading the page anyway.
  • Heading level — headingLevel 2 to 6 makes the title a real heading at the level the surrounding headings set; unset, it is not in the outline, which is safer than a guessed level.
  • Not a loading state — render it once the answer is known to be nothing; before that, a skeleton. A failed request is an alert, not an empty state.

API Reference

gog-empty-state inputs

NameTypeDefaultDescription
headingstring''The title.
headingLevelGogEmptyStateHeadingLevel | nullnull2 to 6 makes the title a real heading at that level; unset, it is styled text.
iconNameGogIconName | nullnullDrawn above the title, decorative. A projected gogEmptyStateMedia replaces it.
live'polite' | 'off''polite''off' for an empty state the page loads with.
sizeGogSize'md''xsm' | 'sm' | 'md' | 'lg' | 'slg'.

Slots

DirectiveContextDescription
(default)contentThe description, under the title. Announced with it.
[gogEmptyStateMedia]an <svg> or <img>An illustration in place of the icon; aria-hidden.
[gogEmptyStateActions]a <div> of buttonsThe actions row under the description. Never announced.

Global Configuration

This component has no GOG_CONFIG entries of its own — every default is set per instance. See Global Configuration for what does apply app-wide.

Styling Tokens

Every CSS custom property the empty state paints with. Override any of them — on a single instance, a subtree, or a theme — to restyle it. See the Theming guide for the full token-layering model, or the Theme Generator to tweak these live.

TokenDescription
--gog-empty-state-font-family / -gap / -message-gapThe typeface; the space between media, message and actions; and between title and description.
--gog-empty-state-xsm-padding / -sm-padding / -md-padding / -lg-padding / -slg-paddingThe padding at each size. A surface, so one value on every side; it draws no border or fill.
--gog-empty-state-xsm-icon-size / -sm-icon-size / -md-icon-size / -lg-icon-size / -slg-icon-sizeThe icon at each size, 24 to 64px.
--gog-empty-state-icon-color / -icon-line-heightThe icon’s muted colour, which an illustration drawn in currentColor takes too.
--gog-empty-state-xsm-heading-font-size / -sm-heading-font-size / -md-heading-font-size / -lg-heading-font-size / -slg-heading-font-sizeThe title at each size.
--gog-empty-state-heading-color / -heading-font-weight / -heading-line-heightThe title.
--gog-empty-state-xsm-description-font-size / -sm-description-font-size / -md-description-font-size / -lg-description-font-size / -slg-description-font-sizeThe description at each size.
--gog-empty-state-description-color / -description-line-height / -measureThe description, and the widest it sets before wrapping (48ch).
--gog-empty-state-actions-gap / -actions-offsetBetween the buttons, and the extra step above the row.