For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. The dithercn agent skill, for building any dither on the engine, is at /.well-known/agent-skills/dithercn/SKILL.md.
dithercn

Empty state

A lit, dithered illustration with a title, a description and an action, for views with nothing in them yet.

Controls
Illustration
Matrix
Colour
Animate

Installation

pnpm dlx shadcn@latest add https://dithercn.dev/r/empty-state.json

Usage

import { EmptyState } from "@/components/dithercn/empty-state";
import { Button } from "@/components/ui/button";
 
export function NoProjects() {
  return (
    <EmptyState
      illustration="folder"
      title="No projects yet"
      description="Create a project to start building."
      action={<Button>New project</Button>}
    />
  );
}

Above the text sits a small lit object drawn in dither cells. Each surface takes a tone from a light up and to the left, so faces turned to the light are dense, faces turned away are sparse, and curved surfaces step through every Bayer level. A one-cell seam splits the object's parts, a clear margin outlines it, and a faint halo and floor shadow sit behind it.

  • box: an open box with its flaps folded back. The default, for lists and orders.
  • search: a magnifying glass with a glint on the glass. For search and filters with no results.
  • folder: a folder with a sheet peeking out. For files, projects and documents.
  • planet: a lit sphere with a tilted ring. For feeds, events and anything still to arrive.

matrix changes the pattern: bayer4 for crisp steps, bayer8 for finer ones, blue-noise for an even grain.

Examples

Illustrations

The four objects in four colours.

Inside a settings panel

A first-run state for API keys, with the green folder and a dither button for the action.

No search results

The magnifier in grey, for a state the user will see often. Keep these quiet and give a way out.

Props

PropTypeDefault
title*

The heading. Say what is empty, plainly.

Type: ReactNodeDefault –
description

One or two sentences: why it is empty and what to do next.

Type: ReactNodeDefault –
action

Buttons or links, under the text.

Type: ReactNodeDefault –
illustration

The dithered object above the text.

Type: "box" | "search" | "folder" | "planet"Default "box"
color

Colour of the illustration: a palette name, a CSS variable name or any CSS colour.

Type: DitherColorDefault "ink"
matrix

The threshold pattern.

Type: "bayer2" | "bayer4" | "bayer8" | "blue-noise"Default "bayer4"
animate

Bob the object up and down by one cell.

Type: booleanDefault true
titleAs

Heading level of the title.

Type: "h2" | "h3" | "h4"Default "h3"

Notes

  • The illustration is decorative and hidden from assistive technology. The title is a real heading; set titleAs to fit the page outline.
  • The bob moves the object one whole cell in steps, so the dither never smears, and it stops under reduced motion. Each illustration is two SVG paths, computed once per illustration and matrix and cached, so it costs no JavaScript at runtime and renders on the server.
  • The illustration keeps a 112 by 72 cell aspect ratio up to 336 pixels wide, so cells are 3 pixels at full size, and it shrinks on narrow screens.