# CodeGroup
> Tabbed set of code blocks with site-wide sync via SyncKey. For "same thing in three package managers."
Source: https://shelldocs.shellui.dev/docs/components/code-group
`CodeGroup` wraps a set of `CodeTab` children in a tabbed panel with a code-block frame. Give several groups the same `SyncKey` and they switch together, on every page, and remember the choice between visits.
## Basic use
**dotnet CLI**
```bash
dotnet add package ShellDocs.Components --prerelease
```
**PackageReference**
```xml
```
Write it as an inline tag in the page, with a fenced block in each tab. Leave a blank line between the tags and the fences:
````markdown
```bash
dotnet add package ShellDocs.Components --prerelease
```
```xml
```
````
## Syncing tabs
Set the same `SyncKey` on every group that should stay in step. Pick a tab in either group below and the other follows:
**dotnet CLI**
```bash
dotnet add package ShellDocs.Core --prerelease
```
**PackageReference**
```xml
```
**dotnet CLI**
```bash
dotnet add package ShellDocs.Markdown --prerelease
```
**PackageReference**
```xml
```
> **The choice follows the reader**
>
> `SyncKey="pkg"` is the convention on this site for install snippets. The selection is saved in `localStorage`, so it carries to other pages and to the next visit.
## Rich tab content
Tab bodies are markdown, so a tab can hold several code blocks, prose, or other components.
**With the CLI**
```bash
shelldocs init MyDocs
cd docs/MyDocs.Docs
shelldocs dev
```
**By hand**
```bash
dotnet new blazor -o MyDocs.Docs
cd MyDocs.Docs
dotnet add package ShellDocs.Components --prerelease
```
Then wire up `Program.cs` and `App.razor` : see [attach mode](https://shelldocs.shellui.dev/docs/cli/init.md).
## Props
### CodeGroup
| Name | Type | Default | Description |
|------|------|---------|-------------|
| `SyncKey` | `string?` | `—` | Groups with the same key switch together, across pages, and remember the choice in localStorage. |
| `ChildContent` | `RenderFragment?` | `—` | The CodeTab children. Must be direct children. |
### CodeTab
| Name | Type | Default | Description |
|------|------|---------|-------------|
| `Label` (required) | `string` | `—` | Tab label. Also the value sync matches on : tabs with the same label in the same sync group switch together. |
| `ChildContent` | `RenderFragment?` | `—` | Tab body. |
## How it works
The tab strip and every panel are rendered on the server. `shelldocs.js` switches panels through `data-tabs`, `data-tab-target` and `data-tab-panel` attributes, so a `CodeGroup` works on a static host with no Blazor runtime. It follows the WAI-ARIA tabs pattern : arrow keys move between tabs, Home and End jump to the first and last.
Sync matches tabs by `Label`. Two groups sharing a key only move together on labels they have in common.
`CodeGroup` and [`Tabs`](https://shelldocs.shellui.dev/docs/components/tabs.md) share this mechanism. Use `Tabs` when the panels are not code.
## See also
- [Tabs](https://shelldocs.shellui.dev/docs/components/tabs.md): The same tab mechanism for any content.
- [Fenced code](https://shelldocs.shellui.dev/docs/authoring/fenced-code.md): Everything ShellDocs does with fenced code blocks.