How to add a new tab to the product page in BigCommerce

If you’re a BigCommerce developer working with a stencil theme, you might find yourself wanting to add a new tab to the product page.

One neat feature of our Metafields Manager app is the ability to manage WYSIWYG content that will get published to a Bigcommerce metafield.

So for this tutorial, we’re going to walk through an example of how to add our size guide metafield into a new tab on the product page. In our setup we have a metafield with key “size-guide” in the namespace “shared”. Where appropriate in the code samples in this blog post, replace these values with references to your own metafield.

Pass metafields to tabs component

The first step is to fetch the required metafield form GraphQL from within the product.html template. To achieve this, add the following GraphQL to your product page template’s front matter.

--- 
gql: "query productById($productId: Int!) {
  site { 
    product(entityId: $productId) { 
      metafields(namespace: \"shared\", keys: [\"size-guide\"]) {
        edges { 
          node { 
            id
            key
            value
          }
        }
      }
    }
  }
}
"
---

For a more detailed guide on fetching and using metafield data in stencil, read our other article on using a metafield with a JSON value on the product page

With the metafields in hand, we can update the reference to the tabs partial within the product page template to pass in the metafields in a parameter

{{> components/products/tabs metafields=gql.data.site.product.metafields }}

Create a new tab

We can now move in to the tab partial in templates/components/products/tabs.html

There are two new sections we need to add to create a new tab: a new list item which is the tab itself, and then a new tab panel that holds the contents to be shown when our tab is active.

Let’s look at creating the new tab itself first.

The easiest way to do this is copying another list item, say the similar by views tab, and then reviewing for parts that need to change:

{{#if product.similar_by_views}}
    <li class="tab{{#unless product.related_products}} is-active{{/unless}}" role="presentation">
        <a class="tab-title" href="#tab-similar" role="tab" tabindex="0" aria-selected="{{#if product.related_products}}false{{else}}true{{/if}}" controls="tab-similar">
            {{lang 'products.similar_by_views'}}
        </a>
    </li>
{{/if}}

We can see that the similar by views tab is automatically open if there are no related products. That sounds like a good idea, let’s do that for our sie guide tab but instead only if there are no related products or similar by views products to show.

To do that, we’re going to need to replace the unless handlebars helper with the neither helper to account for the second condition check. That means we can show the is-active class when appropriate.

We’ll also update the link target and aria control to reference a new ID which we’ll add to our tab panel in a moment.

Lastly we’ll ensure the aria-selected attribute is true only when there are no related products or similar by views products.

<li class="tab {{#neither product.related_products product.similar_by_views}} is-active{{/neither}}" role="presentation">
    <a class="tab-title" href="#tab-size-guide" role="tab" tabindex="0" aria-selected="{{#or product.related_products product.similar_by_views}}false{{else}}true{{/or}}" controls="tab-size-guide">
        Size guide
    </a>
</li>

Adding tab contents

Assuming that you have stencil running, at this point, you should be able to refresh your storefront and see the new tab – albeit with no content yet.

The next step is to add a new tab panel. Again, we’re going to use the similar by views tab panel as a starting point to add our own. Again, we have conditions to update to ensure that the appropriate active/hidden demarcations are in place.

<div role="tabpanel" aria-hidden="{{#or product.related_products product.similar_by_views}}true{{else}}false{{/or}}" class="tab-content{{#neither product.related_products product.similar_by_views}} is-active{{/neither}}" id="tab-size-guide">     
    {{#filter metafields.edges "size-guide" property="node.key"}}
        {{#JSONparse node.value}}
            {{#withFirst this}}
                <h4>{{heading}}</h4>
                <div class="size-guide">
                    {{{details}}}
               </div>
            {{/withFirst}}
        {{/JSONparse }}
    {{/filter}}
</div>

You’ll notice that we’re doing some work here to parse the metafield value as JSON.

If you, once again, go back to your storefront, you’ll now have a working size guide that shows content when active, and is automatically active on page load if there are no other tabs.

Handling the edge cases

There’s one more step that we’re going to cover in this tutorial to tidy up this functionality, and that’s ensuring that we only show our new tab when we have a size guide to show.

We need to conditionally output our new list item and tab panel. One way of achieving this would be to add additional metafield loops outside of these items, but we can do better.

What we can do instead to reduce the amount of loops is to introduce a new variable hasSizeGuide. With this variable set based on the presence of the size guide metafield, we can use it to conditionally output our new sections.

In handlebars, we can use the assignVar and getVar helpers to read/write to a variable.

At the top of your tabs.html, add the following section that will loop through metafields and update the hasSizeGuie variable to 1 if it exists, otherwise the default value of 0 will remain.

{{assignVar "hasSizeGuide" 0}}
{{#filter metafields.edges "size-guide" property="node.key"}}
    {{assignVar "hasSizeGuide" 1}}
{{/filter}}

We can now wrap our tab list item with a new condition:

{{#if (getVar "hasSizeGuide") "===" 1}}
    <li class="tab {{#neither product.related_products product.similar_by_views}} is-active{{/neither}}" role="presentation">
        <a class="tab-title" href="#tab-size-guide" role="tab" tabindex="0" aria-selected="{{#or product.related_products product.similar_by_views}}false{{else}}true{{/or}}" controls="tab-size-guide">
            Size guide
        </a>
   </li>
{{/if}}

And the same goes for the tab panel:

{{#if (getVar "hasSizeGuide") "===" 1}}
    <div role="tabpanel" aria-hidden="{{#or product.related_products product.similar_by_views}}true{{else}}false{{/or}}" class="tab-content{{#neither product.related_products product.similar_by_views}} is-active{{/neither}}" id="tab-size-guide">   
        {{#filter metafields.edges "size-guide" property="node.key"}}
            {{#JSONparse node.value}}
                {{#withFirst this}}
                    <h4>{{heading}}</h4>
                    <div class="size-guide">
                        {{{details}}}
                   </div>
                {{/withFirst}}
            {{/JSONparse }}
        {{/filter}}
    </div>
{{/if}}

And with that, we’re done!

We have successfully created a new size guide tab on the product page using a metafield in our stencil theme!

Tom Robertshaw
Stay up to date with Hypa news and features