Skip to main content

Creating a Tab Bar

A tab bar can help with quick navigation in your app. Especially if your app is divided into different sections. A tab count of 2 to 5 is optimal.

A tab bar in mos. is created through the interaction of several files. First, the start_config must be set to tab and reference the tabView template. Accordingly, the client_template tabView is required. In addition, each tab requires its own layout file, in which the contents of the respective tab are specified. To add layers to the tab bar, an additional layout file and client templates for each tab are required.

You can skip straight to the copyable code of this tutorial or follow the step by step instructions.

The following mos. components are used in this tutorial. If needed, you can refer to the corresponding wiki pages:

Step by step

Following these instructions you will be able to create a tab bar for your app.

Setting up the tab bar

First, the project needs to be set up to use a tab bar.

For this, the start config has to be edited.

/start_config/default.json
{
"name": "default",
"content": {
"type": "tab",
"staticTemplate": "tabView",
"templateIsNode": true
}
}
  • Go to the default.json file in the /start_config directory.
  • Set the type to tab, the staticTemplate to tabView and remove the line "layout": "startView", in the content object.

The tabs have to be defined in the client template, which is referenced in the start config under the field statictemplate.

/client_template/tabView.json
{
"name": "tabView",
"content": {
"title": "Tab View",
"content": {
"tabs": [
{
"layout": "c_homeTabContent",
"title": "Home",
"staticTemplate": "homeTab",
"templateIsNode": true
},
{
"layout": "c_awayTabContent",
"title": "Away",
"staticTemplate": "awayTab",
"templateIsNode": true
}
]
}
}
}
  • Create a new file tabView.json in the /client_template directory.
  • Add a name field and set its value to tabView.
  • Add your tabs in the tabs array. Each tab should have a layout field refering to the layout file that is displayed when the tab is active

Each tab requires the corresponding layout file, which is referenced in the tabView client template.

/layout/c_homeTabContent
{
"name": "c_homeTabContent",
"layers": [
{
"type": "color",
"name": "backgroundColor",
"classes": [
"fullSize",
"background"
]
},
{
"type": "text",
"value": "Home",
"scaleType": "alignCenter",
"classes": [
"fullSize",
"text"
]
}
]
}
  • Create a new file in the /layout directory for each tab you have specified in the tabs array in tabView.json, e.g. c_homeTabContent.json.
  • Add a name field and set its value according to the tab/file name, e.g. c_homeTabContent.
  • Add the layers and actions you wish. This is the content that is displayed when the tab is active.
Screenshot of the tab bar with layout files for the content. Home tab active. Screenshot of the tab bar with layout files for the content. Away tab active.

The tab bar with layouts for the content of each tab.

The project has been set up to use a tab bar.

Adding a layout to the tab bar

To add layers to the tab bar, an additional layout file is needed.

Each tab requires a client template that specifies the values to be displayed in the tab bar layout.

/client_template/homeTab.json
{
"name": "homeTab"
}
  • Create a new file homeTab.json in the /client_template directory.
  • Add a new name field and set the value to homeTab.
/client_template/homeTab.json
{
"name": "homeTab",
"content": {
"title": "Home"
}
}
  • Add a new content object.
  • Add a new title field in the content object and set its value to Home.
/client_template/homeTab.json
{
"content": {
"title": "Home",
"content": {
"tabText": {
"value": "Home"
},
"tabIcon": {
"value": "fa-home"
}
}
}
}
  • Add another content object within the first one.
  • Add a new tabText object to the new content object.
  • Set the value in the tabText object to Home.
  • Add a new tabIcon object to the same content object.
  • Set the value in the tabIcon object to fa-home. This will translate to a Font Awesome icon later on.
note
  • Repeat these steps for all tabs with the corresponding values.

The style file has to be edited so that it references the layout of the tab bar.

/style/default.json
{
"name": "default",
"content": {
"content": {
"default": {
"tabbarLocation": "Bottom",
"tabbarHeights": {
"default": "56pt"
},
"tabbarLayout": "t_tabbar",
"navbarDisabled": true,
}
}
}
}
  • Go to the file default.json in the /style directory.
  • Add the following fields to the content object and set their values according to your preferences:
    • tabbarLocation
    • tabbarHeights
  • Add a tabbarLayout field to the content object and set its value to t_tabbar. This specifies the layout that is used for the tab bar.
Screencapture of the tab bar after editing the style file.

The tabbar with after editing the style file, but the corresponding layout file is missing.

The tab bar layout file contains the layers displayed in the tab bar. The values for these layers are specified in the respective client templates for each tab.

/layout/t_tabbar.json
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
"value": "#2B2F2F",
"classes": [
"fullSize"
]
}
]
}
  • Create a new file t_tabbar.json in the /layout directory. This will contain the layers for the tab bar.
  • Add a name field and set its value to t_tabbar.
  • Add a layers array.
  • Add a color layer to the layers array. This will set the background color of the tab bar.
  • Set the value of the color layer to #2B2F2F or another color of your choice.
  • Give the color layer the class fullSize, as it is restricted by the dimensions of the tab bar.
/layout/t_tabbar.json
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
...
},
{
"type": "text",
"dataKey": "tabIcon",
"font": "FontAwesome",
"fontColor": "#F3F3F3",
"scaleType": "alignCenter",
"fontSize": "30pt",
"constraints": [
{
"type": "pos",
"x": 0,
"y": "5pt"
},
{
"type": "pos",
"anchor": "e",
"relativeAnchor": "e",
"x": 0
}
]
}
]
}
  • Add a text layer to the layers array.
  • Add a dataKey field to the text layer and set its value to tabIcon. This refers to the tabIcon object in the client_templates.
  • Add a font field to the text layer and set its value to FontAwesome.
  • Style the text layer by setting the values for the following fields according to your preferences:
    • fontColor
    • scaleType
    • fontSize
    • constraints
/layout/t_tabbar.json
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
...
},
{
"type": "text",
"dataKey": "tabIcon",
...
},
{
"type": "text",
"dataKey": "tabText",
"fontColor": "#F3F3F3",
"scaleType": "alignCenter",
"fontSize": "12pt",
"constraints": [
{
"type": "size",
"height": "14pt"
},
{
"type": "pos",
"x": 0,
"y": "-0pt",
"anchor": "sw",
"relativeAnchor": "sw"
},
{
"type": "pos",
"x": 0,
"anchor": "e",
"relativeAnchor": "e"
}
]
}
]
}
  • Add another text layer to the layers array.
  • Add a datakey field to the new text layer and set its value to tabText. This refers to the tabText object in the client_templates.
  • Style the new text layer by setting the values for the following fields according to your preferences:
    • fontColor
    • scaleType
    • fontSize
    • constraints
Screencapture of the tab bar with an added tab bar layout.

A layout has been added to the tab bar.

Adding highlighting to the tab bar

Highlighting the active tab adds to a good user experience and improves navigatio in the app.

For this, additional content objects have to be added to the tab client templates.

/client_template/homeTab.json
{
"name": "homeTab",
"content": {
"title": "Home",
"content": {
"tabText": {
"value": "Home"
},
"tabIcon": {
"value": "fa-home"
},
"tabIconActive": {
"value": "fa-home",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 0
},
"mode": "equals"
}
}
]
}
}
}
}
  • Go to the file homeTab.json in the /client_template directory.
  • Add a new tabIconActive object to the inner content object.
  • Set the value in the tabIconActive object to fa-Home, the same as in the tabIcon object.
  • Add a conditions array to the tabIconActive object.
  • Add a state field to the conditions array and set its value to visible.
  • Add a conditions object to the conditions array with the fowllowing values:
    • left
      • context: tabView
      • field: currentTab
    • right:
      • value: 0
    • mode: equals

This compares the index of the active tab (left) to 0 (right). If the two sides are equal (mode), the condition returns true, indicating that the condition is fulfilled. This means, that the state of the tabIconActive object is set to visible if the condition is met.

/client_template/homeTab.json
{
"name": "homeTab",
"content": {
"title": "Home",
"content": {
"tabText": {
"value": "Home"
},
"tabIcon": {
"value": "fa-home"
},
"tabIconActive": {
"value": "fa-home",
...
},
"tabTextActive": {
"value": "Home",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 0
},
"mode": "equals"
}
}
]
}
}
}
}
  • Add a new tabTextActive object to the inner content object.

The same steps are now carried out for tabTextActive as previously for tabIconActive.

  • In the tabTextActive object, set the value to Home, the same as in the tabText object.
  • Add a conditions array to the tabTextActive object.
  • Add a state field to the conditions array and set its value to visible.
  • Add a conditions object to the conditions array with the fowllowing values:
    • left
      • context: tabView
      • field: currentTab
    • right:
      • value: 0
    • mode: equals
note
  • Repeat these steps for all tabs with the corresponding values.

Finally, layers for the highlighting have to be added to the tab bar layout.

/layout/t_tabbar.json
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
...
},
{
"type": "text",
"dataKey": "tabIcon",
...
},
{
"type": "text",
"dataKey": "tabText",
...
},
{
"type": "text",
"dataKey": "tabIconActive",
"font": "FontAwesome",
"fontColor": "#34A7C9",
"scaleType": "alignCenter",
"fontSize": "30pt",
"states": {
"visible": {
"hidden": false
}
},
"hidden": true,
"constraints": [
{
"type": "pos",
"x": 0,
"y": "5pt"
},
{
"type": "pos",
"anchor": "e",
"relativeAnchor": "e",
"x": 0
}
]
}
]
}
  • Go to the file t_tabbar.json in the /layout directory.
  • Add a new text layer to the layers array.
  • Add a dataKey field to the text layer and set its value to tabIconActive. This refers to the tabIconActive object in the client_templates.
  • Add a fontColor field to the text layer and set its value to #34A7C9 or a color of your choice for highlighting.
  • Style the rest of text layer tabIconActive the same as the text layer tabIcon by using the following fields:
    • font
    • scaleType
    • fontSize
    • constraints
  • Add a hidden field and set its value to true. This hides the layer by default.
  • Add a states field and set its value to visible {hidden: false}. This shows the layer, if the state is visible.
/layout/t_tabbar.json
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
...
},
{
"type": "text",
"dataKey": "tabIcon",
...
},
{
"type": "text",
"dataKey": "tabText",
...
},
{
"type": "text",
"dataKey": "tabIconActive",
...
},
{
"type": "text",
"dataKey": "tabTextActive",
"fontColor": "#34A7C9",
"scaleType": "alignCenter",
"fontSize": "12pt",
"states": {
"visible": {
"hidden": false
}
},
"hidden": true,
"constraints": [
{
"type": "size",
"height": "14pt"
},
{
"type": "pos",
"x": 0,
"y": "-0pt",
"anchor": "sw",
"relativeAnchor": "sw"
},
{
"type": "pos",
"x": 0,
"anchor": "e",
"relativeAnchor": "e"
}
]
}
]
}
  • Add another new text layer to the layers array.
  • Add a dataKey field to the new text layer and set its value to tabTextActive. This refers to the tabTextActive object in the client_templates.

The same steps are now carried out for the new text layer tabTextActive as previously for tabIconActive.

  • Add a fontColor field to the text layer and set its value to #34A7C9 or a color of your choice for highlighting.
  • Style the rest of the text layer tabTextActive the same as the text layer tabText by using the following fields:
    • scaleType
    • fontSize
    • constraints
  • Add a hidden field and set its value to true. This hides the layer by default.
  • Add a states field and set its value to visible {hidden: false}. This shows the layer, if the state is visible.
Screencature of the tab bar with added highlighting of the active tab.

Highlighting has been added to the tab bar.

Copyable code

/start_config/default.json - default start config
{
"name": "default",
"content": {
"type": "tab",
"staticTemplate": "tabView",
"templateIsNode": true
}
}
/client_template/tabView.json - tabView client template
{
"name": "tabView",
"content": {
"title": "Tab View",
"content": {
"tabs": [
{
"layout": "c_homeTabContent",
"title": "Home",
"staticTemplate": "homeTab",
"templateIsNode": true
},
{
"layout": "c_awayTabContent",
"title": "Away",
"staticTemplate": "awayTab",
"templateIsNode": true
}
]
}
}
}
/layout/c_homeTabContent.json - Home tab layout
{
"name": "c_homeTabContent",
"layers": [
{
"type": "color",
"name": "backgroundColor",
"classes": [
"fullSize",
"background"
]
},
{
"type": "text",
"value": "Home",
"scaleType": "alignCenter",
"classes": [
"fullSize",
"text"
]
}
]
}
/layout/c_awayTabContent.json - Away tab layout
{
"name": "c_awayTabContent",
"layers": [
{
"type": "color",
"name": "backgroundColor",
"classes": [
"fullSize",
"background"
]
},
{
"type": "text",
"value": "Away",
"scaleType": "alignCenter",
"classes": [
"fullSize",
"text"
]
}
]
}
/client_template/homeTab.json - Home tab client template
{
"name": "homeTab",
"content": {
"title": "Home",
"content": {
"tabText": {
"value": "Home"
},
"tabIcon": {
"value": "fa-home"
},
"tabIconActive": {
"value": "fa-home",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 0
},
"mode": "equals"
}
}
]
},
"tabTextActive": {
"value": "Home",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 0
},
"mode": "equals"
}
}
]
}
}
}
}
/client_template/awayTab.json - Away tab client template
{
"name": "awayTab",
"content": {
"content": {
"tabText": {
"value": "Away"
},
"tabIcon": {
"value": "fa-plane"
},
"tabIconActive": {
"value": "fa-plane",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 1
},
"mode": "equals"
}
}
]
},
"tabTextActive": {
"value": "Away",
"conditions": [
{
"state": "visible",
"conditions": {
"left": {
"context": "tabView",
"field": "currentTab"
},
"right": {
"value": 1
},
"mode": "equals"
}
}
]
}
}
}
}
/style/default.json - default style
{
"name": "default",
"content": {
"content": {
"default": {
"tabbarLocation": "Bottom",
"tabbarHeights": {
"default": "56pt"
},
"tabbarLayout": "t_tabbar",
"navbarDisabled": true
}
}
}
}
/layout/t_tabbar.json - tab bar layout
{
"name": "t_tabbar",
"layers": [
{
"type": "color",
"value": "#2B2F2F",
"classes": [
"fullSize"
]
},
{
"type": "text",
"dataKey": "tabIcon",
"font": "FontAwesome",
"fontColor": "#F3F3F3",
"scaleType": "alignCenter",
"fontSize": "30pt",
"constraints": [
{
"type": "pos",
"x": 0,
"y": "5pt"
},
{
"type": "pos",
"anchor": "e",
"relativeAnchor": "e",
"x": 0
}
]
},
{
"type": "text",
"dataKey": "tabText",
"fontColor": "#F3F3F3",
"scaleType": "alignCenter",
"fontSize": "12pt",
"constraints": [
{
"type": "size",
"height": "14pt"
},
{
"type": "pos",
"x": 0,
"y": "-0pt",
"anchor": "sw",
"relativeAnchor": "sw"
},
{
"type": "pos",
"x": 0,
"anchor": "e",
"relativeAnchor": "e"
}
]
},
{
"type": "text",
"dataKey": "tabIconActive",
"font": "FontAwesome",
"fontColor": "#34A7C9",
"scaleType": "alignCenter",
"fontSize": "30pt",
"states": {
"visible": {
"hidden": false
}
},
"hidden": true,
"constraints": [
{
"type": "pos",
"x": 0,
"y": "5pt"
},
{
"type": "pos",
"anchor": "e",
"relativeAnchor": "e",
"x": 0
}
]
},
{
"type": "text",
"dataKey": "tabTextActive",
"fontColor": "#34A7C9",
"scaleType": "alignCenter",
"fontSize": "12pt",
"states": {
"visible": {
"hidden": false
}
},
"hidden": true,
"constraints": [
{
"type": "size",
"height": "14pt"
},
{
"type": "pos",
"x": 0,
"y": "-0pt",
"anchor": "sw",
"relativeAnchor": "sw"
},
{
"type": "pos",
"x": 0,
"anchor": "e",
"relativeAnchor": "e"
}
]
}
]
}
/layer_style/background.json - .background class
{
"name": ".background",
"content": {
"value": "#121212"
}
}
/layer_style/fullSize - .fullSize class
{
"name": ".fullSize",
"content": {
"constraints": [
{
"type": "pos",
"x": "0",
"y": "0"
},
{
"type": "pos",
"x": "0",
"y": "0",
"anchor": "se",
"relativeAnchor": "se"
}
]
}
}
/layer_style/text.json - .text class
{
"name": "text",
"content": {
"fontSize": "15pt",
"contentType": "plain",
"fontColor": "#F3F3F3",
"font": "Raleway-Regular"
}
}