The layout you see on our site is just two simple template overrides, a custom field in the ATS categories, and some CSS. That is to say, we use the exact same tools we expect you to use to customise the layout of ATS. We do what we preach, and we preach what we do :)
We have a custom field on each ATS category called visual-group
which is a drop-down field. The title of that field is used as the title of the group of categories ("Pre-sales Inquiries", "Actively Supported Software", and "Extended Support for Joomla! 3" at the time of this writing).
Let's see the template overrides.
[template]/html/com_ats/categories/default.php
use Akeeba\Component\ATS\Site\Helper\LayoutHelper;
use Akeeba\Component\ATS\Site\Helper\ModuleRenderHelper;
<div class="ats ats-categories">
<?= ModuleRenderHelper::loadPosition('ats-top') ?>
<?= ModuleRenderHelper::loadPosition('ats-categories-top') ?>
<h3 class="text-center text-primary h2 my-4">
Support and Documentation by Product
</h3>
<?= LayoutHelper::render('akeeba.ats.category.list-alt', [
'categories' => $this->items,
'params' => $this->params,
]); ?>
<?= ModuleRenderHelper::loadPosition('ats-categories-bottom') ?>
<?= ModuleRenderHelper::loadPosition('ats-bottom') ?>
</div>
This template override is there just to print out the "Support and Documentation by Product" header. The header and footer content you see on that page are "Custom HTML" modules.
[template]/html/layouts/akeeba/ats/category/list-alt.php
<?php
/**
* Akeeba Ltd – Official Site Template
*
* @package tpl_akeebabs4
* @copyright Copyright (c)2017-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
defined('_JEXEC') or die;
use Akeeba\Component\ATS\Site\Helper\LayoutHelper;
use Akeeba\Component\ATS\Site\Helper\ModuleRenderHelper;
use Joomla\CMS\Categories\CategoryNode;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\Registry\Registry;
/**
* @var array $displayData
* @var CategoryNode[] $categories
* @var null|Registry $params
*/
$categories = $displayData['categories'];
$params = $displayData['params'] ?? call_user_func(function () {
// Merge the global component and menu parameters
$app = Factory::getApplication();
$menu = $app->getMenu()->getActive();
$menuParams = is_object($menu) ? $menu->getParams() : new Registry();
$mergedParams = clone ComponentHelper::getParams('com_ats');
return $mergedParams->merge($menuParams);
});
$showEmptyMessage = $params->get('cats_show_empty_message', 1);
$distributedCategories = [];
$headings = [];
foreach ($categories as $category) {
$fields = ($category->jcfields ?? []) ?: [];
$vgField = array_reduce(
$fields,
fn($carry, $item) => $carry ?? ($item->name === 'visual-group' ? $item : null),
null
);
$key = $vgField?->rawvalue ?? 'supported';
$title = $vgField?->value ?? 'Actively Supported Software';
$key = is_array($key) ? array_pop($key) : $key;
if (!isset($headings[$key])) {
$headings[$key] ??= $title;
}
$distributedCategories[$key] ??= [];
$distributedCategories[$key][] = $category;
}
?>
<?php if (!count($categories)): ?>
<?= ModuleRenderHelper::loadPosition('ats-categories-none-top') ?>
<?php if ($showEmptyMessage): ?>
<p class="fa fa-info-circle">
<span class="icon-info-circle" aria-hidden="true"></span>
<?= Text::_('COM_ATS_CATEGORIES_MSG_NOCATEGORIES') ?>
</p>
<?php endif; ?>
<?= ModuleRenderHelper::loadPosition('ats-categories-none-bottom') ?>
<?php else: ?>
<?php foreach ($headings as $key => $heading): ?>
<h4 class="border-bottom border-primary pb-1"
id="group-<?= $key ?>"
>
<?= $heading ?>
</h4>
<div class="container-lg p-4">
<div class="row">
<?php foreach ($distributedCategories[$key] as $cat): ?>
<?= LayoutHelper::render('akeeba.ats.category.list_item', [
'category' => $cat,
'params' => $params,
]) ?>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
This template override is, in fact, a Joomla! layout override. This is the "meat and potatoes" of that page. It distributes the categories into visual groups and prints out the group headings and the categories using the default layout. The categories are put into a Bootstrap 5 row container which distributes its contents into columns – it uses CSS Flexbox under the hood.
The rest of the formatting you see is just CSS. The SCSS source for that is:
.category-box {
border-bottom: 1px solid darken($lightGrey, 5%);
&:last-child {
border-bottom: 0;
&:after {
display: none;
}
}
&:after {
content: '';
display: block;
width: 1px;
height: 1px;
border: 7px solid darken($lightGrey, 5%);
border-radius: 50%;
position: absolute;
right: -7px;
bottom: -7px;
}
border-right: 0;
&:after {
display: none;
}
@include media-breakpoint-up(sm) {
border-right: 1px solid darken($lightGrey, 5%);
&:nth-child(2n) {
border-right: 0;
&:after {
display: none;
}
}
}
@include media-breakpoint-up(lg) {
&:nth-child(2n) {
border-right: 1px solid darken($lightGrey, 5%);
}
&:nth-child(3n) {
border-right: 0;
clear: right;
&:after {
display: none;
}
}
&:nth-last-child(2),
&:nth-last-child(3) {
border-bottom: none;
}
}
}
// Hover effect on category links
.category-box {
a.ats-category {
color: $grey;
&:hover {
background: $grey;
color: $white;
text-decoration: none;
img {
opacity: 1;
}
}
}
}
.view-all-link {
a:hover {
background-color: $teal !important;
color: white !important;
}
}
The media breakpoint SCSS functions come from Bootstrap 5. The colour variables are custom to our site's template. Remember, we build it as part of our site's monolithic CSS file which includes Bootstrap 5.
Nicholas K. Dionysopoulos
Lead Developer and Director
🇬🇷Greek: native 🇬🇧English: excellent 🇫🇷French: basic • 🕐 My time zone is Europe / Athens
Please keep in mind my timezone and cultural differences when reading my replies. Thank you!