Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Understanding Existing Alpine Components in Hyvä: Mobile Menu and Mini Cart as Learning Examples

Understanding Existing Alpine Components in Hyvä: Mobile Menu and Mini Cart as Learning Examples

~8 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

The fastest way to learn a new pattern is often to read an existing, working example. Two components that show up in practically every Hyvä theme and combine all the fundamentals from chapter 14: the mobile menu and the mini cart.

The mobile menu as a learning example

A typical mobile menu consists of a toggle button and a panel that gets shown and hidden - exactly the pattern from chapter 14, just with a few extra details for accessibility and body scroll locking:

<div x-data="{ mobileMenuOpen: false }">
    <button
        type="button"
        @click="mobileMenuOpen = !mobileMenuOpen"
        :aria-expanded="mobileMenuOpen"
        aria-label="Open menu"
        class="lg:hidden"
    >
        <span x-show="!mobileMenuOpen">☰</span>
        <span x-show="mobileMenuOpen">✕</span>
    </button>

    <nav
        x-show="mobileMenuOpen"
        x-cloak
        @click.outside="mobileMenuOpen = false"
        class="fixed inset-0 z-40 bg-white p-6"
    >
        <!-- menu items -->
    </nav>
</div>

New details compared to chapter 14: :aria-expanded (shorthand for x-bind:aria-expanded) dynamically binds an HTML attribute to an Alpine value - important for screen readers. @click.outside closes the menu as soon as a click happens anywhere outside it. x-cloak prevents a brief flash of the unstyled element before Alpine has loaded (via the CSS rule [x-cloak] { display: none; }, already included in Hyvä's base CSS).

The mini cart as a learning example

The mini cart demonstrates another important pattern: state that doesn't originate purely client-side, but comes from a server-side data source. The initial cart contents are already supplied as a PHP array (via a ViewModel) when the page loads, and embedded as JSON inside x-data:

Simplified principle of the mini cart pattern
<?php
/** @var \Magento\Framework\Escaper $escaper */
/** @var \Magento\Framework\Serialize\Serializer\Json $json */
?>
<div x-data="{ items: <?= /* @noEscape */ $json->serialize($cartViewModel->getCartData()) ?> }">
    <span x-text="items.length"></span>
</div>

This pattern - embedding server-rendered initial data as JSON inside x-data, then working with it client-side from there - is the standard way to feed Alpine with "real" Magento data, without needing an extra AJAX request on the initial page load.

Achtung: JSON embedded in an x-data attribute must be produced by a real JSON serializer (e.g. \Magento\Framework\Serialize\Serializer\Json), not by manual string concatenation - otherwise you risk broken JSON or XSS holes via unescaped quotation marks.

What we take from this for the team page

For our own team page starting in chapter 17, we'll use a very similar pattern: team member data comes from the ViewModel, gets embedded as JSON in an x-data attribute, and category filtering then happens entirely client-side in Alpine - with no page reload and no extra server request.