nili/ui
All components

EmptyState

Overview
4 exports0 variant axes7 props2 files
import { EmptyState } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

Basic

Only title is required. The illustration slot sizes whatever SVG or image you hand it from the size axis, so pass the glyph itself rather than something that frames it — the artwork lives in Figma and is exported, not shipped by the component.

No invoices yet

When you send your first invoice, it will show up here.

import { EmptyState, Button, Icon } from "@nili/ui"
import { RiInboxLine, RiAddLine } from "@remixicon/react"

export function Example() {
  return (
    <EmptyState
      illustration={<Icon icon={RiInboxLine} />}
      title={t('copy.noInvoices')}
      description={t('copy.noInvoicesBody')}
      actions={<Button startIcon={<Icon icon={RiAddLine} />}>New invoice</Button>}
    />
  )
}

Sizes

Three densities. sm for an empty cell or a narrow panel, md for a card, lg for a whole page.

sm
No results

Try a different search term.

md
No results

Try a different search term.

lg
No results

Try a different search term.

import { EmptyState } from "@nili/ui"

export function Example() {
  return (
    <>
      <EmptyState size="sm" title={t('copy.noResults')} />
      <EmptyState size="md" title="No results" />
      <EmptyState size="lg" title="No results" />
    </>
  )
}

The three cases worth distinguishing

Nothing created yet, nothing matched, and something went wrong are different situations, and the action differs each time. A “no results” state that offers “Create your first item” is confusing — the items exist, the filter is wrong.

No projects yet

Create one to get started.

No matches for “roadmap”

Check the spelling, or clear the filters.

Could not load projects

Check your connection and try again.

import { EmptyState, Button, LinkButton, Icon } from "@nili/ui"
import { RiInboxLine, RiSearchLine, RiWifiOffLine } from "@remixicon/react"

export function Example() {
  return (
    <>
      {/* nothing created yet → offer to create */}
      <EmptyState
        illustration={<Icon icon={RiInboxLine} />}
        title={t('copy.noProjects')}
        description={t('copy.noProjectsBody')}
        actions={<Button>New project</Button>}
      />

      {/* nothing matched → offer to clear the filter */}
      <EmptyState
        illustration={<Icon icon={RiSearchLine} />}
        title="No projects match “roadmap”"
        description={t('copy.noMatchesBody')}
        actions={<Button appearance="stroke">Clear filters</Button>}
      />

      {/* something failed → offer to retry */}
      <EmptyState
        illustration={<Icon icon={RiWifiOffLine} />}
        title={t('copy.loadFailed')}
        description={t('copy.loadFailedBody')}
        actions={
          <>
            <Button appearance="stroke">Retry</Button>
            <LinkButton href="#">Contact support</LinkButton>
          </>
        }
      />
    </>
  )
}