VTEX Tab Layout

Tab-layout is a layout structuring paradigm built within VTEX IO store framework to allow the construction of custom tabbed layouts. This paradigm uses the concept of a tab list containing tab list items (the tabs) and a tab content area containing tab content items (the content panes that the tabs control) to set the desired structure and visibility of components in a given page.

The tab-layout component provides a context for the tab-list and tab-content components to communicate with each other. A variety of layouts are possible as long as both of those are somewhere within tab-layout.

Blocks API

Since tab-layout should be widely used to achieve different layouts, its interface is very permissive:

"tab-layout": {
  "component": "TabLayout",
  "composition": "children",
  "allowed": "*"
},
"tab-list": {
  "component": "TabList",
  "composition": "children",
  "allowed": ["tab-list.item"]
},
"tab-list.item": {
  "component": "TabListItem"
},
"tab-content": {
  "component": "TabContent",
  "composition": "children",
  "allowed": "*"
},
"tab-content.item": {
  "component": "TabContentItem",
  "composition": "children",
  "allowed": "*"
}

Notice that you could use any array of blocks as children of tab-layout, given that they are allowed by the block that is directly above it. However, tab-list and tab-content must exist somewhere within tab-layout for the tab interface to function.

Only tab-list.items may exist inside tab-list, as those represent the actual tabs that users will interact with. Each tab should be given a tabId prop with a value that matches the tabId of a tab-content.item block.

Despite apparently allowing any block as its children, tab-content must only contain an array of tab-content.items as its children.

A tab-content.item can contain any array of blocks as its children, given that they are allowed by the parent of tab-content (or tab-layout as the case may be). Each tab content item should be given a tabId prop with a value that matches the tabId of a tab-list.item block.

Configuration

This props should be edited at your theme's blocks.json:

tab-layout

Prop nameTypeDescriptionDefault value
blockClassStringUnique class name to be appended to block container class""

tab-list

Prop nameTypeDescriptionDefault value
blockClassStringUnique class name to be appended to block container class""

tab-list.item

Prop nameTypeDescriptionDefault value
blockClassStringUnique class name to be appended to block container class""
tabIdStringA string used to match the tab to its content itemundefined
labelStringA string that determines the tab's text labelundefined
defaultActiveTabBooleanSet to true if this tab should be pre-selected when the page loads (only one tab should have this set to true)false

tab-content

Prop nameTypeDescriptionDefault value
blockClassStringUnique class name to be appended to block container class""

tab-content.item

Prop nameTypeDescriptionDefault value
blockClassStringUnique class name to be appended to block container class""
tabIdStringA string used to match the content item to its tabundefined

Styles API

This app provides some CSS classes as an API for style customization.

To use this CSS API, you must add the styles builder and create an app styling CSS file.

  1. Add the styles builder to your manifest.json:
"builders": {
  "styles": "1.x"
}
  1. Create a file called vtex.tab-layout.css inside the styles/css folder. Add your custom styles:
.container {
  margin-top: 10px;
}

CSS namespaces

Below, we describe the namespaces that are defined by tab-layout.

Class nameDescription
containerThe container of the entire tabbed layout.
listContainerThe container of the list of tabs.
listItemThe container of an individual tab.
contentContainerThe container of the tab content items.
contentItemThe container of an individual content item.

Rules and recommendations

  • Ensure that only one tab-list.item is given a defaultActiveTab prop of true.
  • Ensure that the tabId of each tab-list.item/tab-content.item pair matches exactly.

Example usage

The following creates a tab-layout with two tabs labeled "Home 1" and "Home 2":

"store.home": {
    "blocks": [
      "tab-layout#home"
    ]
  },
  "tab-layout#home": {
    "children": [
      "tab-list#home",
      "tab-content#home"
    ],
    "props": {
      "blockClass": "home"
    }
  },
  "tab-list#home": {
    "children": [
      "tab-list.item#home1",
      "tab-list.item#home2"
      ]
  },
  "tab-list.item#home1": {
    "props": {
      "tabId": "home1",
      "label": "Home 1",
      "defaultActiveTab": true
    }
  },
  "tab-list.item#home2": {
    "props": {
      "tabId": "home2",
      "label": "Home 2"
    }
  },
  "tab-content#home": {
    "children": [
      "tab-content.item#home1",
      "tab-content.item#home2"
    ]
  },
  "tab-content.item#home1": {
    "children": [
      "carousel#home"
    ],
    "props": {
      "tabId": "home1"
    }
  },
  "tab-content.item#home2": {
    "children": [
      "shelf#home",
      "info-card#home",
      "rich-text#question",
      "rich-text#link",
      "newsletter"
    ],
    "props": {
      "tabId": "home2"
    }
  }