Lumen Docs

EmptyState

Placeholder for empty lists, coming-soon sections, or feature-flagged areas. Located at apps/web/components/ui/empty-state.tsx.

Usage

<EmptyState
  icon={<IconFolder />}
  message={<><strong>No files yet.</strong> Upload docs to give the AI context.</>}
  action={
    <Button variant="primary" size="sm" onClick={() => setShowUpload(true)}>
      <IconPlus /> Upload file
    </Button>
  }
/>

Props

interface EmptyStateProps {
  message: ReactNode;          // required, shown centered
  icon?: ReactNode;            // optional, above message
  action?: ReactNode;          // optional row below message (buttons)
  variant?: "dashed" | "solid";
  size?: "sm" | "md" | "lg";
  className?: string;
}

Variants

dashed (default)

Dashed border, softer background. For coming-soon, placeholder, intentionally-empty areas.

<EmptyState
  icon={<IconFolder />}
  message="No projects yet"
/>

solid

Solid background surface, stronger presence. For "load failed" or action-required empties.

<EmptyState
  variant="solid"
  icon={<IconAlert />}
  message={<><strong>Failed to load.</strong> Try refreshing.</>}
  action={<Button variant="primary" size="sm">Retry</Button>}
/>

Sizes

| size | Padding | |---|---| | sm | p-4 | | md (default) | p-6 | | lg | p-12 |

Use lg for full-page empties (no data at all). Use sm for inline empties inside a smaller panel.

Message shape

Message is ReactNode, not just string. Use inline formatting:

<EmptyState
  message={
    <>
      <strong>No threads yet.</strong> Start a conversation using the composer below.
    </>
  }
/>

Bold the headline sentence, normal weight for the explanation.

Action

Single button OR a row of 2 buttons max. Don't stuff a lot of actions in an empty state — the empty state is about helping the user decide what to do next, not enumerate every possibility.

Don't

  • Don't inline empty-state divs. Always use <EmptyState> — it centralizes spacing, border, icon padding.
  • Don't use for error states that need action. For full error pages, use a dedicated error component.
  • Don't pass a raw string with emoji. Use an icon prop with an SVG for consistent rendering.