Templating
Contents of this page:
Guppy follows a component-based approach to ensure clean separation of logic and presentation. Our goal is to create a system that is both maintainable and future-proof. To achieve this, we rely on dynamic and modular mechanisms, which also come into play in template design. This allows us to make individual adjustments without affecting the core functions of Shopware 6. Through this methodology, Guppy remains fully updateable and reduces long-term maintenance effort.
Why this approach?
Shopware 6 is a powerful framework whose updateability and flexibility are best preserved through our approach. The dynamic handling of configurations enables:
- Maximum Customizability: Different requirements can be met through targeted configurations without modifying the core code.
- Modularity: Components like footer, header, or widgets are treated as independent modules, increasing their reusability.
- Upgrade Compatibility: Since we adhere to Shopware 6 guidelines and make specific adjustments in separate files, future system updates remain smoothly applicable.
- Accessibility: Through modular templates, accessibility adjustments can be integrated specifically and flexibly without adapting global code.
Theme Integration
Guppy uses the theme configuration (theme.json) as a central control instance for dynamic component adjustments. The configuration makes it possible to make specific design decisions directly via theme settings without having to delve deeply into the code.
Advantages
Using theme.json allows important settings like footer type to be defined flexibly. This brings the following advantages:
- Clarity and Structure: All adjustments are managed in one central location.
- Maintainability: Changes can be made easily by adjusting the
theme.jsonwithout touching the template code. - Extensibility: New configuration options can be easily added, making the system future-proof.
- Upgrade Compatibility: Adjustments are based on Shopware conventions, which minimizes conflicts in future updates.
How it works (using the footer example)
The footer code considers the settings in the theme.json by using the theme_config() function. This reads the values defined in the theme.json.
Example code:
{% if theme_config('guppy-footer') != "default" %}
{% set configFooter = theme_config('guppy-footer') %}
{% endif %}INFO
Explanation The function theme_config('guppy-footer') checks whether a specific footer configuration (guppy-footer) has been defined in the theme.json.
Addition in footer template:
{# src/Resources/views/storefront/base.html.twig #}
{% block base_footer %}
<footer class="footer-main{% if configFooter %} footer-main-{{ configFooter }} pt-md-3 pt-4{% endif %}">
{% block base_footer_inner %}
{% if configFooter %}
{% sw_include '@Storefront/storefront/layout/footer/footer-' ~ configFooter ~ '.html.twig' %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
</footer>
{% endblock %}Example configuration in theme.json:
// src/Resources/theme.json
{
...
"config": {
...
"fields": {
...
"guppy-footer": {
"label": {
"en-GB": "Footer variant",
"de-DE": "Footer Variante"
},
"type": "text",
"value": "guppy-default",
"custom": {
"componentName": "sw-single-select",
"options": [
{
"value": "default",
"label": {
"en-GB": "Shopware Default",
"de-DE": "Shopware Standard"
}
},
{
"value": "guppy-default",
"label": {
"en-GB": "Guppy Default",
"de-DE": "Guppy Standard"
}
}
]
},
"editable": true,
"tab": "footer",
"block": "layoutFooter",
"order": 100
}
}
}
}Template Variant System
The Guppy Theme implements a comprehensive variant system for various components:
Header Variants
The header can be displayed in different variants:
{% if theme_config('guppy-header') != "default" %}
{% set configHeader = theme_config('guppy-header') %}
{% endif %}
{% block base_header %}
<header class="header-main{% if configHeader %} header-variant-{{ configHeader }}{% endif %}">
{% block base_header_inner %}
{% if configHeader %}
{% sw_include '@Storefront/storefront/layout/header/header-' ~ configHeader ~ '.html.twig' %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
</header>
{% endblock %}Available Header Variants:
default: Shopware standard headercompact: Guppy standard - Compact header variantextended: Extended header variant with top barsimple: Minimalist header variant
Navigation Variants
The navigation supports different flyout variants:
{% if theme_config('guppy-navigation') != "content" %}
{% set navigationStyle = theme_config('guppy-navigation') %}
{% endif %}
{% block base_navigation %}
<nav class="nav-main{% if navigationStyle %} nav-{{ navigationStyle }}{% endif %}">
{% sw_include '@Storefront/storefront/layout/navbar/' ~ (navigationStyle ?: 'content') ~ '.html.twig' %}
</nav>
{% endblock %}Available Navigation Variants:
content: Shopware standard navigationcontent-compact: Compact navigation with optimized display
Product Card System
The product card system offers different display variants:
{% if theme_config('guppy-productcard-config') %}
{% set boxDesign = theme_config('guppy-productcard-config') %}
{% endif %}
<article class="card product-box box-{{ layout }}{% if boxDesign %} box-{{ boxDesign }}{% endif %}">
<!-- Product card content -->
</article>Available Product Card Variants:
default: Shopware standard product cardguppy-default: Guppy standard - Accessible product card
Accessibility Features
Skip Links
The theme offers configurable skip links for better accessibility:
{# base.html.twig #}
{% block base_body_inner %}
{% if theme_config('guppy-header-skip-to-main-content') %}
<a href="#content-main" class="skip-link">
{{ 'skipLink.toMainContent'|trans|sw_sanitize }}
</a>
{% endif %}
{% if theme_config('guppy-header-skip-to-main-nav') %}
<a href="#main-navigation" class="skip-link">
{{ 'skipLink.toMainNavigation'|trans|sw_sanitize }}
</a>
{% endif %}
{% if theme_config('guppy-header-skip-to-search') %}
<a href="#search" class="skip-link">
{{ 'skipLink.toSearch'|trans|sw_sanitize }}
</a>
{% endif %}
{{ parent() }}
{% endblock %}Available Skip Links:
guppy-header-skip-to-main-content: Jump to main contentguppy-header-skip-to-main-nav: Jump to main navigationguppy-header-skip-to-search: Jump to search
Custom Twig Extensions
The Guppy Theme extends Twig with additional functions:
CategoryOneLevelExtension
The categoryOneLevel() function enables display of single-level category navigations:
{% set navigationData = categoryOneLevel(navigationTree, currentCategoryId) %}
{% for category in navigationData %}
<a href="{{ category.url }}" class="nav-link">
{{ category.name }}
</a>
{% endfor %}Implementation:
// src/Twig/CategoryOneLevelExtension.php
class CategoryOneLevelExtension extends AbstractExtension
{
public function getFunctions(): array
{
return [
new TwigFunction('categoryOneLevel', [$this, 'categoryOneLevel'])
];
}
public function categoryOneLevel($navigationTree, $currentCategoryId)
{
// Implementation of single-level category navigation
}
}Best Practices
Template Inheritance
{# Always inherit from the corresponding Shopware template #}
{% sw_extends '@Storefront/storefront/layout/header/header.html.twig' %}
{# Override specific blocks #}
{% block layout_header_logo %}
<div class="header-logo-custom">
{{ parent() }}
</div>
{% endblock %}Use Theme Configuration
{# Always use theme configuration for variants #}
{% if theme_config('guppy-component-variant') %}
{% set variant = theme_config('guppy-component-variant') %}
{% endif %}
{# Fallback for default behavior #}
{% if variant %}
{# Custom logic #}
{% else %}
{{ parent() }}
{% endif %}Consider Accessibility
{# Always use semantic HTML elements #}
<nav role="navigation" aria-label="{{ 'navigation.main'|trans }}">
{# Navigation content #}
</nav>
{# Skip links for important areas #}
<a href="#main-content" class="skip-link">
{{ 'skipLink.toMainContent'|trans }}
</a>