---
title: Code components - Workbench component mocks
description: Add named component mock specs for tabbed Workbench previews.
---

import { Aside } from '@astrojs/starlight/components';

Workbench component mocks let you preview the same component with multiple named prop and slot configurations.

You can author component mocks in a JSON file. Each mock entry becomes a tab in
the Workbench preview panel.

Workbench also includes a built-in _Default_ preview for every component. It
shows the component as Canvas renders it initially, before a content editor
populates props or slots. Canvas and Workbench generate this preview from the
first example value of each prop in `component.yml` and leave slots empty.

## File naming and placement

Author the mock file in the same directory as the component metadata and source
file. Name it either `mocks.json` or `[component-name].mocks.json`, depending
on how the component metadata is named.

**Example: index-style component**

```text
src/components/hero/
  index.tsx
  component.yml
  mocks.json
```

**Example: named component**

```text
src/components/
  card.tsx
  card.component.yml
  card.mocks.json
```

## Mock entries

Each mock file contains a JSON array of entries. Every entry includes `name`,
which Workbench uses as the preview tab label.

Each entry becomes its own preview tab in Workbench.

### Props format

Use the props format when the preview only changes the component props.

| Key | Description |
| --- | --- |
| `name` | Labels the preview tab in Workbench. |
| `props` | Provides prop values for the component. |

**Example:** `heading.mocks.json`

```json
[
  {
    "name": "Centered",
    "props": {
      "text": "Publish AI-assisted content with editorial control",
      "eyebrow": "Build faster",
      "textAlign": "center"
    }
  }
]
```

### Props and slots format

Use the props and slots format when the preview needs component props and
slots.

| Key | Description |
| --- | --- |
| `name` | Labels the preview tab in Workbench. |
| `props` | Provides prop values for the inferred root component. |
| `slots` | Maps root component slots to element IDs from `elements`. Those IDs are arbitrary. |
| `elements` | Defines authored child elements, keyed by arbitrary element IDs referenced from `slots`. |

Each entry in `elements` must include a `type`. It can also include `props`
and `slots`, which reference other element IDs from the same `elements`
object.

Each element `type` must match a discovered component name, such as `card` or
`js.card`. Workbench discovers these component types from the code components
available in your project.

**Example:** `card.mocks.json`

```json
[
  {
    "name": "Featured",
    "props": {
      "featured": true
    },
    "slots": {
      "header": ["card-featured-header"],
      "content": ["card-featured-content"],
      "footer": ["card-featured-actions"]
    },
    "elements": {
      "card-featured-header": {
        "type": "heading",
        "props": {
          "text": "Featured article"
        }
      },
      "card-featured-content": {
        "type": "text",
        "props": {
          "content": "Learn how editorial teams use Canvas to review, refine, and publish AI-assisted content."
        }
      },
      "card-featured-actions": {
        "type": "button-group",
        "props": {
          "stacked": false
        },
        "slots": {
          "items": ["card-featured-primary-action", "card-featured-secondary-action"]
        }
      },
      "card-featured-primary-action": {
        "type": "button",
        "props": {
          "label": "Get started",
          "href": "/sign-up",
          "variant": "primary"
        }
      },
      "card-featured-secondary-action": {
        "type": "button",
        "props": {
          "label": "Read more",
          "href": "/articles/canvas-workflows"
        }
      }
    }
  },
]
```

<Aside>Before rendering, Workbench normalizes the props format and the props and slots format into a [`@json-render/react`](https://json-render.dev)-compatible spec shape (with our [hopefully temporary patch](https://github.com/vercel-labs/json-render/pull/105) by automatically creating the root element from the component that owns the mock file.</Aside>

### Advanced format

Use the advanced format when the preview needs full control over the rendered
root element.

This format is useful when you need to render a component inside other
components to verify how it behaves in context.

| Key | Description |
| --- | --- |
| `name` | Labels the preview tab in Workbench. |
| `root` | Identifies the root element to render. |
| `elements` | Defines the full element tree, including the root element and any elements referenced by slots. |

Unlike the props and slots format, this version lets you control the rendered
root directly. Define that root element inside `elements`, along with its
props, slots, and any nested elements it references.

Each element `type` must match a discovered component name, such as `card` or
`js.card`. Workbench discovers these component types from the code components
available in your project.

**Example:** `card.mocks.json`

```json
[
  {
    "name": "In grid",
    "root": "card-grid",
    "elements": {
      "card-grid": {
        "type": "grid",
        "props": {
          "columns": 3,
          "gap": "md"
        },
        "slots": {
          "items": ["card-1", "card-2", "card-3"]
        }
      },
      "card-1": {
        "type": "card",
        "props": {
          "featured": true
        },
        "slots": {
          "header": ["card-1-header"],
          "content": ["card-1-content"],
          "footer": ["card-1-footer"]
        }
      },
      "card-1-header": {
        "type": "heading",
        "props": {
          "text": "Featured article"
        }
      },
      "card-1-content": {
        "type": "text",
        "props": {
          "content": "Learn how editorial teams use Canvas to review, refine, and publish AI-assisted content."
        }
      },
      "card-1-footer": {
        "type": "button-group",
        "slots": {
          "items": ["card-1-primary-action", "card-1-secondary-action"]
        }
      },
      "card-1-primary-action": {
        "type": "button",
        "props": {
          "label": "Read more",
          "href": "/articles/canvas-workflows"
        }
      },
      "card-1-secondary-action": {
        "type": "button",
        "props": {
          "label": "Save for later",
          "href": "/saved"
        }
      },
      "card-2": {
        "type": "card",
        "props": {
          "featured": false
        },
        "slots": {
          "header": ["card-2-header"],
          "content": ["card-2-content"],
          "footer": ["card-2-footer"]
        }
      },
      "card-2-header": {
        "type": "heading",
        "props": {
          "text": "Documentation update"
        }
      },
      "card-2-content": {
        "type": "text",
        "props": {
          "content": "Review the latest guidance for authoring Workbench component mocks."
        }
      },
      "card-2-footer": {
        "type": "button",
        "props": {
          "label": "Open docs",
          "href": "/docs/workbench-mocks"
        }
      },
      "card-3": {
        "type": "card",
        "props": {
          "featured": false
        },
        "slots": {
          "header": ["card-3-header"],
          "content": ["card-3-content"],
          "footer": ["card-3-footer"]
        }
      },
      "card-3-header": {
        "type": "heading",
        "props": {
          "text": "Team workflow"
        }
      },
      "card-3-content": {
        "type": "text",
        "props": {
          "content": "Coordinate AI drafting, editorial review, and publishing approvals in one place."
        }
      },
      "card-3-footer": {
        "type": "button",
        "props": {
          "label": "See workflow",
          "href": "/workflow"
        }
      }
    }
  }
]
```

<Aside>The advanced format matches the [`@json-render/react`](https://json-render.dev) spec shape (with our [hopefully temporary patch](https://github.com/vercel-labs/json-render/pull/105)).</Aside>

### Choosing a format

- Use the props format for quick component variations driven only by props.
- Use the props and slots format when you need slots, too.
- Use the advanced format when you need to render the component inside a different root.
