Hyvä simplifies Magento 2 frontend development by removing RequireJS, KnockoutJS, and LESS, replacing them with Alpine.js and Tailwind CSS. This guide covers how to build and integrate custom components efficiently using Hyvä’s modern stack, making Magento 2 Hyvä customization easier and more efficient.

Understanding Hyvä's Component Architecture

Hyvä components are built using:

  • .phtml templates – HTML structure & dynamic data.
  • Tailwind CSS – Utility-first styling.
  • Alpine.js – Lightweight JavaScript interactions.

Unlike Magento’s traditional KnockoutJS-based components, Hyvä components are:

  • Faster (no RequireJS overhead).
  • Simpler (modular, maintainable).
  • More flexible (easy to customize).

Step 1: Creating a Custom Hyvä Component

Define a New Component (.phtml Template)

Let’s create a custom product badge component to display labels like "New", "Sale", or "Bestseller" for Magento Hyvä components.

File:
app/design/frontend/Vendor/Theme/Hyva_Custom/templates/product-badge.phtml

<?php
/** @var \Magento\Catalog\Model\Product $product */
$product = $block->getProduct();
$badgeType = $block->getBadgeType();
?>
<?php if ($badgeType): ?>
<span class="badge <?= $badgeType ?> px-3 py-1 text-sm font-semibold text-white rounded">
<?= /* @noEscape */ $block->getBadgeHtml() ?: ucfirst($badgeType) ?>
</span>
<?php endif; ?>

Add Styles with Tailwind CSS

File: app/design/frontend/Vendor/Theme/web/css/custom.css

@layer components {
.badge {
@apply absolute top-2 left-2 bg-red-500;
}
.badge.sale { @apply bg-green-500; }
.badge.new { @apply bg-blue-500; }
.badge.bestseller { @apply bg-yellow-500; }
}

Integrate Component into Product Listing

File:
app/design/frontend/Vendor/Theme/Magento_Catalog/templates/product/list.phtml
Modify the loop that renders products:

<?php foreach ($block->getLoadedProductCollection() as $product): ?>
<div class="relative p-4 border rounded-lg">
<?= $this->getLayout()
->createBlock(\Magento\Framework\View\Element\Template::class)
->setTemplate('Hyva_Custom::product-badge.phtml')
->setProduct($product)
->setBadgeType('sale')
->toHtml();
?>
<h2 class="text-lg font-bold"><?= $product->getName(); ?></h2>
<p class="text-gray-700"><?= $block->getProductPrice($product); ?></p>
</div>
<?php endforeach; ?>

How it Works:

  • Calls our product-badge.phtml template.
  • Passes the product object and badge type dynamically.
  • Uses Tailwind CSS for styling.

Step 2: Adding Alpine.js for Interactivity

Let’s enhance the product badge component by adding an Alpine.js toggle effect to show/hide the badge, improving Magento 2 Hyvä customization.

Modify product-badge.phtml to Include Alpine.js

<span
x-data="{ show: true, htmlContent: '<?= ucfirst($badgeType) ?> <b>✖</b>' }"
x-show="show"
class="badge <?= $badgeType ?> px-3 py-1 text-sm font-semibold text-white rounded cursor-pointer"
@click="show = false"
>

What this does:

  • Uses x-data="{ show: true }" to initialize the state.
  • x-show="show" hides the badge when show is false.
  • @click="show = false" lets users remove the badge on click.

Step 3: Adding a Custom ViewModel for Dynamic Data

Magento ViewModels allow passing custom logic to templates without modifying core code, which is essential for Magento 2 custom development.

Create ViewModel Class

File: app/code/Vendor/Module/ViewModel/ProductBadge.php

<?php
namespace Vendor\Module\ViewModel;
use Magento\Catalog\Model\Product;
use Magento\Framework\View\Element\Block\ArgumentInterface;
class ProductBadge implements ArgumentInterface{
    public function getBadge(Product $product): string
    {
        if ($product->getSpecialPrice()) {
            return 'sale';
        }
        if ($product->getNewArrival()) {
            return 'new';
        }
        return 'bestseller';
    }
}

Register ViewModel in di.xml

File: app/code/Vendor/Module/etc/frontend/di.xml

<type name="Magento\Framework\View\Element\Template">
    <arguments>
        <argument name="viewModel" xsi:type="object">Vendor\Module\ViewModel\ProductBadge</argument>
    </arguments>
</type>

Use ViewModel in product-badge.phtml


<?php
$viewModel = $block->getViewModel();
$badgeType = $viewModel->getBadge($product);
?>
<span class="badge <?= $badgeType ?>"><?= ucfirst($badgeType) ?></span>

Now, the badge type is automatically determined based on product attributes!

Step 4: Deploy and Test

Once the component is built, test it in Magento 2 Hyvä theme development:

php bin/magento cache:flush

php bin/magento setup:static-content:deploy -f

Check if badges appear correctly and Alpine.js interactions work. This method ensures optimized Magento 2 Hyvä customization for better performance and flexibility.

By following this guide, you can leverage Hyvä theme development for Magento 2 custom development, making frontend components more modern, efficient, and easy to maintain.