<!-- Protocore Design System — TabbedShowcase -->
# TabbedShowcase

- **Category:** Navigation (`navigation`)
- **Slug:** `navigation/tabbed-showcase`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { TabbedShowcase } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/navigation/tabbed-showcase

> Tab-bar-over-panel showcase — mono [ 0N ] tabs that fill and merge into a bordered panel below. Split lays copy beside an illustration; single is one column.

## When to use it

**TabbedShowcase** is a marketing / landing-page primitive: a heavyweight, illustrated feature switcher for presenting a product's pillars or a protocol's building blocks.

- Switching peer views inside an app screen (config panels, entity tabs)? Use the lighter **Tabs** instead — TabbedShowcase is deliberately larger and more decorative.
- One idea explored across facets with a pinned rail? Use **StickyAccordion**.
- A single hero call-to-action pair? Use **DualCTA**.
- Feed the `art` slot a **LineArt** field to stay on-brand.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `defaultIndex` | `number` | no | `0` | Uncontrolled initial index. Default 0. |
| `index` | `number` | no | — | Controlled active index. Pair with `onIndexChange`. |
| `layout` | `enum` | no | `split` | `split` = 2-col panel (copy left, illustration right); `single` = one column of copy. |
| `onIndexChange` | `((index: number) => void)` | no | — | Fires with the next active index whenever a tab is selected. |
| `style` | `CSSProperties` | no | — | — |
| `tabs` | `ShowcaseTab[]` | yes | — | The tabs and their panels. |

## Examples

### Split layout

The `split` layout pairs copy (title, body, sub-tag chips, an action) with a right-hand illustration. Each tab is prefixed with its `[ 0N ]` index; the active tab fills the surface and merges into the panel.

```tsx
import { TabbedShowcase, LineArt, Button } from "@protocore/pds";

export default function TabbedShowcaseSplit() {
  return (
    <TabbedShowcase
      layout="split"
      tabs={[
        {
          label: "Interoperability",
          title: "Interoperability",
          body: "A neutral, immutable messaging layer every application can build on — no wrapped assets, no fragmented liquidity.",
          subTabs: ["Infrastructure", "Value Transfer", "Asset Issuance"],
          art: <LineArt variant="sweep" animate={false} />,
          action: <Button variant="secondary">Learn more</Button>,
        },
        {
          label: "Transport",
          title: "Transport",
          body: "Unified liquidity that moves native assets across every connected network in a single step.",
          subTabs: ["Bridge", "Pools", "Farms"],
          art: <LineArt variant="star4" animate={false} />,
          action: <Button variant="secondary">Learn more</Button>,
        },
        {
          label: "Compute",
          title: "Compute",
          body: "The decentralized multi-core world computer — throughput for infinite scale.",
          subTabs: ["Storage", "Networking", "ZK"],
          art: <LineArt variant="sphere" animate={false} />,
          action: <Button variant="secondary">Learn more</Button>,
        },
      ]}
    />
  );
}
```

### Single column (numbered breakdown)

The `single` layout is one column of copy — the numbered-breakdown pattern for walking through the parts of one system.

```tsx
import { TabbedShowcase } from "@protocore/pds";

// The numbered-breakdown pattern: single-column panels that walk through the
// parts of one system.
export default function TabbedShowcaseSingle() {
  return (
    <TabbedShowcase
      layout="single"
      tabs={[
        {
          label: "Endpoints",
          title: "Endpoints",
          body: "Immutable on-chain contracts that send and receive messages. They can never be paused or upgraded, so what you build on stays.",
        },
        {
          label: "Executor",
          title: "Executor",
          body: "An open role that delivers messages and prepays destination gas on the recipient network — anyone can run one.",
        },
        {
          label: "DVN",
          title: "DVN",
          body: "Decentralized Verifier Networks independently attest to message validity. Applications choose their own verifier set and thresholds.",
        },
      ]}
    />
  );
}
```

## Do & don't

**Do**

- Use it on marketing / landing surfaces to showcase a handful of pillars.
- Give each tab a one-word label; the [ 0N ] index carries the ordering.
- Put a LineArt illustration in the art slot for split layouts.
- Keep body copy to a sentence or two so panels stay a consistent height.

**Don't**

- Don't use TabbedShowcase for in-app view switching — that's Tabs.
- Don't exceed ~4 tabs; the bordered bar stops reading as a set.
- Don't mix split and single semantics in one instance.
- Don't stuff a form or interactive table inside a panel — it's a display surface.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Move focus to the tab bar and onto a tab button |
| `Enter / Space` | Select the focused tab and swap the panel |

**Notes**

- The tab bar is a `role="tablist"` of `role="tab"` buttons with `aria-selected`, over a `role="tabpanel"` panel.
- The `[ 0N ]` index prefix is `aria-hidden` decoration; the tab's text label is its accessible name.

## Related

`tabs`, `sticky-accordion`, `dual-cta`, `product-card`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
