Tabs

Switch between panels containing related content.

Live preview
Interact with the component to see results here.
View code
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Usage guide

#

Separate and switch related content within one context. Use Navigation across the app and Steps for sequential tasks.

  1. Pair tabs with content

    Match sy-tab's tabkey to sy-tab-content's name.

  2. Set the active tab

    active starts at 0. Use setActiveTab() to switch in code.

  3. Many tabs or closable tabs

    Use the overflow menu to navigate many tabs. Set closable only on tabs that need a close action.

Examples

#

Basic tabs

Match tabkey to the content's name to switch panels.

View code
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Card style

Apply card styling to work areas that need a visible boundary.

View code
HTML
<sy-tab-group
  active="0"
  type="card"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Vertical tabs

Set position to left or right to place tabs beside the content.

View code
HTML
<sy-tab-group
  active="0"
  position="left"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Close a tab

The close icon removes both the tab and its associated content.

View code
HTML
<sy-tab-group
  active="0"
  type="card"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0" closable>Overview</sy-tab>
  <sy-tab tabkey="tab-1" closable>Activity</sy-tab>
  <sy-tab tabkey="tab-2" closable>Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Confirm before closing

After receiving a close request, use the confirmation button to remove the tab. Cancel keeps it open.

View code
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="height:190px"
>
  <sy-tab
    tabkey="draft"
    closable
    manual-close
  >Drafting</sy-tab>
  <sy-tab-content name="draft">
    <p>This draft has not been saved.</p>
  </sy-tab-content>
</sy-tab-group>
<div id="close-prompt" hidden>
  <p>Close the tab you are editing?</p>
  <sy-button id="confirm-close" variant="primary">Confirm close</sy-button>
  <sy-button id="cancel-close">Keep editing</sy-button>
</div>

<script type="module">
  await (root => {
    const group = root.querySelector('#sample');
    const prompt = root.querySelector('#close-prompt');
    let pending;
    group.addEventListener('closed', event => {
      if (!event.detail.isManualClose) return;
      pending = event.detail.tabkey;
      prompt.hidden = false;
    });
    root.querySelector('#confirm-close').addEventListener('click', async () => {
      await group.closeTab(pending);
      prompt.hidden = true;
    });
    root.querySelector('#cancel-close').addEventListener('click', () => {
      pending = undefined;
      prompt.hidden = true;
    });
  })(document);
</script>

Disable individual tabs

Only the Settings tab is disabled. Other tabs remain selectable.

View code
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2" disabled>Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

Control tabs in code

Switch by tab index, read the selected index, or close by key.

View code
HTML
<sy-tab-group
  active="0"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0" closable>Overview</sy-tab>
  <sy-tab tabkey="tab-1" closable>Activity</sy-tab>
  <sy-tab tabkey="tab-2" closable>Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Go to Activity tab</sy-button>
  <sy-button id="action-1" size="small">Read current tab</sy-button>
  <sy-button id="action-2" size="small">Close Settings tab</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setActiveTab(1);
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.getActiveTab();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.closeTab("tab-2");
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Many tabs

When space runs out, select hidden tabs from the overflow menu.

View code
HTML
<sy-tab-group active="0" style="width:100%;height:240px">
  <sy-tab tabkey="report-0">Report 1</sy-tab>
  <sy-tab-content name="report-0">
    <p>Content for report 1.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-1">Report 2</sy-tab>
  <sy-tab-content name="report-1">
    <p>Content for report 2.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-2">Report 3</sy-tab>
  <sy-tab-content name="report-2">
    <p>Content for report 3.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-3">Report 4</sy-tab>
  <sy-tab-content name="report-3">
    <p>Content for report 4.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-4">Report 5</sy-tab>
  <sy-tab-content name="report-4">
    <p>Content for report 5.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-5">Report 6</sy-tab>
  <sy-tab-content name="report-5">
    <p>Content for report 6.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-6">Report 7</sy-tab>
  <sy-tab-content name="report-6">
    <p>Content for report 7.</p>
  </sy-tab-content>
  <sy-tab tabkey="report-7">Report 8</sy-tab>
  <sy-tab-content name="report-7">
    <p>Content for report 8.</p>
  </sy-tab-content>
</sy-tab-group>

Events and payloads

Interact with the component and inspect the latest event name and detail. The code includes subscriptions to events emitted by this component and its children.

View code
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>
<output id="demo-events" aria-live="polite">Interact with the component to see
  its latest event and payload.</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  for (const name of ["selected", "closed", "ordered", "tabSelected", "tabClosed", "tabAdded"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

Handle requests to add tabs

The add button emits tabAdded to request a new tab. This example displays the request in the result. In an app, add both a new sy-tab and sy-tab-content.

View code
HTML
<sy-tab-group
  active="0"
  type="line"
  position="top"
  size="medium"
  align="left"
  padding="none"
  add-new-tab
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>
<output id="demo-events" aria-live="polite">Interact with the component to see
  its latest event and payload.</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "addNewTab": true
  });
  for (const name of ["tabAdded"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

Tab, content, and extra-action slots

Put tabs in tabs and their associated panels in contents. Use extra for supplementary content next to the tab list.

View code
HTML
<sy-tab-group active="0" style="height:220px">
  <sy-tab tabkey="overview" slot="tabs">Overview</sy-tab>
  <sy-tab tabkey="activity" slot="tabs">Activity</sy-tab>
  <sy-tab-content name="overview" slot="contents">Project overview
  </sy-tab-content>
  <sy-tab-content name="activity" slot="contents">Recent activity
  </sy-tab-content><span slot="extra">Team project</span>
</sy-tab-group>

Bottom tab navigation

Place centered tabs below their content panel.

View code
HTML
<sy-tab-group
  active="0"
  type="line"
  position="bottom"
  size="medium"
  align="center"
  padding="none"
  id="sample"
  style="width:100%;height:250px"
>
  <sy-tab tabkey="tab-0">Overview</sy-tab>
  <sy-tab tabkey="tab-1">Activity</sy-tab>
  <sy-tab tabkey="tab-2">Settings</sy-tab>
  <sy-tab-content name="tab-0">
    <p style="margin:20px 0">View project status at a glance.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-1">
    <p style="margin:20px 0">Review recent changes and team activity.</p>
  </sy-tab-content>
  <sy-tab-content name="tab-2">
    <p style="margin:20px 0">Manage the project's basic settings.</p>
  </sy-tab-content>
</sy-tab-group>

<script type="module">
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "position": "bottom",
    "align": "center"
  });
</script>

API reference

#

Hover over a name or focus it with the keyboard to see the code. On touch screens, tap the name.

<sy-tab-group>

Properties

Attribute / PropertyTypeDefaultDescription
numberundefinedCurrent tab index, starting at 0.
'center' | 'left''left'Left or center alignment of the tab row.
booleanfalseBlock user interaction and keyboard focus.
booleanfalseAllow tabs to be reordered by dragging.
"top" | "bottom" | "left" | "right""top"Item layout direction.
"card" | "line""line"line or card style.
"small" | "medium" | "large""medium"Component size.
"small" | "medium" | "large" | 'none'"none"Padding inside the tab area.
booleanfalseProvide an add button and the tabAdded event. The app creates the new tab.

Events

EventDetailDescription
CustomEvent<any>Emitted when the user selects an item.
CustomEvent<any>Read the result from the event's detail.
CustomEvent<HTMLSyTabElement[]>Read the result from the event's detail.
CustomEvent<{ index: number; value: string }>Read the result from the event's detail.
CustomEvent<{ index: number; value: string }>Read the result from the event's detail.
CustomEvent<void>Read the result from the event's detail.

Methods

MethodReturnsDescription
Promise<void>Remove a tab and its associated content by index or tabkey.
Promise<void>Select a tab by its zero-based index.
Promise<number | undefined>Return the current tab index, or undefined if no tab is selected.

Slots

SlotDescription
Content displayed in the tabs area.
Content displayed in the extra area.
Component body or child items.
Content displayed in the contents area.

<sy-tab>

Properties

Attribute / PropertyTypeDefaultDescription
booleanfalseShow the close button.
booleanfalseBlock user interaction and keyboard focus.
stringundefinedUnique tab key associated with the content's name.
booleanfalseEmit only a close request. After confirmation, call closeTab on the parent.
booleanfalseCurrently selected tab. Managed by the parent.
booleanfalseDisabled state passed down by the parent.
booleanfalseFinal disabled state combining the parent and individual settings.
numberundefinedItem index calculated by the parent.
"card" | "line""line"line or card style, passed down by the parent.
"small" | "medium" | "large""medium"Component size.
"top" | "bottom" | "left" | "right""top"Item layout direction.
booleanfalseTab styling inside Global Header, set by the header.

Events

EventDetailDescription
CustomEvent<any>Emitted when the user selects an item.
CustomEvent<any>Read the result from the event's detail.

Methods

MethodReturnsDescription
Promise<void>Close the item.

Slots

SlotDescription
Component body or child items.

<sy-tab-content>

Properties

Attribute / PropertyTypeDefaultDescription
booleanfalseWhether the content associated with the current tab is visible. Managed by the parent.
booleanfalseBlock user interaction and keyboard focus.
stringundefinedUse the same value as the tabkey of the sy-tab to display.

Slots

SlotDescription
Component body or child items.