Skip to content

How to create a two-column accordion checkout

Only available for checkout version `^1.1.18

Preview

Preview of Checkout Accordion style step 1 Preview of Checkout Accordion style step 2

Layout Setup

To achieve this, create a new Hyvä Checkout layout named accordion.

You can start by either creating a new module or theme, or using an existing one to store your files.

Next, add a new layout file at view/frontend/layout/hyva_checkout_layout_accordion.xml.

<?xml version="1.0"?>
<page
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
>
    <update handle="hyva_checkout_layout_2columns"/>

    <body>
        <!-- Modify the layout view to an accordion. -->
        <referenceBlock
            name="hyva.checkout.columns"
            template="Example_Module::layout/accordion.phtml"
        />

        <!-- Accordion become the breadcrumbs, waypoints are no longer needed. -->
        <!-- Single downside; sign-in / registration button disappears. -->
        <referenceBlock name="hyva.checkout.breadcrumbs" remove="true"/>
    </body>
</page>

Next, add a new template file at view/frontend/templates/layout/accordion.phtml.

<?php

declare(strict_types=1);

use Hyva\Checkout\Magewire\Main as MagewireComponent;
use Hyva\Checkout\ViewModel\Main as ViewModel;
use Hyva\Theme\ViewModel\HeroiconsOutline;
use Magento\Framework\Escaper;
use Magento\Framework\View\Element\Template;
use Hyva\Theme\Model\ViewModelRegistry;

/** @var Template $block */
/** @var MagewireComponent $magewire */
/** @var ViewModel $viewModel */
/** @var Escaper $escaper */
/** @var ViewModelRegistry $viewModels */

$viewModel = $viewModels->require(ViewModel::class);
$navigatorViewModel = $viewModels->require(\Hyva\Checkout\ViewModel\Navigation::class);
$heroicons = $viewModels->require(HeroiconsOutline::class);

$navigator = $navigatorViewModel->getNavigator();
$currentStep = $navigator->getActiveStep();
$checkout = $navigator->getActiveCheckout();
?>
<div class="flex flex-col gap-6 lg:my-6 lg:flex-row lg:items-start">
    <div class="w-full space-y-6 lg:w-2/3">
        <?php foreach ($checkout->getAvailableSteps() as $step): ?>
            <?php
                $stepId = $checkout->getName() . '-step-' . $step->getName();
                $isActiveStep = $checkout->isComparison($step, $navigator->getActiveStep());
                $isActivePosition = $step->getPosition() === $currentStep->getPosition();
                $canNavigateTo = $checkout->isStepBackwards($step, $currentStep) || $isActiveStep;
            ?>
            <div class="border border-gray-200 text-gray-900 rounded-lg">
                <button
                    type="button"
                    class="item group w-full flex gap-2 justify-between items-center bg-white px-6 py-4 text-xl font-medium rounded-lg aria-expanded:rounded-b-none disabled:text-gray-600 disabled:bg-gray-100 <?= $isActivePosition ? 'active' : 'completed' ?>"
                    <?php if ($isActivePosition): ?>
                        aria-current="step"
                    <?php endif ?>
                    <?php if (! $canNavigateTo): ?>
                        disabled
                    <?php endif ?>
                    aria-expanded="<?= $isActivePosition ? 'true' : 'false' ?>"
                    aria-controls="<?= $escaper->escapeHtmlAttr($stepId) ?>"
                    onclick="hyvaCheckout.navigation.stepTo('<?= $escaper->escapeJs($step->getRoute()) ?>', false)"
                >
                    <span><?= $escaper->escapeHtml($step->getLabel()) ?></span>
                    <?php if ($canNavigateTo): ?>
                        <span class="group-aria-expanded:rotate-180">
                            <?= $heroicons->chevronDownHtml('', 24, 24, ['aria-hidden' => 'true']) ?>
                        </span>
                    <?php endif ?>
                </button>

                <div id="<?= $escaper->escapeHtmlAttr($stepId) ?>" class="column column-main">
                    <?php if ($isActiveStep): ?>
                        <div class="space-y-6 p-6 border-t border-gray-200">
                            <?= $block->getChildHtml('column.main') ?>
                            <?= $block->getChildHtml('hyva.checkout.navigation') ?>
                        </div>
                    <?php endif ?>
                </div>
            </div>
        <?php endforeach ?>
    </div>

    <div class="column column-right w-full space-y-6 lg:w-1/3 lg:sticky lg:top-6">
        <?= $block->getChildHtml('column.right') ?>
    </div>
</div>

At this point, you can use layout="accordion" within your hyva_checkout.xml configuration.

For further details, refer to the hyva_checkout.xml section.

Usage

Since this only affects the layout, it must be manually defined in the hyva_checkout.xml configuration file, either within an existing checkout or a new one. Simply setting the layout attribute to accordion, while keeping the rest of your configuration intact, will transform your checkout into an accordion-style layout.

<?xml version="1.0"?>
<config
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:module:Hyva_Checkout:etc/hyva_checkout.xsd"
>
    <checkout name="accordion"
              label="Hyvä Accordion"
              layout="accordion"
              parent="default"
    />
</config>

Recommendations

Moving elements to their own step

Having too many steps can often be a drawback, but in an accordion-style checkout, it can create a one-page checkout experience by removing visible breadcrumbs. As a result, you might consider adding extra steps and organizing components more logically.

For example, you could move the Guest Details component (where users enter their email address) into a separate "Customer" step that comes before the shipping step. This can be achieved by using a move directive within the hyva_checkout_accordion_customer.xml layout XML handle.

Limitations

Open/close transitions

Each accordion item functions as its own step, similar to how steps are loaded with visible breadcrumbs. However, instead of breadcrumbs, this layout presents the steps as accordion items. Only one step is displayed at a time, so pre-loading steps is not possible. Attempting to enable pre-loading would require additional framework modifications, which we do not recommend.