Extensions

Creating Tab Outlets

Updated:

How to implement a tecton-tabbed-outlet in your platform to render extensions as tabs.

Tab outlets render one or more extensions as tabs within a tabbed interface. The platform hosts the <tecton-tabbed-outlet> element, which resolves which extensions should appear as tabs and manages their loading states. Each extension contributes a tab loaded inside an iframe.

How Tab Outlets Work

When a <tecton-tabbed-outlet> is placed in a platform's template, it:

  1. Sends a resolution request to the platform with its outlet path, context, and context value
  2. The platform resolves which extensions should appear as tabs based on the outlet configuration and context matching
  3. For each resolved tab, a <tecton-tab-pane> is created containing an iframe that loads the extension
  4. The tab container handles user interaction (switching tabs, active state)

Adding the Element

Add <tecton-tabbed-outlet> to your platform template where you want the tabbed interface to appear. Wrap a <q2-tab-container> inside it — platform-provided tabs can be placed alongside extension-contributed tabs:

<tecton-tabbed-outlet
    name="AccountDetails.main.tabs"
    context="Account::Q2Account"
    contextValue={{accountId}}
    resolvedType={{accountType}}
    min-height="450px"
>
    <q2-tab-container name="account-details-tabs" value={{currentTab}}>
        <!-- Platform-provided tabs sit alongside extension tabs -->
        <tecton-tab-pane value="transactions" label="Transactions" name="account-details-tabs">
            <!-- Platform-owned tab content -->
        </tecton-tab-pane>
    </q2-tab-container>
</tecton-tabbed-outlet>

Attributes

Attribute
Type
Description
name
string
The outlet path identifier. Extensions reference this to register tabs.
context
string
The context type for this outlet (e.g., Account::Q2Account, Transaction::Q2Transaction, None).
contextValue
string
The current context value (e.g., the account ID).
resolvedType
string
The resolved subtype of the context (e.g., Checking, Savings). Used for context filtering.
additionalContext
string
Additional context data for granular filtering (e.g., product ID).
contextId
string
The context identifier parameter name (e.g., accountId).
outlet-selector
string
Identifies the outlet for theme CSS targeting. See Outlet Selectors.
min-height
string
Minimum height CSS value applied to the tab container while loading.

Tab Selection Events

The <q2-tab-container> emits a tctChange event whenever the selected tab changes. The event payload is { value: string }, where value is the value attribute of the newly selected <tecton-tab-pane>. Use this event to react to tab changes — for example, to update a URL fragment or persist the user's last-viewed tab.

<tecton-tabbed-outlet name="AccountDetails.main.tabs" ...>
    <q2-tab-container name="account-details-tabs">
        <tecton-tab-pane value="transactions" label="Transactions" name="account-details-tabs">
            <!-- ... -->
        </tecton-tab-pane>
    </q2-tab-container>
</tecton-tabbed-outlet>

<script>
    document.querySelector('q2-tab-container')
        .addEventListener('tctChange', e => {
            console.log('Selected tab:', e.detail.value);
        });
</script>

Setting value on Platform-Authored Tab Panes

For tab panes you author directly inside a <q2-tab-container>, set the value attribute to a stable identifier of your choosing. This identifier is what tctChange will emit when the tab is selected, and it's also what <q2-tab-container value="..."> uses to mark a tab as initially selected.

<q2-tab-container name="account-details-tabs" value="transactions">
    <tecton-tab-pane value="transactions" label="Transactions" name="account-details-tabs">
        <!-- emits { value: 'transactions' } when selected -->
    </tecton-tab-pane>
    <tecton-tab-pane value="statements" label="Statements" name="account-details-tabs">
        <!-- emits { value: 'statements' } when selected -->
    </tecton-tab-pane>
</q2-tab-container>

Choose values that are stable identifiers — not display copy — so that label changes don't break listeners.

value for Dynamically Inserted Extension Tabs

When the platform resolves an extension into a tab outlet, the dynamically inserted <tecton-tab-pane> automatically receives a stable value derived from its moduleId. Specifically, the value is featureName.moduleName.

For example, if an extension named MyFeature contributes a module called Main to the AccountDetails.main.tabs outlet, the resolved moduleId is AccountDetails.main.tabs.MyFeature.Main and the inserted tab pane's value will be MyFeature.Main. Selecting that tab emits:

{ value: 'MyFeature.Main' }

This identifier is independent of the tab's display label, so editing tabLabel in an extension's configuration won't break consumers listening for the tab's tctChange value.

How Extensions Map to Outlets

The mapping between an extension's CLI configuration and the platform's outlet element is handled through the Tecton configuration system. When the CLI configures a tabbed outlet, it writes an entry like:

ACCOUNT_DETAILS_TABS = [
    {
        'tabLabel': 'My Tab',
        'modules': [{'moduleName': 'Main'}]
    }
]

This maps to the AccountDetails.main.tabs outlet in the platform. The platform reads these configurations and resolves which tabs should appear for the current context.

For information on how extension developers configure their extensions to appear in tab outlets, see Loading Into Tab Outlets.