Skip to main content

ProductTabs

A tabbed content organizer for product detail pages. Combines four sub-components — Description, Specifications, Downloads, and Videos — into a unified interface with horizontal tabs on desktop and an accordion on mobile.


Usage

Basic usage with all tabs

<ProductTabs
product={product}
graphqlClient={graphqlClient}
productId={product.productId}
/>

Only description and specifications

<ProductTabs
product={product}
graphqlClient={graphqlClient}
productId={product.productId}
showDownloads={false}
showVideos={false}
/>

Collapsed description with custom labels

<ProductTabs
product={product}
graphqlClient={graphqlClient}
productId={product.productId}
descriptionCollapsed={true}
descriptionMaxLength={300}
labels={{
description: 'Overview',
specifications: 'Tech Specs',
downloads: 'Documents',
videos: 'Media',
}}
/>

Grouped specifications in list layout

<ProductTabs
product={product}
graphqlClient={graphqlClient}
productId={product.productId}
specificationsLayout="list"
specificationsGrouping={true}
language="EN"
/>

Custom labels for sub-components

<ProductTabs
product={product}
graphqlClient={graphqlClient}
productId={product.productId}
downloadsLabels={{ title: 'Product Documents', download: 'Get file' }}
videosLabels={{ title: 'Product Videos' }}
/>

Configuration

Core

PropTypeDefaultDescription
productProductrequiredThe product object containing descriptions, attributes, media documents, and media videos.
languagestring'NL'Language code passed to all sub-components for localized content resolution.
labelsRecord<string, string>{}Override the tab button labels. Keys: description, specifications, downloads, videos.
classNamestring''Extra CSS class applied to the root element.

Tab Visibility

All default to true. Set to false to hide a tab entirely.

PropTypeDescription
showDescriptionbooleanShow or hide the Description tab. Automatically hidden if the product has no description for the active language.
showSpecificationsbooleanShow or hide the Specifications tab.
showDownloadsbooleanShow or hide the Downloads tab.
showVideosbooleanShow or hide the Videos tab.

Description Options

PropTypeDefaultDescription
descriptionCollapsedbooleanfalseWhen true, truncates the description to descriptionMaxLength characters with a "Read more" / "Read less" toggle.
descriptionMaxLengthnumber0Maximum characters shown when collapsed. 0 means no truncation.

Specifications Options

PropTypeDefaultDescription
graphqlClientGraphQLClientundefinedInitialized Propeller SDK GraphQL client, passed to ProductSpecifications for attribute fetching.
productIdnumberundefinedProduct ID for fetching attributes via the SDK.
specificationsLayoutstring'table'Display layout: 'table' (two-column name/value) or 'list' (vertical stacked rows).
specificationsGroupingbooleanfalseWhen true, groups specifications by their group field with a heading per section.

Downloads & Videos Labels

PropTypeDefaultDescription
downloadsLabelsRecord<string, string>{}Override UI strings for the Downloads section. Keys: title, download.
videosLabelsRecord<string, string>{}Override UI strings for the Videos section. Key: title.

Behavior

Tab Switching

  • Desktop (md and above): Horizontal tab bar with an underline indicator on the active tab. Clicking a tab replaces the visible content panel below.
  • Mobile (below md): Accordion layout with chevron icons. Tapping a section header toggles it open or closed. Only one section is open at a time — opening a new section closes the previous one. Tapping the currently open section closes it (all collapsed state).

Initial Tab Selection

On mount, the component selects the first visible tab in this priority order:

  1. Description (if enabled and the product has description content)
  2. Specifications
  3. Downloads
  4. Videos

If the product or language changes after mount, the component re-evaluates and resets to the Description tab when applicable.

Lazy Loading of Specifications

The Specifications sub-component is not rendered until the user visits the Specifications tab at least once. On desktop, after the first visit it stays mounted (hidden via CSS hidden class) to preserve fetched data. On mobile (accordion), the specs section is only rendered when both visited AND currently active — it unmounts when collapsed. The attribute fetch via ProductService.getAttributeResultByProductId() fires when the tab is first visited and graphqlClient + productId are provided.

Description Auto-Hide

The Description tab is automatically excluded from the tab bar when the product has no description content for the current language (and no fallback description exists). The next available tab becomes the default.


SDK Services & Product Fields

ProductTabs reads the following fields from the Product object (from propeller-sdk-v2):

FieldUsed ByPurpose
product.descriptionsDescription tabArray of { language, value } objects. The component matches by language prop (default 'NL'), falling back to the first entry. If no description exists, the Description tab is automatically hidden.
product.attributes.itemsSpecifications tabArray of AttributeResult objects passed directly to ProductSpecifications.
product.media.documentsDownloads tabPaginatedMediaDocumentResponse containing downloadable files associated with the product.
product.media.videosVideos tabPaginatedMediaVideoResponse containing video entries associated with the product.

The Specifications tab can also fetch attributes independently via graphqlClient and productId, which is useful when product.attributes is not populated in the initial product query. When fetching independently, the component calls ProductService.getAttributeResultByProductId() with { attributeDescription: { isPublic: true }, page: 1, offset: 2000 }. This fetch is triggered only when the Specifications tab is first visited (lazy-loaded).