Pipeline A does not support tabs. There's no view{mode="tabs"} directive
concept in the marked-based pipeline. This container is pipeline-B only.
Tabs are authored as a generic view directive with mode="tabs", wrapping one
view{label="..."} per panel — there is no dedicated tabs/tab directive name,
unlike steps/step or the card family. The same colon-nesting rule applies: the
outer view{mode="tabs"} needs more colons than the panels nested inside it.
Before this page, tabs had zero real usage in this repository (per #2453) — the
CSS (.aup-tab-input/.aup-tab/.aup-tab-panel in
packages/aup/src/primitives-css.ts) and the ARIA wiring
(role="tablist"/aria-controls/aria-labelledby/aria-selected in
renderer/primitives/view.ts's renderTabs()) existed but had never been rendered
from real content. The examples below intentionally cover #2453's stated acceptance
matrix: 2 tabs, 8+ tabs, long CJK labels, and a nested code block in a panel.
Two tabs
Source:
::::view{mode="tabs"}
:::view{label="pnpm"}
```bash
pnpm install
```
:::
:::view{label="npm"}
```bash
npm install
```
:::
::::Rendered:
pnpm installnpm installUnder the hood, each panel is a CSS-only radio input + label pair (no JavaScript
required to switch tabs); tabs-enhance.ts keeps aria-selected in sync as the
user clicks, on top of an already fully keyboard-usable native radiogroup.
Eight-plus tabs
Source:
::::view{mode="tabs"}
:::view{label="Node.js"}
Runtime: Node.js 20+
:::
:::view{label="Bun"}
Runtime: Bun 1.x
:::
:::view{label="Deno"}
Runtime: Deno 2.x
:::
:::view{label="Python"}
Runtime: Python 3.12+
:::
:::view{label="Go"}
Runtime: Go 1.22+
:::
:::view{label="Rust"}
Runtime: Rust 1.75+
:::
:::view{label="Java"}
Runtime: Java 21+
:::
:::view{label="Ruby"}
Runtime: Ruby 3.3+
:::
::::Rendered:
Runtime: Node.js 20+
Runtime: Bun 1.x
Runtime: Deno 2.x
Runtime: Python 3.12+
Runtime: Go 1.22+
Runtime: Rust 1.75+
Runtime: Java 21+
Runtime: Ruby 3.3+
The tab bar wraps rather than forcing the page into horizontal scroll at 8+ tabs, including at the 390px mobile breakpoint.
Long CJK labels
Source:
::::view{mode="tabs"}
:::view{label="安装与配置指南"}
第一步:安装依赖。
:::
:::view{label="部署到生产环境的完整流程"}
第二步:部署。
:::
::::Rendered:
第一步:安装依赖。
第二步:部署。
CJK text has no natural word-break points the way space-separated Latin text does — a long CJK label must still fit the tab bar without pushing the page into horizontal scroll at 390px.
Nested code block in a panel
Source:
::::view{mode="tabs"}
:::view{label="Example"}
Full working example:
```typescript
export async function main() {
const afs = await mountAfs();
const items = await afs.list("/packages/content/docs/markdown");
return items;
}
```
:::
:::view{label="Output"}
```json
{ "count": 7, "type": "docs" }
```
:::
::::Rendered:
Full working example:
export async function main() {
const afs = await mountAfs();
const items = await afs.list("/packages/content/docs/markdown");
return items;
}{ "count": 7, "type": "docs" }A fenced code block inside a tab panel renders exactly the same as anywhere else in this pipeline (language label, copy button) — the panel is just another block container.