Hyvä compatible module and how to deal with it
A few words about Hyvä
Let’s briefly examine how Hyvä is organized, with more detailed information available here. Here’s a concise overview of Hyvä’s frontend in five key points.
1. Layouts: Hyvä maintains the core structure of typical Magento layouts, which includes essential containers like header, footer, main.content, main, sidebar, and sidebar.additional. However, it innovatively restructures the organization of containers and blocks. While this has introduced some improvements, there are still questions to address. For instance, certain new templates lack extensibility from the layout, leaving room for further enhancements – a topic we may explore at another time.
2. Styles: Hyvä leverages Tailwind CSS for styling. Initially, you might find the concept of styling with classes in Magento a bit unusual.
However, it’s all good; you just need a little time to get acquainted with it if you haven’t worked with it before. You can find detailed guidance on working with Tailwind in the Hyvä documentation and, of course, on the official Tailwind website. If you’re used to working with less/sass for styles and find yourself missing them, Hyvä has you covered with PostCSS. It’s already configured in the Hyvä-theme. You just need to navigate to the vendor/Hyvä-themes/magento2-default-theme/web/tailwind folder and run npm install. Inside vendor/Hyvä-themes/magento2-default-theme/web/tailwind/package.json, you’ll find all the commands for building styles, including ‘watch,’ which is handy during development, and ‘build-prod,’ which is essential before deploying static content for production.
3. JS: Handling components in Hyvä is the responsibility of Alpine.js. It’s a breeze to work with and impressively lightweight; that’s the best way I can describe it in just two words.
4. Templates: Hyvä goes the extra mile by reworking nearly all the templates, aligning them with Hyvä’s frontend architecture.
5. The Hyvä theme introduces a collection of invaluable viewModels, conveniently located under the Hyvä_Theme module. These viewModels simplify tasks such as fetching configurations, data, managing icons, and creating icon packages, among other useful functions.
In summary, Hyvä isn’t just another Magento 2 frontend theme. It represents a departure from the familiar landscape of requireJS, knockoutJS, and less. Instead, it embraces a new stack of frameworks and tools. Whether this departure is cool or not is a subjective judgment that each developer should make for themselves.
Why create Hyvä compatible modules for Magento 2?
To facilitate this integration, Hyvä’s theme includes an additional module that establishes a fallback system for our modules. This approach mirrors the organization of Magento 2’s fallback system. Essentially, this module empowers Hyvä Themes compatibility modules to override templates without the need for layout XML. It’s an elegant solution that streamlines the process.
To install it via Composer, simply run the following command:
- Copy code
- composer require Hyvä-themes/magento2-compat-module-fallback
Now that we’ve established the necessity of adapting our frontend modules for Hyvä, and with Hyvä_CompatModuleFallback already at our disposal, let’s delve into the structure of compatibility modules.
Base structure of Hyvä compatible module
Let’s dive into the foundational structure of a Hyvä-compatible module, outlining the essential components to kickstart the process.
To begin, we must create a skeleton for our compatibility module. Here’s a rundown of what’s required to get started:
1. Registration.php File: This file is quite standard, akin to any Magento module’s registration file. It plays a pivotal role in initializing our compatibility module within the Hyvä environment.
2. module.xml – Typical module.xml file but with sequence for original module, and sequence for Hyvä_CompatModuleFallback.
3. frontend/di.xml – Here we tell for which module we want to create a compatibility one, as a result it gives us a fallback system for our compatibility module for overriding templates.
4. Tailwind configuration file – here we add the files that should be involved in styles compilation flow. Also here we can extend/add additional variables for tailwind. All the info here for any version of Tailwind, Hyvä could be on Tailwind v2 and v3.
Note: In case you need to add classes via xml, add:
‘../layout/**/*.phtml’ to content array.
Approaches, suggestions, decisions, workarounds for compatibility modules
Let’s begin by emphasizing that the following content is not a comprehensive guide or a step-by-step instruction. Instead, it offers insights and perspectives gained from the experience of creating over 20 compatibility modules.
Now, let’s delve deeper into the process of creating a compatibility module.
<?= /* Styles */ ?>
We already know that Hyvä uses Tailwind CSS Framework and how to set up styles flow under modules. So let’s check out how we solve casual styling tasks for our modules.
Under module view/frontend/tailwind folder – create necessary file tailwind.config.js.
This one tells what we want to involve into CSS flow – in our case only ‘../templates/**/*.phtml’ (also it is possible to add ‘../layout/**/*.phtml’)
Also, here we can extend tailwind with our custom variables. In our example colors and z-index are extended, all the details easily can be found in Tailwind docs.
Any variables can be extended here.For adding custom styles not in templates directly just create view/frontend/tailwind/tailwind-source.css
It is possible to add styles directly here; however, we prefer to organize styles into separate files within the components folder, as shown on the screen. This approach allows us to logically structure the styles and maintain a cleaner codebase.
In style files, it makes sense to include styles for elements that are either reusable or difficult to access on the frontend. In other cases, we add Tailwind classes directly to the templates. If we need to create a new class, we can conveniently use Tailwind’s @layer directive. You can find more information about this in the documentation, which explains how to create new classes that can be used within templates as Tailwind classes.
<?= /* Alpine components */ ?>
As Hyvä doesn’t have requireJS as in Luma, we create Alpine components directly in template after or before html structure on which it initialized. Example:
For initialize component just need to create function
accountTabs_<?= $escaper->escapeHtml($uniqueId); ?>() like in example which returns an object with component variables / methods, all variables are dynamical, all methods reachable within the component. For initialization component on any DOM element just need to add directive x-data=”accountTabs_<?= $escaper->escapeHtml($uniqueId); ?>()”
$uniqueId – need to use if more than one similar component could be on one route (page), EX: some widgets from module, sliders etc.
Hyvä versions 1.1.* and 1.2.* have different versions of AlpineJS and TaliwindCSS,
and if you need to maintain both Hyvä versions variations you will have a bit pain:)
Hyvä 1.1.* – Alpine ver. 2, Tailwind ver. 2;
Hyvä 1.2.* – Alpine ver. 3, Tailwind ver. 3;
With Tailwind all quite easy – for maintaining both Hyväs just use docs for Tailwind v2, Tailwind v.3 supports all entries of 2d version.
In case of Alpine it is a bit complicated, as they have differences that are not supported by each other. The Hyvä doc has answers on general issues you can find here.
Aws, like $el, return the current element in Alpine 3, while in Alpine 2, it returns the component’s top element (with x-data). This change might require a bit of patience and adjustment, but overall, it’s a positive step forward.
<?= /* Structuring components. */ ?>
Just pass template path to it $block->getTemplateFile(‘path to template’) and it will make your code a bit cleaner 😉
Also if you need to pass some data from parent template to template witch is pulled by fetchView, it is possible just to use
$block->assign([‘uniqueId’ => $uniqueId]) before fetch view, it give a chance to pass any data for pulled template (Hyvä uses this one in many templates to keep all readable and easy to use) ex:
<?= /* Communication between components. */ ?>
In another component just waiting for firing this Event and do some other magic.
Probably that’s all about passing data from one component to another.
<?= /* ViewModels in Hyvä. */ ?>
Hyvä provides a variety of useful view models that can be found under the directory “vendor/Hyvä-themes/magento2-theme-module/src/ViewModel.” One such example is “Hyvä\Theme\ViewModel\StoreConfig,” which makes it simple to retrieve configuration data directly from templates. This allows you to easily access and utilize configuration settings within your templates.
In Hyvä, you can easily access and utilize view models in your templates. These view models, such as “Hyvä\Theme\ViewModel\StoreConfig,” can be called directly within any template to retrieve the configuration data you need.
Unlike traditional approaches that involve passing view models through the layout, Hyvä utilizes “Hyvä\Theme\Model\ViewModelRegistry” to connect view models to templates. This method simplifies the process of accessing view models, allowing you to retrieve and use them conveniently within your templates. This approach is consistent across all created view models within your compatible module and can be accessed in the same manner, as demonstrated in the provided screenshot.
Layouts in Hyvä
In terms of layout, Hyvä follows the same structure and instructions as the Luma theme. However, there’s a key distinction: if you intend to make layout adjustments specific to the Hyvä module, you’ll find that all layout handles for Hyvä have a prefix of “hyva_” in addition to the standard layout handles. This prefix enables you to target and customize layout elements specifically for the Hyvä module without affecting other parts of your theme.
The layout structure in Hyvä maintains familiar main containers like “after.body.start,” “before.body.end,” “page.top,” “main.content,” “sidebar.main,” and others found in standard Magento themes. However, the internal structure of these containers and blocks has been reworked in Hyvä theme layouts. This means that while the overarching structure remains consistent, you might need to invest some time in understanding where to make modifications or how to adjust certain containers or blocks. It presents new challenges and opportunities for you to explore and master.
<?= /* GraphQL in Hyvä. */ ?>
When developing modules with GraphQL support, our primary approach is to utilize mutations for both retrieving and storing data instead of relying on Ajax calls to Controllers. This strategy offers several advantages, including data consistency even when the main module code undergoes changes in new releases. We can still access and save data correctly via GraphQL, which aligns with the module’s current support.
However, it’s important to note that creating full functionality exclusively through GraphQL, especially when the module has its own separate route, can introduce challenges. For example, if you’re implementing a popup feature with products displayed through GraphQL, you may need to create new listings (like Product Detail Pages and catalogs) using Alpine.js, complete with ratings, swatches, and other elements. This approach can potentially introduce additional complexities and issues.
In essence, we prefer to use GraphQL primarily for data retrieval and storage (mutations), but the choice ultimately lies in your hands, and you have the flexibility to decide the best approach for your specific module requirements.
<?= /* Icons */ ?>
The theme provides a ViewModel and a collection of SVG icons, making it convenient to work with these resources. This simplifies tasks related to data management and icon usage within the theme.
Just need to connect a ViewModel like shown above, and use it any place of template like:
You can pass classes, width, and height as arguments for these icons. The theme offers a collection of heroic icons, which can be located at the following path: vendor/Hyvä-themes/magento2-theme-module/src/ViewModel/Heroicons.php. Additionally, a cheat sheet is available for your reference.
If you wish to create your own icon pack under your module, you can follow these steps:
1. Create a virtual type Hyvä\Theme\ViewModel\SvgIcons under the etc/frontend/di directory of your module.
2. Place icons under /view/frontend/web/svg
3. Call the view model in your template.
4. Call icon in template via view model, passing name of icon and classes for modify.
That is all about icons, easy and clear.
In summary, Hyvä represents more than just a new theme for Magento 2; it introduces a novel frontend approach with a distinct stack of frameworks and tools for the storefront.
Digging into styles flow – on one hand styles flow quite simpler than less flow in Luma and cleaner but on the other hand here you don’t have mixins and using variables isn’t so flexible than in less Luma’s flow.
Speaking about the JS part – AlpineJS components work faster and more modern that knockoutJS, also less of loading resources, as Hyva doesn’t have requireJS, but communication between different components possible only via EventListeners, and sure thing if you was working with Luma, familiarizing with AlpineJS will take some time.
Templates were also dramatically reworked, in some cases they became useful for customizing and maintaining, but some problems appeared also, for example some of templates didn’t have possibility to pass some blocks from layout, and for solving this kind of issues you need to override templates under your module/theme.
Is it faster out of the box compared to Luma? Absolutely. Is it easy to work with on the frontend? In my opinion, yes, but forming a definitive conclusion requires gaining some experience with it, so I encourage you to give it a try.
Additional technical materials
Here’s a list of valuable resources for working with Hyvä, many of which were mentioned earlier: