# Components

The blocks you can use in any page, with an example of each. They work in MDX without an import.

Pages live in `src/content/docs/` as MDX files. Write Markdown as usual and drop in any of the components below where you need more than text.

## Callout

Use a callout for something the reader should not miss. There are four types: `note`, `tip`, `warning` and `danger`.

<Callout type="note">Search keys are read only.</Callout>
<Callout type="tip" title="Faster imports">Send documents in batches of up to 1,000 per request.</Callout>
<Callout type="warning">Changing ranking rules rebuilds the index, which can take a few minutes.</Callout>
<Callout type="danger" title="This cannot be undone">Deleting an index removes every document in it.</Callout>

```mdx
<Callout type="tip" title="Faster imports">
  Send documents in batches of up to 1,000 per request.
</Callout>
```

## Cards

Cards point to other pages. Group them with `CardGroup` and choose two or three columns.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/docs/getting-started/quickstart">
    Your first search in five minutes.
  </Card>
  <Card title="Authentication" icon="key" href="/docs/getting-started/authentication">
    Admin keys, search keys and scoped keys.
  </Card>
</CardGroup>

```mdx
<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/docs/getting-started/quickstart">
    Your first search in five minutes.
  </Card>
</CardGroup>
```

The icons are `rocket`, `key`, `database`, `code`, `book`, `flash`, `search`, `filter` and `layers`.

## Code groups

Show the same example in several languages. Readers switch with the tabs, and every block has a copy button.

<CodeGroup labels={["cURL", "JavaScript"]}>

```bash
curl https://api.zeroindex.test/v1/indexes/products \
  -H "Authorization: Bearer $ZEROINDEX_KEY"
```

```js
const index = await client.index("products").get();
```

</CodeGroup>

````mdx
<CodeGroup labels={["cURL", "JavaScript"]}>

```bash
curl https://api.zeroindex.test/v1/indexes/products
```

```js
const index = await client.index("products").get();
```

</CodeGroup>
````

## Tabs

Tabs hold any content, not only code.

<Tabs labels={["Server", "Browser"]}>
  <Tab>Use an admin key and the full client. It can add and delete documents.</Tab>
  <Tab>Use a search key and the search only client. It is under 4 kB.</Tab>
</Tabs>

```mdx
<Tabs labels={["Server", "Browser"]}>
  <Tab>Use an admin key and the full client.</Tab>
  <Tab>Use a search key and the search only client.</Tab>
</Tabs>
```

## Steps

Steps number a sequence for you.

<Steps>
  <Step title="Create an index">Name it after what it holds, like `products`.</Step>
  <Step title="Add documents">Send them as a JSON array.</Step>
  <Step title="Search">Query the index from your app.</Step>
</Steps>

```mdx
<Steps>
  <Step title="Create an index">Name it after what it holds.</Step>
  <Step title="Add documents">Send them as a JSON array.</Step>
</Steps>
```

## Accordion

Accordions hide detail until the reader asks for it. They suit questions and edge cases.

<Accordion title="What counts as a document?">
  Any JSON object with an `id`. Nested objects and arrays are fine.
</Accordion>
<Accordion title="Is there a size limit?">
  Each document can be up to 100 kB.
</Accordion>

```mdx
<Accordion title="What counts as a document?">
  Any JSON object with an `id`.
</Accordion>
```

## Fields

Document the parameters a request takes with `ParamField`, and what comes back with `ResponseField`.

<ParamField name="q" type="string" required>
  The text to search for.
</ParamField>
<ParamField name="limit" type="number" default="20">
  How many hits to return, up to 100.
</ParamField>
<ResponseField name="hits" type="array">
  The matching documents, best first.
</ResponseField>

```mdx
<ParamField name="limit" type="number" default="20">
  How many hits to return, up to 100.
</ParamField>
<ResponseField name="hits" type="array">
  The matching documents, best first.
</ResponseField>
```

## Badges

Badges label versions and states: <Badge>Beta</Badge> <Badge variant="accent">New</Badge> <Badge variant="warning">Preview</Badge> <Badge variant="success">Stable</Badge> <Badge variant="danger">Deprecated</Badge> <Badge variant="outline">v2.4</Badge>

```mdx
<Badge variant="success">Stable</Badge>
```

The variants are `muted`, `accent`, `warning`, `success`, `danger` and `outline`.

## Images

Wrap screenshots in a `Frame` to give them a border and an optional caption. Pass `darkSrc` and readers in dark mode see the dark version. Put image files in `public/images/`.

<Frame
  src="/images/docs/dashboard-light.webp"
  darkSrc="/images/docs/dashboard-dark.webp"
  alt="The Indexes page of the ZeroIndex dashboard, listing five indexes with their document counts"
  caption="The Indexes page in the dashboard."
/>

```mdx
<Frame
  src="/images/docs/dashboard-light.webp"
  darkSrc="/images/docs/dashboard-dark.webp"
  alt="The Indexes page of the ZeroIndex dashboard"
  caption="The Indexes page in the dashboard."
/>
```

Plain Markdown images get the same border, without a frame or caption.

## Video

`Video` plays a file you host. Add `autoplay` for short clips that loop silently, like a terminal recording. Without it, the video waits behind a poster with controls.

<Video
  src="/images/docs/terminal-build.mp4"
  poster="/images/docs/terminal-build.webp"
  title="Running a production build"
  autoplay
/>

```mdx
<Video
  src="/images/docs/terminal-build.mp4"
  poster="/images/docs/terminal-build.webp"
  title="Running a production build"
  autoplay
/>
```

For YouTube or Vimeo, pass the video id instead of `src`. The player only loads when someone presses play, so the page stays fast.

```mdx
<Video youtube="VIDEO_ID" poster="/images/docs/talk.webp" title="Search relevance in ten minutes" />
<Video vimeo="VIDEO_ID" title="Setting up faceted search" />
```