Tabs Block
The Tabs block is a tabbed container: a horizontal strip of tabs where selecting one shows its content. Tabs has two sources — Manual, where you author each tab by hand and every tab owns its own canvas area, and Mapped, where the strip is generated from a data source and all tabs share one content area.
| Manual | Mapped | |
| Tab strip source | Hand-authored list | Generated from a data source |
| Content areas | One canvas area per tab | One shared content area for all tabs |
| Per-tab options | Full set (disabled, error, visibility, permissions…) | Mapping fields only (label, value, link, badge, icon) |
| Default tab | Open by Default dropdown (supports conditions) | Initial Value expression |
Tabs — Top-Level Properties
| Property | Type | Default | Description |
| tabType | "manual" | "mapped" | manual | Where tabs come from. New blocks start with 3 example tabs in Manual mode |
| items | array of tabs | 3 example tabs | Hand-authored tab list. Only for Manual type |
| mappedTab | data mapping | — | Data source mapping that generates the strip. Only for Mapped type |
| defaultValue | string (tab value) | first tab | The tab selected at load. Supports conditional values in manual mode (Open by Default) |
| slots.header | block slot | — | Container rendered above the tab strip |
| slots.footer | block slot | — | Container appended at the end of each manual tab's content panel (not available in Mapped) |
| slots.divider | block slot | — | A small element rendered between tab items in the strip |
| interactions | event list | — | Attaches actions to the On Change event |
| permissions | permission rule | — | Restricts who sees the whole block |
Manual Tab Properties
Open a tab from Inspector → Content → Tabs to configure each individual tab:
| Property | Type | Default | Description |
| Label | string (translatable) | generated | The tab's visible title |
| Disabled | condition | off | When true, tab is visible but cannot be selected |
| Error | condition | off | When true, tab renders in error styling |
| To | string | — | A link target for the tab |
| Badge | string (translatable) | — | Small counter text shown next to the label |
| Start Icon | icon (conditional) | — | Icon shown before the label |
| Icon Color | color | — | Color of the start icon. Pill variant (web) only |
| Visibility | conditions | visible | Show/hide this individual tab |
| Permissions | permission rule | — | Restrict who sees this individual tab |
Mapped Tabs — Configuration
With Mapped type, configure a data source and field mappings:
| Property | Required | Description |
| Data Source | Required | The array of objects — one tab per row |
| Value | Required | The field holding each tab's unique value |
| Label | Required | The field holding each tab's display title |
| To | Optional | Per-row link target |
| Badge | Optional | Per-row badge text |
| Start Icon | Optional | Per-row icon before the label |
| Start Icon Options | Optional | Per-row icon styling (e.g., color). Used by pill-style tabs |
| Initial Value | Optional | The tab value to select at load. Falls back to the first tab |
Warning: Data Source + Value + Label are all required. Until all three are set, the block shows an "Invalid configuration" notice instead of the strip.
Tabs Events & Methods
| Event / Method | Type | Description |
| On Change | Event | Fires when the user selects a different tab. Does NOT fire for programmatic tab switches |
| Change Tab | Method | Switches the active tab programmatically. Takes a Destination Tab value. Does not fire On Change |
Tabs — Exposed State
| Binding | Type | Description |
{{ id.data }} | array | The resolved tabs (id, label, value, disabled, error, badge, visible) after filtering |
{{ id.activeTab }} | tab object | The currently selected tab |
{{ id.activeTabIndex }} | number | Position of the active tab in the visible strip |
{{ id.defaultTab }} | tab object | The tab configured as the default |
{{ id.content.value }} | string | The active tab's value (kept for backward compatibility) |
{{ id.context.currentTabItem }} | tab object | The owning tab — available only inside a manual tab's content area |
Tabs Behaviors & Gotchas
Warning: Hidden/permission-blocked tabs disappear entirely: They are removed from the strip; activeTabIndex counts only surviving tabs. Use Disabled when you want a visible-but-locked tab.
Warning: If the active tab vanishes, the block snaps to the default: If the current tab is removed (visibility flips, permissions change, mapped row disappears), the block auto-selects the default tab. No On Change fires for this reset.
Note: Tab strip scrolls, doesn't wrap: When tabs don't fit the available width, the strip becomes horizontally scrollable — tabs never wrap to a second row.
Note: Mapped method tab list is frozen at first load: The Change Tab method resolves its destination against tabs captured at first load. New rows added later can't be targeted until page reload.
Note: Footer slot belongs to content, not the block: Footer renders at the end of each manual tab's content — it scrolls with the panel. In mapped mode the footer doesn't render at all.
Tabs — Examples
Stepped Container Block
The Stepped Container holds the page content for each step of a wizard. You link it to a Stepper or Stepper V2 block; it maintains one content panel per step and swaps panels automatically as the user navigates. The panel list is managed for you — add, rename, or remove steps on the linked stepper and the container's panels follow.
Note: Only the active step's panel is rendered. Panels for other steps are absent from the page, not hidden — blocks inside them don't run until the user reaches that step.
Stepped Container Properties
| Property | Type | Description |
| stepperId | block reference (Stepper / Stepper V2) | The stepper block this container follows. Required for panels to appear |
| items | array (auto-managed) | Per-step panels. Generated automatically from the linked stepper — not directly editable |
| interactions | event list | On Click — fires when user clicks anywhere in the container |
| permissions | permission rule | Restrict who sees the block |
| styles | style set | Width, height, flex layout, margin, padding, gap, overflow, background, shadow, stroke, radius. New containers start with large gap, primary background, xl padding |
| visibility | conditions | Show/hide the whole container |
| theme | inherit | light | dark | Theme override for all panel content |
Stepped Container — Exposed State
| Binding | Type | Description |
{{ id.content.stepperId }} | string | The linked stepper block ID |
{{ id.content.items }} | array | The per-step panels (label, step value, panel content reference) |
{{ id.appearance }} | object | The container's style settings |
Stepped Container Behaviors & Gotchas
Warning: No matching panel = container disappears entirely: If no stepper is linked, or the current step has no panel, the block renders nothing — not an empty box. A "vanished" container means the Stepper property is unset or the step value matches no panel.
Warning: Changing a step's value orphans its panel: Panels are matched by step value, not label. Renaming a step relabels the panel, but changing a step's underlying value creates a fresh empty panel — the content you built for the old value is no longer reachable.
Warning: Panels are created at build time: If the linked stepper's steps come from data and a new step value appears only at runtime, the container has no panel for it — that step shows nothing.
Note: Steps with sub-steps get no panel: The container creates panels only for leaf steps (no sub-steps). Parent steps are skipped — put the parent's content in its first sub-step.
Stepped Container — Examples
Tabs vs. Stepped Container
| Feature | Tabs | Stepped Container |
| Navigation model | Free — user can visit any tab in any order | Ordered — follows a Stepper block's current step |
| Content areas | Manual: one per tab. Mapped: one shared | One panel per step, auto-managed |
| Data-driven | Yes (Mapped type) | No (panels follow the stepper) |
| Tab strip / progress header | Built-in tab strip | Provided by the paired Stepper block |
| Events | On Change (user click) | On Click |
| Methods | Change Tab | None (navigation via stepper) |
Frequently Asked Questions
Why is my Tab not showing even though it exists in the list?
A tab with a failing Visibility condition or a Permissions rule that blocks the current user is removed entirely from the strip — not greyed out. Check the tab's Visibility and Permissions settings. Use the Disabled condition instead if you want the tab visible but unclickable.
How do I switch to a specific tab programmatically (e.g., from a button click)?
Add a Control block method action to the button, pick the Tabs block, and select the Change Tab method. Set the Destination Tab to the target tab's value. Note: this does not fire the Tabs block's On Change event — attach any follow-up actions to the button itself.
What is the difference between Mapped tabs and Manual tabs?
Manual tabs: you author each tab by hand, and each tab gets its own canvas area with individual content. Mapped tabs: the tab strip is generated from a data source (one tab per row), but all tabs share a single content area that you configure once and drive from the active tab's state bindings.
Why does a panel in my Stepped Container show as empty?
Panels are matched by the step's underlying value, not its label. If you changed a step's value, the old panel is orphaned and a new empty one is created. Also check that a Stepper block is linked in the Stepped Container's Stepper property. If no stepper is linked, no panels are shown.
Can I use a Stepped Container without a Stepper header?
The Stepped Container requires a linked Stepper or Stepper V2 block to know which step is active. You don't have to show the stepper on screen, but it must exist somewhere on the page and be linked. If you only want to switch between sections without a progress indicator, use a Tabs block with the strip hidden or a Container with visibility conditions instead.