---
language: "en"
title: "Authoring components"
canonical: "https://cookbook.tenphi.me/authoring/"
source: "docs/authoring.mdx"
version: "0.23.0"
index: true
---

# Authoring components

Write ordinary Markdown for most pages. Use MDX when a page needs components,
and import them from `@tenphi/cookbook/components`. Local MDX is supported by
default; npm MDX requires an explicit `trust: "mdx"` source declaration.

## Tabs

Every panel requires a `label`. Arrow keys, Home, and End move between tabs;
right-to-left layouts reverse the horizontal arrow direction. Without
JavaScript, all panels remain readable under their headings.

```mdx
import { Tab, Tabs } from "@tenphi/cookbook/components";

<Tabs label="Installation">
  <Tab label="npm">Run `npm install your-package`.</Tab>
  <Tab label="pnpm">Run `pnpm add your-package`.</Tab>
</Tabs>
```

Run `npm install your-package`.
Run `pnpm add your-package`.

## Callouts

Use `kind="note"`, `"tip"`, `"caution"`, or `"danger"`; `title` overrides the
visible label. The default kind is `note`. Status colors come from
`theme.palette.info`, `success`, `warning`, and `danger` and adapt to all schemes
and contrast modes.

```mdx
<Callout kind="tip" title="Keep content close to code">
  Relative Markdown links continue to work after Cookbook assigns public routes.
</Callout>
```

Relative Markdown links continue to work after Cookbook assigns public routes.

## Code groups

Pass labeled source strings to create an accessible tabbed code group. `language`
selects the Shiki grammar (defaults to plain text). Groups share semantic syntax
colors, configured grammars/transformers, and copy controls with Markdown fences.
Each panel retains keyboard-accessible tabs and readable fallback content.

```mdx
<CodeGroup
  label="Install Cookbook"
  items={[
    { label: "npm", language: "shell", code: "npm install @tenphi/cookbook" },
    { label: "pnpm", language: "shell", code: "pnpm add @tenphi/cookbook" },
  ]}
/>
```

## Cards, steps, and previews

Use a card to link to another page, or omit `href` to present a standalone
summary. `Steps` renders an ordered list; put ordinary `li` elements inside it.

```mdx
import { Card, Steps } from "@tenphi/cookbook/components";

<Card title="On-page navigation" href="#on-page-navigation">
  Offer a compact contents list on smaller screens.
</Card>

<Steps>
  <li>Choose a content source.</li>
  <li>Configure the navigation.</li>
  <li>Build and check the output.</li>
</Steps>
```

Offer a compact contents list on smaller screens.

Choose a content source.
Configure the navigation.
Build and check the output.

`Preview` runs HTML and optional JavaScript in a sandboxed iframe with a source
disclosure. It cannot access the documentation page's origin. Its `css` prop is
for the isolated preview document; style the documentation shell with Tasty.

```mdx
import { Preview } from "@tenphi/cookbook/components";

<Preview
  title="A simple button"
  html={'<button type="button">Try it</button>'}
  css={"button { padding: 0.75rem; }"}
/>
```

## Cookbook logo

`Logo` renders the Cookbook mark. Use `label` when it carries meaning or
`decorative` beside nearby text that already names the site. To display your
own artwork in the header and drawer, configure
[`site.logo`](/configuration#site-logo).

## Diff snippets

Use a `diff` code fence to highlight additions and deletions. The `+` and `-`
markers remain visible independently of their theme-aware backgrounds:

```diff
-formatOkhsl(v.h, v.s * 100, l * 100);
+formatOkhsl(v.h, v.s, l);
```

## Component props

| Component | Props and behavior                                                                                  |
| --------- | --------------------------------------------------------------------------------------------------- |
| `Card`    | Optional `title` and `href`; renders an article or link with slot content                           |
| `Steps`   | Ordered list container; supply `li` elements                                                        |
| `Logo`    | Optional `label`, `decorative`, and root `class`; renders the Cookbook mark                         |
| `Preview` | Required `title`; optional `html`, `css`, and `javascript`; isolates examples in a sandboxed iframe |

The public package exports each component's props type, such as `TabProps`,
`CalloutProps`, and `CodeGroupProps`. Styles and all named sub-elements are
listed in [Component styles](/component-styles#style-customization).

## On-page navigation

Desktop pages show a table of contents. Opt into a compact disclosure below the
header on smaller screens, globally in `docs.config.ts`:

```ts
tableOfContents: { mobile: true, minHeadingLevel: 2, maxHeadingLevel: 3 }
```

The same frontmatter field can change heading levels or set `mobile: false` on
one page. `tableOfContents: false` disables both versions. Selecting a mobile
contents link closes the disclosure and moves keyboard focus to the heading.
The desktop contents list highlights the current section and scrolls its own
list when the active link moves out of view.
Customize `theme.styles.MobileTableOfContents` and `TableOfContentsLayout`.

## Hero images

Use a relative local image in frontmatter. Cookbook reads its intrinsic dimensions
and reserves the correct aspect ratio as the layout responds to screen width:

```yaml
hero:
  tagline: Build something useful.
  image:
    file: ./assets/hero.png
    alt: A preview of the documentation
```

Use `light` and `dark` instead of `file` for appearance variants; both must have
the same aspect ratio. Remote or public-path images require explicit `width` and
`height`. Hero images load eagerly with high fetch priority; use ordinary Markdown
images for content farther down the page. `theme.styles.Hero.Visual` controls
responsive sizing without changing the intrinsic dimensions.
