# 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.