Hyvä compatible module and how to deal with it
A few words about Hyvä
Hyvä is not just another Magento 2 theme; it represents a comprehensive toolset, an extension ecosystem, and a supportive community, as described by its developers (Hyvä.io). It’s easy to concur with this statement. While most Magento themes use Blank or Luma (the default M2 theme) as a parent theme, Hyvä is meticulously crafted from the ground up. This means that all frontend components, including styles, graphics, and JavaScript, are built using an entirely new stack of tools and frameworks. Furthermore, the layout structure has been thoughtfully reworked.
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?
Why is it essential to develop modules that are Hyvä-compatible? The reason is quite straightforward: Hyvä ushers in a wholly distinct frontend environment compared to Luma/Blank themes. Consequently, all JavaScript, styles, and many elements that are typically rendered via backend plugins in templates won’t function as expected on Hyvä. This necessitates the creation of a new frontend experience for our modules to seamlessly integrate with Hyvä.
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:
- javascript
- Copy code
- composer require Hyvä-themes/magento2-compat-module-fallback
You can find comprehensive information on this in the Hyvä Docs.
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. */ ?>
When dealing with components that need to be embedded within the template and cannot be called as in Luma using require, you might encounter situations where your template file becomes too large, making it difficult to read and maintain. In such cases, it can be helpful to split the HTML and JavaScript into two separate templates and use the Magento template method fetchView, like this:
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. */ ?>
The process is straightforward. To monitor changes in one component and trigger an action in another, you can utilize JavaScript native eventListeners. For instance, if you perform certain actions in one component and wish to execute a method in another component, you can achieve this by dispatching an event in one component and waiting for it to fire in the other component. You would dispatch an event with a name like “amfilter-option-select” and pass the required data to it for further processing.
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: