Skip to content

Steps, tabs and code

Sequences, alternatives, and code presentation.

Six components for procedures and code.

titleSize"p" | "h2" | "h3" | "h4"default: p

Heading level for each step’s title. On Steps.

Steps children: Step only, at least two. A one-step sequence is not a sequence, and the check enforces it.

On Step:

titlestringrequired

The step’s heading.

idstring

Stable anchor for deep links.

iconicon

Icon beside the title.

stepNumbernumber

Overrides the automatically assigned number.

mdx
<Steps>
<Step title="Install">Add the dependency.</Step>
<Step title="Authenticate">Set your API key in the environment.</Step>
</Steps>

Keep fenced code blocks at the top level of the page rather than inside a <Step> — MDX parses fences differently inside JSX, which is a common source of confusing build failures. Use title plus prose in the step, and put the command below the list.

syncbooleandefault: true

Selecting a tab selects the same-titled tab in every other group on the page. On Tabs.

defaultTabIndexnumberdefault: 0

Which tab starts selected. On Tabs.

Tabs children: Tab only, at least two.

On Tab:

titlestringrequired

The tab label.

idstring

Stable identifier.

iconicon

Icon in the label.

languagestring

Marks the tab as carrying code in this language.

sync defaults to on: a reader who picks Python once sees Python in every group further down the page. That is usually what you want — turn it off when tabs on the same page mean unrelated things.

codestring

The code to show, as a string or a template literal. When set, it wins over any children.

titlestring

Filename or label shown in the block’s header.

languagestring

Syntax highlighting language. Wins over a wrapped fence’s own language tag.

showLineNumbersbooleandefault: false

Renders line numbers.

startLinenumberdefault: 1

First line number when numbering is on.

maxLinesnumber

Scrolls beyond this height instead of growing.

wordWrapbooleandefault: false

Wraps long lines instead of scrolling horizontally.

highlightstring

Line range to emphasize, e.g. "3-5".

focusstring

Line range to focus, dimming the rest.

CodeBlock renders through Expressive Code, like a fence: the same syntax highlighting, the same header with the title, and the same copy button. The code is shown exactly as you wrote it, with straight quotes and braces intact.

Children: the code, in one of three forms. Reed takes the first one present, in this order:

  • The code prop. Use a template literal for code with quotes or braces. It is the only form that needs no children, and any children are ignored when it is set:

    mdx
    <CodeBlock title="config.ts" language="ts" code={`const x = { mode: "strict" };`} />
  • A single fenced child. Put the tags and the fence on their own lines:

    mdx
    <CodeBlock title="config.ts" focus="2">
    ```ts
    const x = { mode: "strict" };
    export default x;
    ```
    </CodeBlock>
  • Loose text. Plain text between the tags, for short code with no braces:

    mdx
    <CodeBlock language="sh">echo "hi"</CodeBlock>

    Straight quotes stay straight, and an entity such as &amp; becomes the character it stands for, &, exactly as in the copied code. A bare { in loose text still opens a JavaScript expression, so the page fails with unparseable-mdx. Use the code prop or a fence for code with braces.

The language comes from the language prop, then the wrapped fence’s language tag. With neither, the block renders as plain text with no highlighting.

A plain fenced code block is still the simplest default, and fences already cover a title, line numbers, line highlighting and wrapping. Reach for CodeBlock for focus or maxLines, or as a tab inside a CodeGroup.

If a page imports its own component named CodeBlock, that page’s <CodeBlock> elements use it. The tabs Reed generates for a CodeGroup on that page still use the catalog component.

dropdownbooleandefault: false

Adds a dropdown above the tab strip for choosing a tab.

Children: fenced code blocks or CodeBlock elements, at least one. Use CodeGroup for one operation shown in several languages. Each child becomes one tab.

mdx
<CodeGroup>
```js title="JavaScript"
await client.projects.list();
```
```python title="Python"
client.projects.list()
```
</CodeGroup>

Each tab’s label comes from that child alone:

  1. its title — a fence’s title="..." option, or a CodeBlock’s title prop;
  2. otherwise its language, exactly as written: a fence tagged TS gives a tab named TS, not ts;
  3. otherwise Tab 1, Tab 2 and so on, counting only the children that reach this step.

The language used for a label is the same one used for highlighting, so a <CodeBlock language="ts"> wrapping a python fence is labelled and highlighted as ts. Fences and CodeBlock elements can be mixed in one group.