<cv-tabgroup> <cv-tab>
The Tabs component lets you define mutually exclusive content sections that users can toggle between — perfect for organizing platform-specific, step-based, or categorized documentation.
When multiple tab groups (<cv-tabgroup/>) share the same group-id attribute, they stay synchronized automatically across the entire page.
Apple Information
Apples are crisp, sweet fruits that come in many varieties. They are rich in fiber and vitamin C.
Orange Information
Oranges are citrus fruits known for their high vitamin C content and refreshing juice.
Pear Information
Pears are sweet, bell-shaped fruits with a soft texture when ripe. They're high in fiber and antioxidants.
Apple Types
Apple types include Granny Smith and the Cosmic Crisp.
Orange Types
Orange types include the Blood orange and Valencia orange.
Pear Types
Pear types include the Asian pear and the European pear
id on the page. The state is saved to browser storage and persists across page reloads.id="fruit", a single-click on "Orange" in the first group only changes that group locally. Double-clicking on "Orange" will sync both groups to show "Orange" and save the state.Each tabgroup element should have a parent id attribute, while each tab element should have their own tab id as well.
However, if a tabgroup element does not have an id attribute, the tabgroup and children tabs will function as normal tabs. If the children tabs do not have id or header attributes, their headers will be enumerated.
For example:
CODE:
<cv-tabgroup>
<cv-tab>
Tab 1 Content
</cv-tab>
<cv-tab>
Tab 2 Content
</cv-tab>
</cv-tabgroup>
OUTPUT:
Tab 1 Content
Tab 2 Content
You can create a single tab that represents multiple alternative IDs by specifying multiple IDs separated by spaces or |
header attribute if provided).python java) present the same content, show a single tab instead of duplicates that might confuse readers into thinking the content differs.Example:
CODE:
<cv-tabgroup group-id="lang" >
<cv-tab tab-id="python" header="Python">
Python is a high-level, interpreted programming language known for its simplicity and readability.
</cv-tab>
<cv-tab tab-id="java" header="Java">
Java is a statically-typed, compiled language known for its robustness and platform independence.
</cv-tab>
<cv-tab tab-id="javascript" header="JavaScript">
JavaScript is a dynamic language primarily used for web development.
</cv-tab>
</cv-tabgroup>
<cv-tabgroup group-id="lang" >
<cv-tab tab-id="python java" header="Python/Java Installation">
Both Python and Java are easy to install. Download from their official websites.
</cv-tab>
<cv-tab tab-id="javascript" header="JS Installation">
Install JavaScript by downloading Node.js from nodejs.org.
</cv-tab>
</cv-tabgroup>
OUTPUT:
Python is a high-level, interpreted programming language known for its simplicity and readability.
Java is a statically-typed, compiled language known for its robustness and platform independence.
JavaScript is a dynamic language primarily used for web development.
Both Python and Java are easy to install. Download from their official websites.
Install JavaScript by downloading Node.js from nodejs.org.
Behavior: In the second tab group, you'll see a single "Installation" tab in the navigation bar that becomes active when either Python or Java is selected in the first group. This avoids showing duplicate tabs with identical content.
By default, the first tab in a group is selected when the page loads (unless the user has previously selected a different tab, in which case their selection is restored).
You can override this default behavior and specify which tab should be initially selected using the custardui.config.json, by adding a default property to the tabGroup.
Default Tab Example Configuration: To make the "orange" tab selected by default for the "fruit" group:
{
"config": {
"tabGroups": [
{
"groupId": "fruit",
"default": "orange",
"tabs": [...]
}
]
}
}
In addition to the standard header attribute, you can use an alternative syntax with <cv-tab-header> and <cv-tab-body> elements to enable rich HTML formatting in your tab headers.
This is useful when you need:
Key Points:
<cv-tab-header> is the recommended way to define headers. It takes precedence over the header attribute.<cv-tab-header>: Supports both MarkBind shortcodes (e.g., :fa-user:) and raw HTML. MarkBind processes the content automatically.header="..." attribute: Supports raw HTML only (e.g., header='<i class="fa-solid fa-user"></i> Title' to display an icon, and bold is header='<strong>Important</strong>'). MarkBind shortcodes will not work in attributes.<cv-tab-header> exists but is empty, the tab ID is used as the fallback header label.Structure:
<cv-tab tab-id="tab-id">
<cv-tab-header>Header content (supports HTML)</cv-tab-header>
<cv-tab-body>Tab body content (both can be used together)</cv-tab-body>
Tab body content (both can be used together)
</cv-tab>
<cv-tabgroup> Attributes| Name | Type | Default | Description |
|---|---|---|---|
| group-id | string | (required) | Unique identifier for the tab group. Tab groups with the same ID will synchronize. |
| nav | string | "auto" | Navigation display mode. Use "none" to hide navigation headers. |
<cv-tab> Attributes| Name | Type | Default | Description |
|---|---|---|---|
| tab-id | string | (required) | Unique identifier for the tab within its group. |
| header | string | Tab ID | Display label for the tab. Supports plain text and raw HTML (e.g., icons via <i> tags). Does not support MarkBind shortcodes. |
<cv-tab-header> AttributesNo required attributes, just a container for the tab header content.
<cv-tab-body> AttributesNo required attributes, just a container for the tab body content.
Tab groups work out of the box with no setup — just use the <cv-tabgroup> and <cv-tab> elements.
By default, the first tab is shown.
For more control (such as settings integration or default selections), configure them in your custardui.config.json.
{
"config": {
"tabGroups": [
{
"groupId": "fruit",
"label": "Fruit Selection",
"isLocal": false,
"default": "apple",
"tabs": [
{ "tabId": "apple", "label": "Apple" },
{ "tabId": "orange", "label": "Orange" },
{ "tabId": "pear", "label": "Pear" }
]
},
{
"groupId": "localTabGroup",
"label": "Page specific tabgroup",
"isLocal": true,
"default": "c",
"tabs": [
{ "tabId": "a", "label": "Alpha" },
{ "tabId": "b", "label": "Beta" },
{ "tabId": "c", "label": "Charlie" }
]
}
]
}
}
The TabGroupConfig object is for defining tabgroups in JSON configuration.
| Name | Type | Default | Description |
|---|---|---|---|
| groupId | string | (required) | Group identifier (must match HTML cv-tabgroup id). |
| label | string | - | Display name shown in the settings. |
| description | string | - | Optional description to display below functionality. |
| isLocal | boolean | false | Set to true to make the group only appear in the settings on pages where it's used. |
| default | string | - | The tabId of the tab that should be selected by default. |
| tabs | TabConfig[] | (required) | Array of tab configurations. |
The TabConfig object is for defining tabs in JSON configuration.
| Name | Type | Default | Description |
|---|---|---|---|
| tabId | string | (required) | Tab identifier (must match HTML cv-tab id). |
| label | string | - | Display label for the tab (used in settings and as fallback for header). |
Note: Configuration is completely optional. Tab groups will work fine without being added to the config file—they'll just default to showing the first tab and won't appear in the settings.
You can bind a tab group to a placeholder variable. Selecting a tab will automatically set the variable's value.
| Name | Type | Description |
|---|---|---|
| placeholderId | string | Added to TabGroupConfig. The name of the placeholder variable to update. |
| placeholderValue | string | Added to TabConfig. The value to set when this tab is active. |
Example:
{
"groupId": "code-switch",
"placeholderId": "lang",
"tabs": [
{ "tabId": "java", "label": "Java", "placeholderValue": "java" },
{ "tabId": "python", "label": "Python", "placeholderValue": "python" }
]
}
By default, all tab groups defined in your configuration are global—they will appear in the settings on every page of your site.
You can mark a tab group as local to make it appear in the settings only on pages where that specific tab group is actually used. This is useful for keeping the settings clean and only showing relevant options to the user.
To mark a tab group as local, add "isLocal": true to its configuration.
Example:
For example, this tab group is only specific to this page:
By setting it as local in the configuration, the "Local Tab Configuration" option will only show up in the settings on pages containing that tab group.
If all tab configurations (and other component configurations) are local, and a given page has no configured elements, neither the modal nor the modal icon will appear.
Configuration file setting this option:
{
"config": {
"tabGroups": [
{
"groupId": "ltab",
"label": "Local Tab Configuration",
"isLocal": true, // This makes the group local
"tabs": [
{ "tabId": "lt1", "label": "Tab Option 1" },
{ "tabId": "lt2", "label": "Tab Option 2" },
{ "tabId": "lt3", "label": "Tab Option 3" }
]
}
]
}
}
You can ensure that specific local tab groups are always available in the settings, even if they are not initially visible on the page. This is useful for tab groups that are loaded dynamically (e.g., inside a dropdown menu) and might not be detected by the plugin otherwise.
To do this, add a data-cv-page-local-tabs attribute to any element (an empty <div> is a good choice). The value of this attribute should be a comma-separated list of the local tab group IDs you want to register.
For example, to make the local tab groups with IDs OS and language available in the settings, add the following to your page:
<div data-cv-page-local-tabs="OS, language"></div>
This will ensure that the specified local tab groups appear in the configuration settings, allowing users to control them even if they are not immediately visible on the page.
Active tab selections can be encoded in a URL using the tabs parameter. The format is a comma-separated list of groupId:tabId pairs, where each group ID and tab ID is individually encoded with encodeURIComponent.
| Parameter | Format | Example |
|---|---|---|
tabs | Comma-separated groupId:tabId pairs | ?tabs=os:linux,lang:python |
?tabs=os:linux,lang:python
Only the tab groups explicitly listed are affected; all others retain the visitor's saved selection or the configured default.
Constructing the URL in JavaScript:
const tabs = { os: 'linux', lang: 'python' };
const param = Object.entries(tabs)
.map(([g, t]) => `${encodeURIComponent(g)}:${encodeURIComponent(t)}`)
.join(',');
const url = `https://yoursite.com/guide.html?tabs=${param}`;