Tabs
Tabs are layered sections of content that display one panel of content at a time. Each tab panel has an associated tab element; when this is activated, the panel is displayed. The list of tab elements is arranged along one edge of the currently displayed panel.
Use cases:
- creating blocks of contents that can be shown one at a time
- Associating a "tab" item with a title; when clicked, this shows the associated content
- Flashing a tab while a related grid still holds rows that need attention (see Alerting tabs)
You can use rapid-tabs, rapid-tab, rapid-tab-item to create your tabs.
Example
You can see tabs in action in the example below. This has three tabs; clicking on a tab displays the relevant content.
Primary style tabs
- Stuffed artichokes
- Bruschetta
- Tomato Bread Soup with Steamed Mussels
- Grilled Fish with Artichoke Caponata
- Tiramisu
- limoncello and Ice Cream with Biscotti
Secondary style tabs
- Counterparty 1
- Counterparty 2
- First Bank Account
- Second Bank Account
- React
- Genesis
- Angular
Declaration
<rapid-tabs>
<rapid-tab></rapid-tab>
<rapid-tab-panel>
<!-- content -->
</rapid-tab-panel>
</rapid-tabs>
Usage
@customElement({
name: 'my-element',
template: html<MyElement>`
<rapid-tabs activeid="entrees">
<rapid-tab id="apps">Appetizers</rapid-tab>
<rapid-tab id="entrees">Entrees</rapid-tab>
<rapid-tab id="desserts">Desserts</rapid-tab>
<rapid-tab-panel id="appsPanel">
<ol>
<li>Stuffed artichokes</li>
<li>Bruschetta</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel id="entreesPanel">
<ol>
<li>Tomato Bread Soup with Steamed Mussels</li>
<li>Grilled Fish with Artichoke Caponata</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel id="dessertsPanel">
<ol>
<li>Tiramisu</li>
<li>limoncello and Ice Cream with Biscotti</li>
</ol>
</rapid-tab-panel>
</rapid-tabs>
<rapid-tabs appearance="secondary">
<rapid-tab>Counterparties</rapid-tab>
<rapid-tab>Accounts</rapid-tab>
<rapid-tab-panel>
<ol>
<li>Counterparty 1</li>
<li>Counterparty 2</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel>
<ol>
<li>First Bank Account</li>
<li>Second Bank Account</li>
</ol>
</rapid-tab-panel>
</rapid-tabs>
`,
})
export class MyElement extends GenesisElement { }
Declaration
<Tabs>
<Tab></Tab>
<TabPanel>
</TabPanel>
</Tabs>
Usage
import { Tab, TabPanel, Tabs } from '@genesislcap/rapid-design-system/react';
export function MyComponent() {
return (
<>
<Tabs activeid="entrees">
<Tab id="apps">Appetizers</Tab>
<Tab id="entrees">Entrees</Tab>
<Tab id="desserts">Desserts</Tab>
<TabPanel id="appsPanel">
<ol>
<li>Stuffed artichokes</li>
<li>Bruschetta</li>
</ol>
</TabPanel>
<TabPanel id="entreesPanel">
<ol>
<li>Tomato Bread Soup with Steamed Mussels</li>
<li>Grilled Fish with Artichoke Caponata</li>
</ol>
</TabPanel>
<TabPanel id="dessertsPanel">
<ol>
<li>Tiramisu</li>
<li>limoncello and Ice Cream with Biscotti</li>
</ol>
</TabPanel>
</Tabs>
<Tabs appearance="secondary">
<Tab>Counterparties</Tab>
<Tab>Accounts</Tab>
<TabPanel>
<ol>
<li>Counterparty 1</li>
<li>Counterparty 2</li>
</ol>
</TabPanel>
<TabPanel>
<ol>
<li>First Bank Account</li>
<li>Second Bank Account</li>
</ol>
</TabPanel>
</Tabs>
</>
)
}
Declaration
<rapid-tabs>
<rapid-tab></rapid-tab>
<rapid-tab-panel>
<!-- content -->
</rapid-tab-panel>
</rapid-tabs>
Usage
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@Component({
selector: 'my-component',
template: `
<rapid-tabs activeid="entrees">
<rapid-tab id="apps">Appetizers</rapid-tab>
<rapid-tab id="entrees">Entrees</rapid-tab>
<rapid-tab id="desserts">Desserts</rapid-tab>
<rapid-tab-panel id="appsPanel">
<ol>
<li>Stuffed artichokes</li>
<li>Bruschetta</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel id="entreesPanel">
<ol>
<li>Tomato Bread Soup with Steamed Mussels</li>
<li>Grilled Fish with Artichoke Caponata</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel id="dessertsPanel">
<ol>
<li>Tiramisu</li>
<li>limoncello and Ice Cream with Biscotti</li>
</ol>
</rapid-tab-panel>
</rapid-tabs>
<rapid-tabs appearance="secondary">
<rapid-tab>Counterparties</rapid-tab>
<rapid-tab>Accounts</rapid-tab>
<rapid-tab-panel>
<ol>
<li>Counterparty 1</li>
<li>Counterparty 2</li>
</ol>
</rapid-tab-panel>
<rapid-tab-panel>
<ol>
<li>First Bank Account</li>
<li>Second Bank Account</li>
</ol>
</rapid-tab-panel>
</rapid-tabs>
`,
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class MyComponent { }
Alerting tabs
Set the boolean alert attribute on a rapid-tab when that desk still has work outstanding — for example while a blotter behind it holds pending orders. The tab flashes until you clear alert.
Keep alert true while matches exist, and false when none remain.
When you pair a tab with a grid, they flash together — same timing, same colour. Use the same row match criteria for both (DatasourceRowMatchTracker for the tab, createRowAlert for the rows).
alert only controls the flash. There is no count attribute on rapid-tab.
To show how many matches there are, read tracker.matchCount after every datasource update and put that number in the tab’s text (as below).
onActiveChanged only tells you whether any matches exist. It will not run again when the count goes from 3 to 5, so a label that updates only there can get stuck on the old number.
- React
- Genesis
- Angular
Usage
import { DatasourceRowMatchTracker } from '@genesislcap/rapid-grid-pro';
import { useMemo, useState } from 'react';
const criteria = { /* module-scope RowMatchCriteria — see Row alerts */ };
export function OrdersTabs() {
const [alerting, setAlerting] = useState(false);
const [matchCount, setMatchCount] = useState(0);
const tracker = useMemo(
() => new DatasourceRowMatchTracker(criteria, setAlerting),
[],
);
return (
<rapid-tabs>
<rapid-tab id="equity" alert={alerting}>
{matchCount > 0 ? `Equity (${matchCount})` : 'Equity'}
</rapid-tab>
<rapid-tab-panel id="equityPanel">
<grid-pro-genesis-datasource
resourceName="ALL_ORDERS"
onDatasourceDataChanged={(event) => {
tracker.handleDataChanged(event.detail);
setMatchCount(tracker.matchCount);
}}
onDatasourceDataCleared={() => {
tracker.handleDataCleared();
setMatchCount(tracker.matchCount);
}}
/>
</rapid-tab-panel>
</rapid-tabs>
);
}
Usage
import { DatasourceRowMatchTracker } from '@genesislcap/rapid-grid-pro';
import { GenesisElement, customElement, html, observable } from '@genesislcap/web-core';
const criteria = { /* module-scope RowMatchCriteria — see Row alerts */ };
@customElement({
name: 'orders-tabs',
template: html`
<rapid-tabs>
<rapid-tab id="equity" ?alert=${(x) => x.alerting}>
${(x) => (x.matchCount > 0 ? `Equity (${x.matchCount})` : 'Equity')}
</rapid-tab>
<rapid-tab-panel id="equityPanel">
<grid-pro-genesis-datasource
resource-name="ALL_ORDERS"
@datasource-data-changed=${(x, c) => x.onDataChanged(c.event)}
@datasource-data-cleared=${(x) => x.onDataCleared()}
></grid-pro-genesis-datasource>
</rapid-tab-panel>
</rapid-tabs>
`,
})
export class OrdersTabs extends GenesisElement {
@observable alerting = false;
@observable matchCount = 0;
private readonly tracker = new DatasourceRowMatchTracker(criteria, (active) => {
this.alerting = active;
});
onDataChanged(event: CustomEvent) {
this.tracker.handleDataChanged(event.detail);
this.matchCount = this.tracker.matchCount;
}
onDataCleared() {
this.tracker.handleDataCleared();
this.matchCount = this.tracker.matchCount;
}
}
Usage
import { DatasourceRowMatchTracker } from '@genesislcap/rapid-grid-pro';
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
const criteria = { /* module-scope RowMatchCriteria — see Row alerts */ };
@Component({
selector: 'orders-tabs',
template: `
<rapid-tabs>
<rapid-tab id="equity" [attr.alert]="alerting ? '' : null">
{{ matchCount > 0 ? 'Equity (' + matchCount + ')' : 'Equity' }}
</rapid-tab>
<rapid-tab-panel id="equityPanel">
<grid-pro-genesis-datasource
resource-name="ALL_ORDERS"
(datasource-data-changed)="onDataChanged($event)"
(datasource-data-cleared)="onDataCleared()"
></grid-pro-genesis-datasource>
</rapid-tab-panel>
</rapid-tabs>
`,
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class OrdersTabs {
alerting = false;
matchCount = 0;
private readonly tracker = new DatasourceRowMatchTracker(criteria, (active) => {
this.alerting = active;
});
onDataChanged(event: CustomEvent) {
this.tracker.handleDataChanged(event.detail);
this.matchCount = this.tracker.matchCount;
}
onDataCleared() {
this.tracker.handleDataCleared();
this.matchCount = this.tracker.matchCount;
}
}
Theming
| CSS custom property | Description |
|---|---|
--tab-alert-color | Flash colour for alerting tabs (defaults to the design-system error fill) |
--alert-flash-duration | Length of one flash cycle for every alerting surface on the page (tabs and rows); default 1s |
Set these on :root (or another shared ancestor). When you use createRowAlert with mirrorColorTo: ['--tab-alert-color'], a colour chosen from the grid’s Alert flash context menu also retints tab headers.
prefers-reduced-motion: reduce shows a static alert colour instead of flashing.
For matching rows, the presets menu, and numeric/boolean criteria, see Row alerts.
Tabs API
API examples shown with Genesis component syntax, and closing tag omitted.
Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
| orientation | "horizontal" | "vertical" | The orientation of the tabs menu. Default: "horizontal". | |
| activeid | string | The id of the active tab. Setting this allows you to configure the default opened tab, else the first tab is shown. | |
| activeindicator | boolean | Whether or not to show the active indicator on the active tab. Default: true. | |
| appearance | "primary" | "secondary" | Controls the appearance of the tabs. Default: primary. | |
Properties
| Property | Type | Description | Example |
|---|---|---|---|
| activetab | HTMLElement | The active tab element. You should only read this value, and not set it on the HTML. | |
| currentTabIndex | number | null | Zero-based index of the currently selected tab. | |
Slots
| Slot | Description |
|---|---|
| start | Content that can be provided before the tablist element |
| end | Content that can be provided after the tablist element |
| tab | The slot for tabs (<rapid-tab>) |
| tabpanel | The slot for tab panels (<rapid-tab-panel>) |
Parts
| Part | Description |
|---|---|
| tablist | The element wrapping for the tabs |
| tab | The tab slot |
| activeIndicator | The visual indicator |
| tabpanel | The tab panel slot |
Events fired
| Event | Type | Description | Example |
|---|---|---|---|
| change | HTMLElement | Fired when a tab is selected, or during keyboard navigation. The event data is active tab. | |
Events listened to
This component doesn't listen to any events.
Tab API
API examples shown with Genesis component syntax; the closing tag is omitted.
Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
| disabled | boolean | Disable the tab, if disabled it will not respond to user interaction. | |
| alert | boolean | When true, the tab flashes to draw attention (sustained alert). See Alerting tabs. | |
Properties
This component doesn't have any properties that are not also controlled via attributes.
Slots
| Slot | Description |
|---|---|
| Default | The default slot for the tab content. |
Parts
This component doesn't have any parts.
Events fired
This component doesn't fire any events.
Events listened to
This component doesn't listen to any events.
Tab panel API
API examples shown with Genesis component syntax, and closing tag omitted.
Attributes
This component doesn't have any attributes.
Properties
This component doesn't have any properties.
Slots
| Slot | Description |
|---|---|
| Default | The default slot for the main tab content. Only shown when the associated tab is active. |
Parts
This component doesn't have any parts.
Events fired
This component doesn't fire any events.
Events listened to
This component doesn't listen to any events.