Code Tabs
Renders :::code-group directives as tabbed code panels via a <CodeGroup> component.
The codeTabs feature groups related code blocks into an interactive tab strip. You wrap consecutive fenced blocks in a :::code-group directive, and zfb emits a <CodeGroup> element that the framework renders as tabs.
Opt-in feature
This feature is disabled by default. Enable it with the codeTabs key in zfb.config.ts. It accepts the true shorthand.
Configuration
export default defineConfig({
markdown: {
features: {
codeTabs: true,
},
},
});Authoring syntax
Wrap two or more fenced code blocks in a :::code-group directive. Each block's tab label is derived from its title="…" attribute:
:::code-group
```ts title="index.ts"
export const greeting: string = "hello";
```
```js title="index.js"
export const greeting = "hello";
```
:::Warning
Two adjacent fenced code blocks on their own do not become tabs; they render as two independent code blocks. The tab grouping is triggered only by the explicit :::code-group directive wrapping the fences.
Tab label resolution
Each tab's label follows this priority order:
The
title="…"attribute on the fenceThe language id (e.g.
ts,js)The fallback string
"tab"when neither is present
Live demo
The directive above renders as:
export const greeting: string = "hello";
export const greeting = "hello";
Emitted output
The :::code-group directive produces a <CodeGroup> JSX element with a tabs prop holding the resolved label array, and one <pre data-lang="…"> child per fence:
<CodeGroup tabs={["index.ts", "index.js"]}>
<pre data-lang="ts">export const greeting: string = "hello";</pre>
<pre data-lang="js">export const greeting = "hello";</pre>
</CodeGroup>The framework does not ship <CodeGroup> — zudo-doc registers its own implementation in pages/, mapping the tabs array and <pre data-lang> children onto the existing <Tabs> / <TabItem> UI. The code inside each <pre> is raw text (the Rust pipeline does not run syntax highlighting inside :::code-group fences).
Syncing tabs with name
The optional name attribute links all :::code-group blocks on the page that share the same name. When a user clicks a tab in one group, every other group with the same name switches to the matching tab automatically — if a tab with that label exists.
:::code-group{name="package-manager"}
```sh title="npm"
npm install my-lib
```
```sh title="pnpm"
pnpm add my-lib
```
:::
:::code-group{name="package-manager"}
```sh title="npm"
npm run dev
```
```sh title="pnpm"
pnpm dev
```
:::The chosen tab is also written to localStorage under the key tabs-group-{name}. On the next page load, every group with that name restores the stored tab (falling back to the default tab if the stored label is not present in the group).
Internally, name is forwarded by zfb as a prop to the <CodeGroup> component, which passes it as groupId to the underlying <Tabs> component. The TabsInit script reads data-group-id from the rendered DOM, syncs all same-groupId containers on click, and reads/writes localStorage for cross-visit persistence.
Notes
Empty
:::code-groupcontainers (no fences) are left unchanged as plain text.Nested
:::code-groupdirectives are not supported.