5 minutes reading time (969 words)

Accordion Override for Articles Module

Articles Module: Accordion Override

If you have followed my writings in the Magazine, you already know that I really like overrides. Overrides have helped me understand how Joomla works and they give me the possibility to change almost everything without breaking Joomla core. 

Overrides need maintenance like extensions do, but to a small extent, normally are only a few files you need to check after a Joomla update. Of course it is nice to use extensions with ready-to-use options and styles instead of writing your own code, but if you don’t try you don’t learn.

I’m always looking for inspiration for new overrides, new ways to display content on a website. Some weeks ago I stumbled upon a fancy accordion design created by Bramus Van Damme, a web developer from Belgium who is part of the Chrome Developer Relations team at Google, focusing on CSS, Web UI, and DevTools. The accordion is based on the <details> and <summary> elements and that is great, because these elements don’t need any kind of JavaScript and are accessible by default.
I immediately had the idea to create an override for the Articles Module based on this accordion. And that is what we will build:

Articles displayed as a vertical accordion. The first element is open

We need

Screenshot of the text feld for the icon

  • Some articles in each category, each with an intro image and a short intro text.
  • An Article Module with these settings:

Screenshot of the settings for the module. Mode: norma. Articles to display: 9. Category filtering type: inclusive. Category: Travel. Child category articles: include. Category Depth: 1

Override

I converted the HTML code from Bramus’ demo into PHP. The file accordion.php has to be copied into html\mod_articles inside your template structure.

accordion.php

<?php

/**
 * @package     Joomla.Site
 * @subpackage  mod_articles
 *
 * @copyright   (C) 2024 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
use Joomla\CMS\Router\Route;

/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();

if (!$list) {
    return;
}

$items = $list;

// Get the category object
$categories = Factory::getApplication()->bootComponent('com_content')->getCategory();

?>

<div class="accordion-wrapper">
    <?php foreach ($items as $item) : ?>
        <?php
            // Get the category id and the fields
            $category   = $categories->get($item->catid);
            $jcfields = FieldsHelper::getFields('com_content.categories', $category, true);

            // Create an associative array for easier access by field name
            foreach($jcfields as $jcfield) {
                $jcfields[$jcfield->name] = $jcfield;
            }

            // Get the intro image of the article
            $images  = json_decode($item->images);
            $layoutAttr = [
                'src' => $images->image_intro,
                'alt' => empty($images->image_intro_alt) ? '' : $images->image_intro_alt,
            ];
        ?>
        <details name="accordion" open >
            <summary aria-label="<?php echo $item->displayCategoryTitle; ?>">
            <span class="<?php echo $jcfields['icon-cat']->value; ?>" aria-hidden="true"></span>
            <?php echo LayoutHelper::render('joomla.html.image', $layoutAttr); ?>
            </summary>
            <div class="details-content-wrapper">
                <?php $item_heading = $params->get('item_heading', 'h4'); ?>
                <<?php echo $item_heading; ?>>
                    <?php echo $item->title; ?>
                </<?php echo $item_heading; ?>>
                <?php echo $item->displayIntrotext; ?>
                <a class="btn btn-accordion" href="/<?php echo $item->link; ?>" aria-label="<?php echo Text::sprintf('JGLOBAL_READ_MORE_TITLE', $item->title); ?>">
                <?php echo '<span class="icon-chevron-right" aria-hidden="true"></span>'; ?>
               </a>
            </div>
        </details>
    <?php endforeach; ?>
</div>

We use the category icon in the <summary> element, that is the visible part of the accordion, where one can click to open the details.

The intro image also needs to be inside the <summary>, because otherwise it would be hidden when the <details> element is not open. With CSS we will position the image to look like a background image. We will also use the title and the intro text from each article:

Screenshot of the accordion with marked parts: Category icon, article title, article intro text

CSS

I added some lines into the CSS from the demo and copied it in the user.css (using Cassiopeia):

.accordion-wrapper {
    display: flex;
    flex-direction: row;
    gap: 1rem;
    width: min-content;
    margin: 0 auto;
}

details {
    display: flex;
    flex-direction: row;
    background: transparent;
    color: white;
    height: 30rem;
    border-radius: 2rem;
    overflow: hidden;
    /* To make the image work …*/
    position: relative;
    z-index: 1;
    /* Hide marker */
    ::marker {
        content: '';
    }
    /* The image is tucked in the summary, because otherwise it would be hidden when not [open] as it ends up in the ::details-content pseudo */
    summary img {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: -1;
        transition: filter 0.5s ease;
    }
    /* Animate the image */
    &[open] summary img {
        filter: brightness(.3);
    }

    summary {
        padding: 1rem 1em;
        width: 6rem;
        flex-shrink: 0; /* Prevent shrinking */
        text-align: center;

        span {
            display: grid;
            place-content: center;
            width: 100%;
            aspect-ratio: 1;
            border-radius: 50%;
            background: rgb(0, 0, 0, .25);
        }

        &:focus {
            outline: none;
        }
    }

    .details-content-wrapper {
        padding: 1.5rem 1em;
        width: 330px;
    }

    &:hover, &:has(summary:focus-visible) {
        outline: 3px solid var(--cassiopeia-color-primary);
        outline-offset: 3px;
    }
    span::before {
        font-size: 1.5rem;
    }
}

.details-content-wrapper {
    display: flex;
    flex-direction: column;
    /* We need margin-trim … */
    :first-child {
        margin-top: 0;
    }
    :last-child {
        margin-bottom: 0;
    }

    /* Animate-in the text when open */
    p, a {
        transform: translateY(2rem);
        opacity: 0;
        transition: opacity 0.5s ease;
        transition-delay: 0.5s;
    }

    [open] & p,
    [open] & a {
        transform: none;
        opacity: 1;
        transition-delay: 0.5s;
    }

    .btn-accordion {
        background: rgb(0, 0, 0, .25);
        aspect-ratio: 1;
        border-radius: 50%;
        color: currentColor;
        margin-inline-start: auto;
        &:hover, &:focus-visible {
            outline: 3px solid currentColor;
            outline-offset: 2px;
        }
    }
}

The special thing in this override is that it uses “display: flex;” for the <details> element. Sadly it will only work as expected on the last version of Chrome. In other browsers the intro text will display next to the category icon and not side-by-side. Hopefully in the near future other browsers will also implement “display: flex;” (and other display options) for <details>.

Chrome

Articles displayed as a vertical accordion. The first element is open

Firefox

Articles displayed as a vertical accordion. The first element is open. In Firefox the intro text is next to the category icon

Conclusion

There are lots of examples out there waiting to be converted into Joomla overrides. If you find something inspiring, but you are not able to create an override by yourself, please don’t hesitate to contact me. Maybe you can help me with my next Magazine article 😉

Some articles published on the Joomla Community Magazine represent the personal opinion or experience of the Author on the specific topic and might not be aligned to the official position of the Joomla Project

3
The December Issue
 

Comments 5

Already Registered? Login Here
Berend Bouma on Monday, 23 December 2024 16:03
Accordion Override for Articles Module

I have successfully followed your presentation but I can't get the intro text and the icons on the screen. What do i wrong? Example site can be found on demo.joomlaheerenveen.nl/motoren

0
I have successfully followed your presentation but I can't get the intro text and the icons on the screen. What do i wrong? Example site can be found on [url=https://demo.joomlaheerenveen.nl/motoren]demo.joomlaheerenveen.nl/motoren[/url]
Viviana Menzel on Thursday, 02 January 2025 18:21
Missing icons

Hi Berend, I can see the intro text in your demo...
The icon class for the span-element is missing, are you sure you have created a custom field for the categories?

0
Hi Berend, I can see the intro text in your demo... The icon class for the span-element is missing, are you sure you have created a custom field for the categories?
Berend Bouma on Friday, 03 January 2025 06:54
Missing icons

Hi Viviana,
Yes i made an field for the Categories

0
Hi Viviana, Yes i made an field for the Categories
Viviana Menzel on Wednesday, 08 January 2025 15:45
Missing icons

And are you sure you are using the correct name of the field in the code? In my example the field is called "icon-cat":
echo $jcfields['icon-cat']->value;

0
And are you sure you are using the correct name of the field in the code? In my example the field is called "icon-cat": echo $jcfields['icon-cat']->value;
Berend Bouma on Thursday, 09 January 2025 10:27
Icons

I found out that I had forgotten to enter something in the tab General -->Name to enter the code

Thank you for the explanation

0
I found out that I had forgotten to enter something in the tab General -->Name to enter the code Thank you for the explanation

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/