Visual Subcategories¶
Availability: Category page context
The visual_subcategories module displays a set of subcategories for a given category. It supports grid and slider (carousel) display modes, configurable headings, and responsiveness. Subcategories can be filtered to hide empty ones, and the module supports custom colors and show-more functionality for mobile in the grid view.
Configuration parameters¶
shouldDisplayUnderline¶
int If set to 1, the header will have an underline.
shouldDisplayHeading¶
int If set to 1, the heading will be rendered.
levelHeader¶
int Section level of a header describing the size and importance of the element in a given context. You can read more about heading elements here. We provide the following levels for the header module:
- 2 for the h2 heading
- 3 for the h3 heading
- 4 for the h4 heading
- 5 for the h5 heading
- 6 for the h6 heading
textHeader¶
string The text for the heading.
shouldHideEmptySubcategories¶
int If set to 1, only subcategories with products are displayed.
numberOfSubcategoriesToShow¶
int Maximum number of subcategories to display.
desktopProductsCountPerRow¶
int Number of subcategories per row on desktop resolution.
laptopProductsCountPerRow¶
int Number of subcategories per row on laptop resolution.
tabletProductsCountPerRow¶
int Number of subcategories per row on tablet resolution.
phoneProductsCountPerRow¶
int Number of subcategories per row on mobile resolution.
displayMode¶
string Determines how the list of subcategories will be displayed. carousel for a slider, grid for a grid list.
backgroundColor¶
string Custom background color for tiles.
textColor¶
string Custom text color for tiles.
Module source code¶
{% from "@macros/image.twig" import image %}
{% from "@macros/slider.twig" import slider %}
{% from "@macros/list_grid.twig" import list_grid %}
{% from "@macros/category_tile.twig" import category_tile %}
{% set hasUnderline = moduleConfig.shouldDisplayUnderline == 1 %}
{% set isHeadingRenderable = moduleConfig.shouldDisplayHeading == 1 and moduleConfig.levelHeader and moduleConfig.textHeader %}
{% set levelHeader = moduleConfig.levelHeader|default(2) %}
{% set moreSubcategoriesMobileCount = 6 %}
{% if category_id %}
{% set activeCategory = ObjectApi.getCategory(category_id) %}
{% if moduleConfig.shouldHideEmptySubcategories == 1 %}
{% set subcategoriesToDisplay = activeCategory.subcategories|filter(subcategory => subcategory.productsInSubTree|length > 0) %}
{% else %}
{% set subcategoriesToDisplay = activeCategory.subcategories %}
{% endif %}
{% endif %}
{% set shouldDisplayModule = subcategoriesToDisplay|find(subcategory => subcategory.thumbnailImageUrl|length > 0) %}
{% set numOfSubcategories = subcategoriesToDisplay|length > moduleConfig.numberOfSubcategoriesToShow ? moduleConfig.numberOfSubcategoriesToShow : subcategoriesToDisplay|length %}
{% set perPageDesktop = numOfSubcategories < moduleConfig.desktopProductsCountPerRow ? numOfSubcategories : moduleConfig.desktopProductsCountPerRow %}
{% set perPageLaptop = numOfSubcategories < moduleConfig.laptopProductsCountPerRow ? numOfSubcategories : moduleConfig.laptopProductsCountPerRow %}
{% set perPageTablet = numOfSubcategories < moduleConfig.tabletProductsCountPerRow ? numOfSubcategories : moduleConfig.tabletProductsCountPerRow %}
{% set perPageMobile = numOfSubcategories < moduleConfig.phoneProductsCountPerRow ? numOfSubcategories : moduleConfig.phoneProductsCountPerRow %}
{%
set visualSubcategoriesSliderSettings = {
"perPage": perPageDesktop,
"arrows": true,
"arrowsPosition": "below",
"hasArrowsOnMobile": true,
"breakpoints": {
1440: {
"perPage": perPageLaptop,
"arrows": true,
"arrowsPosition": "below"
},
1000: {
"perPage": perPageTablet,
"arrows": true,
"arrowsPosition": "below"
},
576: {
"perPage": perPageMobile
}
},
"i18n": {
"prev": translate("Previous subcategory"),
"next": translate("Next subcategory"),
"first": translate("Next subcategory"),
"last": translate("Previous subcategory")
}
}
%}
{%
set gridSettings = {
phoneItemsCountPerRow: perPageMobile,
smallTabletItemsCountPerRow: perPageTablet,
tabletItemsCountPerRow: perPageTablet,
laptopItemsCountPerRow: perPageLaptop,
desktopItemsCountPerRow: perPageDesktop,
}
%}
{% if shouldDisplayModule %}
{% set subcategoriesTemplate %}
{% set subcategoryLevelHeader = levelHeader|number_format + 1 %}
{% for subcategory in subcategoriesToDisplay %}
{% if loop.index <= numOfSubcategories %}
{% if moduleConfig.displayMode == "carousel" %}
<li class="splide__slide">
{% endif %}
{{ category_tile(
subcategory,
moduleConfig|merge({
levelHeader: subcategoryLevelHeader,
hasParentHeading: isHeadingRenderable
}))
}}
{% if moduleConfig.displayMode == "carousel" %}
</li>
{% endif %}
{% endif %}
{% endfor %}
{% endset %}
<nav
class="visual-subcategories"
aria-label="{{ translate("Visual subcategories") }}"
style="
{% if moduleConfig.backgroundColor %}--visualSubcategoriesTileBgColor: {{ moduleConfig.backgroundColor }};{% endif %}
{% if moduleConfig.textColor %}--visualSubcategoriesTileTextColor: {{ moduleConfig.textColor }};{% endif %}
"
>
<h{{ levelHeader }}
class="
visual-subcategories__header
header
header_h{{ levelHeader }}
{% if hasUnderline %} header_underline {% endif %}
{% if not isHeadingRenderable %}sr-only{% endif %}
"
>
<span {% if hasUnderline %} class="header_highlight" {% endif %}>
{{ moduleConfig.textHeader }}
</span>
</h{{ levelHeader }}>
{% if moduleConfig.displayMode == "carousel" %}
{{
slider(subcategoriesTemplate, {
id: "visual-subcategories-#{moduleInstance}",
sliderConfig: visualSubcategoriesSliderSettings,
visibleItems: numOfSubcategories,
arrowConfigProps: {
position: "right"
}
})
}}
{% else %}
<h-show-more count="{{ moreSubcategoriesMobileCount }}" mobile-only>
{{
list_grid(subcategoriesTemplate, {
grid: gridSettings,
className: "visual-subcategories__tile-grid"
})
}}
<h-show-more-button class="link link_secondary d-block mt-xs-3">
{{ translate("Show more subcategories (%s)", subcategoriesToDisplay|length - moreSubcategoriesMobileCount) }}
</h-show-more-button>
<h-show-more>
{% endif %}
</nav>
{% endif %}
Macros reference¶
Webcomponents reference¶
Used styles¶
Module configuration schema¶
[
{
"label": "General settings",
"state": "unfolded",
"elements": [
{
"type": "infobox",
"name": "infobox",
"options": {
"type": "blank",
"message": "#### Related settings in the admin panel%s- adding images to [categories and subcategories](%s), adding and changing subcategory display order",
"placeholderValues": [
"\n",
"\/admin\/categories"
]
}
},
{
"type": "infobox",
"name": "warning",
"options": {
"type": "warning",
"message": "The module will be shown if at least one subcategory has a photo."
}
},
{
"name": "shouldDisplayHeading",
"type": "checkbox",
"label": "Display heading",
"supportsTranslations": true,
"defaultValue": 0,
"children": [
{
"name": "textHeader",
"type": "text",
"relations": [
{
"parentName": "shouldDisplayHeading",
"parentValueToActionsMap": [
{
"value": 0,
"actions": [
"setHiddenAndOptional",
"setDisabled"
]
},
{
"value": 1,
"actions": [
"setVisibleAndRequired",
"setAvailable"
]
}
]
}
],
"label": "Module heading content",
"supportsTranslations": true
},
{
"name": "levelHeader",
"type": "select",
"hint": "The numbers 2 to 6 indicate the hierarchy of headings, with H2 being the most important and H6 being the least. H1 is reserved for the page title. If you need to add a page title, use the \"Page title\" module.",
"relations": [
{
"parentName": "shouldDisplayHeading",
"parentValueToActionsMap": [
{
"value": 0,
"actions": [
"setHidden",
"setDisabled"
]
},
{
"value": 1,
"actions": [
"setVisible",
"setAvailable"
]
}
]
}
],
"options": {
"isWithSearch": 0,
"selectOptions": [
{
"key": "2",
"label": "H2"
},
{
"key": "3",
"label": "H3"
},
{
"key": "4",
"label": "H4"
},
{
"key": "5",
"label": "H5"
},
{
"key": "6",
"label": "H6"
}
]
},
"label": "Heading level",
"defaultValue": "2"
},
{
"name": "shouldDisplayUnderline",
"type": "checkbox",
"relations": [
{
"parentName": "shouldDisplayHeading",
"parentValueToActionsMap": [
{
"value": 0,
"actions": [
"setHidden",
"setDisabled"
]
},
{
"value": 1,
"actions": [
"setVisible",
"setAvailable"
]
}
]
}
],
"label": "Add underline below the heading",
"defaultValue": 1
}
]
},
{
"name" : "displayMode",
"type" : "radio",
"label" : "Subcategory display mode",
"defaultValue" : "carousel",
"options": {
"radioOptions" : [
{ "key" : "carousel", "label" : "Carousel (scrollable subcategories)" },
{ "key" : "gallery", "label" : "Gallery (all subcategories visible)" }
]
}
},
{
"name" : "namePosition",
"type" : "select",
"label" : "Subcategory name position",
"defaultValue" : "under",
"options": {
"selectOptions" : [
{ "key" : "under", "label" : "Below image" },
{ "key" : "above", "label" : "Above image" }
]
}
},
{
"name" : "nameAlignment",
"type" : "select",
"label" : "Subcategory name alignment",
"defaultValue" : "center",
"options": {
"selectOptions" : [
{ "key" : "left", "label" : "Left <<to_left>>" },
{ "key" : "center", "label" : "Center" },
{ "key" : "right", "label" : "Right <<to_right>>" }
]
}
},
{
"type": "checkbox",
"name": "shouldDisplayNumberOfProducts",
"label": "Display product count",
"defaultValue": 0
},
{
"type": "checkbox",
"name": "shouldHideEmptySubcategories",
"label": "Hide empty subcategories",
"defaultValue": 1
},
{
"type": "checkbox",
"name": "shouldShortenLongNames",
"label": "Shorten long subcategory names",
"defaultValue": 1
},
{
"type": "number",
"name": "numberOfSubcategoriesToShow",
"label": "Number of subcategories in module",
"isRequired": 1,
"defaultValue": 12,
"hint": "By default, the first 12 subcategories will be displayed according to the order set in Category settings. If there are more subcategories, the list will be limited to the selected number.",
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 1 } },
{ "type": "lessEqThan", "options": { "max": 16 } }
]
},
{
"type": "header",
"name": "headerMobile",
"label": "Mobile",
"options": {
"icon": "phone"
},
"children": [
{
"type": "number",
"name": "phoneProductsCountPerRow",
"label": "Number of subcategories per row",
"labelDescription": "Max. 3.",
"defaultValue": 2,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 1 } },
{ "type": "lessEqThan", "options": { "max": 3 } }
]
}
]
},
{
"type": "header",
"name": "headerTablet",
"label": "Tablet",
"options": {
"icon": "tablet"
},
"children": [
{
"type": "number",
"name": "tabletProductsCountPerRow",
"label": "Number of subcategories per row",
"labelDescription": "Max. 6.",
"defaultValue": 4,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 1 } },
{ "type": "lessEqThan", "options": { "max": 6 } }
]
}
]
},
{
"type": "header",
"name": "headerLaptop",
"label": "Laptop",
"options": {
"icon": "laptop"
},
"children": [
{
"type": "number",
"name": "laptopProductsCountPerRow",
"label": "Number of subcategories per row",
"labelDescription": "Max. 8.",
"defaultValue": 6,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 1 } },
{ "type": "lessEqThan", "options": { "max": 8 } }
]
}
]
},
{
"type": "header",
"name": "headerDesktop",
"label": "Desktop",
"options": {
"icon": "desktop"
},
"children": [
{
"type": "number",
"name": "desktopProductsCountPerRow",
"label": "Number of subcategories per row",
"labelDescription": "Max. 10.",
"defaultValue": 6,
"validators": [
{ "type": "int" },
{ "type": "greaterEqThan", "options": { "min": 1 } },
{ "type": "lessEqThan", "options": { "max": 10 } }
]
}
]
}
]
},
{
"state": "unfolded",
"label": "Module appearance",
"elements": [
{
"name": "textColor",
"type": "colorPicker",
"label": "Text color in module",
"defaultValue": "@globalFontColor",
"options": {
"allowVariables": true
}
},
{
"name": "backgroundColor",
"type": "colorPicker",
"label": "Background color behind photo",
"labelDescription": "For photos with transparency",
"defaultValue": "@globalBodyBackgroundColor",
"options": {
"allowVariables": true
}
}
]
},
{
"state": "unfolded",
"label": "CSS",
"elements": [
{
"type": "text",
"name": "classNames",
"label": "CSS class",
"labelDescription": "Enter the class name without a dot at the beginning. You can add multiple classes by separating them with spaces."
}
]
}
]