Skip to content

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:

  1. Maximum Customizability: Different requirements can be met through targeted configurations without modifying the core code.
  2. Modularity: Components like footer, header, or widgets are treated as independent modules, increasing their reusability.
  3. Upgrade Compatibility: Since we adhere to Shopware 6 guidelines and make specific adjustments in separate files, future system updates remain smoothly applicable.
  4. 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:

  1. Clarity and Structure: All adjustments are managed in one central location.
  2. Maintainability: Changes can be made easily by adjusting the theme.json without touching the template code.
  3. Extensibility: New configuration options can be easily added, making the system future-proof.
  4. Upgrade Compatibility: Adjustments are based on Shopware conventions, which minimizes conflicts in future updates.

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:

twig
{% 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:

twig
{# 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:

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:

twig
{% 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 header
  • compact: Guppy standard - Compact header variant
  • extended: Extended header variant with top bar
  • simple: Minimalist header variant

The navigation supports different flyout variants:

twig
{% 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 navigation
  • content-compact: Compact navigation with optimized display

Product Card System

The product card system offers different display variants:

twig
{% 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 card
  • guppy-default: Guppy standard - Accessible product card

Accessibility Features

The theme offers configurable skip links for better accessibility:

twig
{# 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 content
  • guppy-header-skip-to-main-nav: Jump to main navigation
  • guppy-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:

twig
{% set navigationData = categoryOneLevel(navigationTree, currentCategoryId) %}

{% for category in navigationData %}
    <a href="{{ category.url }}" class="nav-link">
        {{ category.name }}
    </a>
{% endfor %}

Implementation:

php
// 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

twig
{# 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

twig
{# 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

twig
{# 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>