# Content tabs

Organize alternatives into tabs: framework-specific examples, two ways to do the same thing, or any content that reads better one option at a time.

The container is framed by the 1.5px rule with 6px corners. Its header strip sits on the `surface-muted` tint above the rule, and the tabs are the same pills as in [code groups](/design-system/code-blocks): a hairline outline, ink fill for the selected tab, in the sans face rather than mono.

## Basic example

### First Tab

This is the content for the **first tab**. It supports full markdown, including:

- Lists
- **Bold** and _italic_ text
- Links and more

### Second Tab

Content for the second tab. You can include any markdown here.

> Even blockquotes work inside tabs.

## Framework documentation

A common use case is showing framework-specific implementations:

### Angular

```typescript filename="app.component.ts"
import { Component, inject } from '@angular/core';
import { DcuplService } from './dcupl.service';

@Component({
  selector: 'app-root',
  template: `<div>{{ data() }}</div>`,
})
export class AppComponent {
  private dcupl = inject(DcuplService);
  data = this.dcupl.query('Product');
}
```

Angular uses signals and dependency injection for reactive data access.

### React

```typescript filename="App.tsx"
import { useDcupl } from '@dcupl/react';

export function App() {
  const { items } = useDcupl('Product');

  return <div>{items.map(i => i.name)}</div>;
}
```

React uses hooks for data fetching and state management.

### Vue

```vue filename="App.vue"
<script setup>
import { useDcupl } from '@dcupl/vue';

const { items } = useDcupl('Product');
</script>

<template>
  <div v-for="item in items">{{ item.name }}</div>
</template>
```

Vue uses the Composition API with reactive refs.

## Comparison tables

### Free

| Feature | Included |
|---------|----------|
| Basic queries | Yes |
| Up to 1,000 items | Yes |
| Community support | Yes |
| API access | No |

### Pro

| Feature | Included |
|---------|----------|
| Advanced queries | Yes |
| Unlimited items | Yes |
| Priority support | Yes |
| API access | Yes |

## Syntax reference

The tab syntax uses a container directive pattern:

```markdown
:::tabs{key="unique-identifier"}
::tab[Tab Label]{key="tab-key"}
Tab content goes here with **markdown** support.
::
::tab[Another Tab]{key="another-key"}
More content here.
::
:::
```

### Attributes

| Attribute | Location    | Required | Description                                                     |
| --------- | ----------- | -------- | --------------------------------------------------------------- |
| `key`     | `:::tabs{}` | Optional | Unique identifier for the tab group. Auto-generated if omitted. |
| `key`     | `::tab[]{}` | Optional | Unique key for each tab. Defaults to `tab-0`, `tab-1`, etc.     |
| Label     | `::tab[]`   | Required | Display text for the tab button (inside brackets).              |

### Notes

- Content inside tabs supports full markdown including code blocks, lists, tables, and more
- Each tab must end with `::` on its own line; leave a blank line before it when the tab ends with a list or a blockquote, or markdown pulls the `::` into it
- The entire tabs block must end with `:::`
- Tab keys should be unique within a group for proper accessibility
