Add Main Menu collapsible dropdown override with Bootstrap 5 responsive navbar
Co-authored-by: jmiller-moko <230051081+jmiller-moko@users.noreply.github.com>
This commit is contained in:
48
CHANGELOG.md
48
CHANGELOG.md
@@ -8,17 +8,61 @@
|
|||||||
DEFGROUP: Joomla.Template.Site
|
DEFGROUP: Joomla.Template.Site
|
||||||
INGROUP: MokoCassiopeia.Documentation
|
INGROUP: MokoCassiopeia.Documentation
|
||||||
PATH: ./CHANGELOG.md
|
PATH: ./CHANGELOG.md
|
||||||
VERSION: 03.08.01
|
VERSION: 03.08.03
|
||||||
BRIEF: Changelog file documenting version history of MokoCassiopeia
|
BRIEF: Changelog file documenting version history of MokoCassiopeia
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Changelog — MokoCassiopeia (VERSION: 03.08.01)
|
# Changelog — MokoCassiopeia (VERSION: 03.08.03)
|
||||||
|
|
||||||
All notable changes to the MokoCassiopeia Joomla template are documented in this file.
|
All notable changes to the MokoCassiopeia Joomla template are documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [03.08.03] - 2026-02-27
|
||||||
|
|
||||||
|
### Added - Main Menu Collapsible Dropdown Override
|
||||||
|
|
||||||
|
**New feature**: Added responsive "Main Menu" mod_menu override with Bootstrap 5 collapsible dropdown functionality.
|
||||||
|
|
||||||
|
#### What's New
|
||||||
|
- **Main Menu module override** with full Bootstrap 5 responsive navbar
|
||||||
|
- Collapsible hamburger menu for mobile devices
|
||||||
|
- Multi-level dropdown support with hover on desktop, tap on mobile
|
||||||
|
- WCAG 2.1 compliant touch targets (48px on mobile, 44px on desktop)
|
||||||
|
- BEM naming convention: `.mod-menu-main__*`
|
||||||
|
|
||||||
|
#### Files Added
|
||||||
|
- `src/templates/html/mod_menu/default.php` - Main layout with Bootstrap navbar
|
||||||
|
- `src/templates/html/mod_menu/default_component.php` - Component menu items
|
||||||
|
- `src/templates/html/mod_menu/default_heading.php` - Heading menu items
|
||||||
|
- `src/templates/html/mod_menu/default_separator.php` - Separator menu items
|
||||||
|
- `src/templates/html/mod_menu/default_url.php` - URL menu items
|
||||||
|
- `src/templates/html/mod_menu/index.html` - Security file
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
- **Bootstrap 5 Navbar**: Uses Bootstrap's native navbar-nav structure
|
||||||
|
- **Collapsible on Mobile**: Hamburger menu with smooth collapse animation
|
||||||
|
- **Dropdown Menus**: Multi-level dropdown support with caret indicators
|
||||||
|
- **Responsive Breakpoints**: Mobile-first design adapting at 768px and 992px
|
||||||
|
- **Touch-Friendly**: 48px minimum touch targets on mobile
|
||||||
|
- **Accessible**: ARIA labels and keyboard navigation support
|
||||||
|
- **Active States**: Visual indicators for current and active menu items
|
||||||
|
|
||||||
|
#### CSS Architecture
|
||||||
|
- 200+ lines of responsive CSS in template.css
|
||||||
|
- BEM naming: `.mod-menu-main`, `.mod-menu-main__list`, `.mod-menu-main__link`
|
||||||
|
- CSS variables integration for colors and borders
|
||||||
|
- Hover effects on desktop, tap effects on mobile
|
||||||
|
- Smooth transitions and animations
|
||||||
|
|
||||||
|
#### Module Count Update
|
||||||
|
- **Before**: 16 module overrides
|
||||||
|
- **After**: 17 module overrides (added mod_menu "Main Menu")
|
||||||
|
- **Component overrides**: Still 7 (unchanged)
|
||||||
|
|
||||||
|
**Note**: Unlike the previously removed mod_menu override (v03.08.01), this new "Main Menu" override is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected.
|
||||||
|
|
||||||
## [03.08.02] - 2026-02-27
|
## [03.08.02] - 2026-02-27
|
||||||
|
|
||||||
### Removed - Fix Language Loading in All Module Overrides
|
### Removed - Fix Language Loading in All Module Overrides
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
INGROUP: MokoCassiopeia.Documentation
|
INGROUP: MokoCassiopeia.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
FILE: docs/MODULE_OVERRIDES.md
|
FILE: docs/MODULE_OVERRIDES.md
|
||||||
VERSION: 03.08.02
|
VERSION: 03.08.03
|
||||||
BRIEF: Comprehensive guide to MokoCassiopeia mobile-responsive module overrides
|
BRIEF: Comprehensive guide to MokoCassiopeia mobile-responsive module overrides
|
||||||
PATH: /docs/MODULE_OVERRIDES.md
|
PATH: /docs/MODULE_OVERRIDES.md
|
||||||
-->
|
-->
|
||||||
@@ -35,9 +35,9 @@ This document provides a comprehensive guide to all mobile-responsive module and
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MokoCassiopeia includes **16 mobile-responsive module overrides** and **7 component view overrides** designed to enhance the mobile user experience for third-party extensions (VirtueMart, Community Builder, Kunena, etc.).
|
MokoCassiopeia includes **17 mobile-responsive module overrides** and **7 component view overrides** designed to enhance the mobile user experience for third-party extensions and the Main Menu navigation.
|
||||||
|
|
||||||
**Important**: Following Cassiopeia template best practices, MokoCassiopeia does NOT override standard Joomla core modules (mod_breadcrumbs, mod_login, mod_articles_latest, etc.). These use Joomla's default layouts to ensure proper language loading and compatibility.
|
**Important**: Following Cassiopeia template best practices, MokoCassiopeia generally avoids overriding standard Joomla core modules to ensure proper language loading and compatibility. **Exception**: mod_menu "Main Menu" override provides essential Bootstrap 5 collapsible dropdown functionality.
|
||||||
|
|
||||||
### Key Features
|
### Key Features
|
||||||
|
|
||||||
|
|||||||
@@ -19362,6 +19362,177 @@ nav[data-toggle=toc] .nav-link.active+ul{
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Main Menu - Collapsible Dropdown Bootstrap Responsive === */
|
||||||
|
.mod-menu-main {
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main .navbar-toggler {
|
||||||
|
border-color: var(--border-color);
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
min-height: 48px; /* WCAG 2.1 touch target */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main .navbar-toggler:focus {
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(var(--link-color-rgb), 0.25);
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main .navbar-toggler-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||||
|
display: inline-block;
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__link,
|
||||||
|
.mod-menu-main__heading {
|
||||||
|
display: block;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
color: var(--link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: background-color 0.2s ease, color 0.2s ease;
|
||||||
|
min-height: 48px; /* WCAG 2.1 touch target on mobile */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__link:hover,
|
||||||
|
.mod-menu-main__link:focus {
|
||||||
|
background-color: var(--secondary-bg);
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__item.active > .mod-menu-main__link,
|
||||||
|
.mod-menu-main__item.current > .mod-menu-main__link {
|
||||||
|
background-color: var(--primary-bg);
|
||||||
|
color: var(--white);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown menu styles */
|
||||||
|
.mod-menu-main__dropdown {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__item.dropdown.show > .mod-menu-main__dropdown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__dropdown .mod-menu-main__item {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__dropdown .mod-menu-main__link {
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
min-height: 44px; /* Slightly smaller for nested items */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__dropdown .mod-menu-main__link:hover,
|
||||||
|
.mod-menu-main__dropdown .mod-menu-main__link:focus {
|
||||||
|
background-color: var(--secondary-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__separator {
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown toggle arrow */
|
||||||
|
.mod-menu-main__link.dropdown-toggle::after,
|
||||||
|
.mod-menu-main__heading.dropdown-toggle::after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: auto;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
border-top: 0.3em solid;
|
||||||
|
border-right: 0.3em solid transparent;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-left: 0.3em solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Desktop styles (≥768px) */
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.mod-menu-main__list {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__link,
|
||||||
|
.mod-menu-main__heading {
|
||||||
|
min-height: 44px; /* WCAG 2.1 touch target on desktop */
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__item.dropdown {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
min-width: 200px;
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover dropdown on desktop */
|
||||||
|
.mod-menu-main__item.dropdown:hover > .mod-menu-main__dropdown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nested dropdowns */
|
||||||
|
.mod-menu-main__dropdown .mod-menu-main__dropdown {
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-left: 0.125rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Large desktop styles (≥992px) */
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.mod-menu-main {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-main__list {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* === mod_breadcrumbs === */
|
/* === mod_breadcrumbs === */
|
||||||
.mod-breadcrumbs-responsive {
|
.mod-breadcrumbs-responsive {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
104
src/templates/html/mod_menu/default.php
Normal file
104
src/templates/html/mod_menu/default.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package Joomla.Site
|
||||||
|
* @subpackage mod_menu
|
||||||
|
*
|
||||||
|
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||||
|
*
|
||||||
|
* Main Menu - Mobile responsive collapsible dropdown menu override
|
||||||
|
* Bootstrap 5 responsive navbar with hamburger menu
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
use Joomla\CMS\Helper\ModuleHelper;
|
||||||
|
|
||||||
|
$id = '';
|
||||||
|
|
||||||
|
if ($tagId = $params->get('tag_id', '')) {
|
||||||
|
$id = ' id="' . $tagId . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get module class suffix
|
||||||
|
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||||
|
|
||||||
|
// The menu class is deprecated. Use mod-menu instead
|
||||||
|
?>
|
||||||
|
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<!-- Hamburger toggle button for mobile -->
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenuCollapse" aria-controls="mainMenuCollapse" aria-expanded="false" aria-label="Toggle Main Menu">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Collapsible menu content -->
|
||||||
|
<div class="collapse navbar-collapse" id="mainMenuCollapse">
|
||||||
|
<ul class="navbar-nav mod-menu-main__list">
|
||||||
|
<?php foreach ($list as $i => &$item) :
|
||||||
|
$itemParams = $item->getParams();
|
||||||
|
$class = 'nav-item mod-menu-main__item item-' . $item->id;
|
||||||
|
|
||||||
|
if ($item->id == $default_id) {
|
||||||
|
$class .= ' default';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->id == $active_id || ($item->type === 'alias' && $itemParams->get('aliasoptions') == $active_id)) {
|
||||||
|
$class .= ' current';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($item->id, $path)) {
|
||||||
|
$class .= ' active';
|
||||||
|
} elseif ($item->type === 'alias') {
|
||||||
|
$aliasToId = $itemParams->get('aliasoptions');
|
||||||
|
|
||||||
|
if (count($path) > 0 && $aliasToId == $path[count($path) - 1]) {
|
||||||
|
$class .= ' active';
|
||||||
|
} elseif (in_array($aliasToId, $path)) {
|
||||||
|
$class .= ' alias-parent-active';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->type === 'separator') {
|
||||||
|
$class .= ' divider';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->deeper) {
|
||||||
|
$class .= ' deeper dropdown';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->parent) {
|
||||||
|
$class .= ' parent';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<li class="' . $class . '">';
|
||||||
|
|
||||||
|
switch ($item->type) :
|
||||||
|
case 'separator':
|
||||||
|
case 'component':
|
||||||
|
case 'heading':
|
||||||
|
case 'url':
|
||||||
|
require ModuleHelper::getLayoutPath('mod_menu', 'default_' . $item->type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
require ModuleHelper::getLayoutPath('mod_menu', 'default_url');
|
||||||
|
break;
|
||||||
|
endswitch;
|
||||||
|
|
||||||
|
// The next item is deeper.
|
||||||
|
if ($item->deeper) {
|
||||||
|
echo '<ul class="dropdown-menu mod-menu-main__dropdown">';
|
||||||
|
} elseif ($item->shallower) {
|
||||||
|
// The next item is shallower.
|
||||||
|
echo '</li>';
|
||||||
|
echo str_repeat('</ul></li>', $item->level_diff);
|
||||||
|
} else {
|
||||||
|
// The next item is on the same level.
|
||||||
|
echo '</li>';
|
||||||
|
}
|
||||||
|
endforeach;
|
||||||
|
?></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
64
src/templates/html/mod_menu/default_component.php
Normal file
64
src/templates/html/mod_menu/default_component.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package Joomla.Site
|
||||||
|
* @subpackage mod_menu
|
||||||
|
*
|
||||||
|
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||||
|
*
|
||||||
|
* Main Menu - Component item layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
use Joomla\CMS\Filter\OutputFilter;
|
||||||
|
use Joomla\CMS\HTML\HTMLHelper;
|
||||||
|
|
||||||
|
$attributes = [];
|
||||||
|
|
||||||
|
if ($item->anchor_title) {
|
||||||
|
$attributes['title'] = $item->anchor_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->anchor_css) {
|
||||||
|
$attributes['class'] = $item->anchor_css;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->anchor_rel) {
|
||||||
|
$attributes['rel'] = $item->anchor_rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
$linktype = $item->title;
|
||||||
|
|
||||||
|
if ($item->menu_icon) {
|
||||||
|
// The link is an icon
|
||||||
|
if ($itemParams->get('menu_text', 1)) {
|
||||||
|
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||||
|
} else {
|
||||||
|
// If the icon itself is the link, it needs a visually hidden text
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->browserNav == 1) {
|
||||||
|
$attributes['target'] = '_blank';
|
||||||
|
$attributes['rel'] = 'noopener noreferrer';
|
||||||
|
} elseif ($item->browserNav == 2) {
|
||||||
|
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||||
|
|
||||||
|
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add dropdown toggle for items with children
|
||||||
|
$linkClass = 'nav-link mod-menu-main__link';
|
||||||
|
if ($item->deeper) {
|
||||||
|
$linkClass .= ' dropdown-toggle';
|
||||||
|
$attributes['data-bs-toggle'] = 'dropdown';
|
||||||
|
$attributes['role'] = 'button';
|
||||||
|
$attributes['aria-expanded'] = 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes['class'] = $linkClass;
|
||||||
|
|
||||||
|
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||||
37
src/templates/html/mod_menu/default_heading.php
Normal file
37
src/templates/html/mod_menu/default_heading.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package Joomla.Site
|
||||||
|
* @subpackage mod_menu
|
||||||
|
*
|
||||||
|
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||||
|
*
|
||||||
|
* Main Menu - Heading item layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||||
|
$anchor_css = $item->anchor_css ?: '';
|
||||||
|
|
||||||
|
$linktype = $item->title;
|
||||||
|
|
||||||
|
if ($item->menu_icon) {
|
||||||
|
// The link is an icon
|
||||||
|
if ($itemParams->get('menu_text', 1)) {
|
||||||
|
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||||
|
} else {
|
||||||
|
// If the icon itself is the link, it needs a visually hidden text
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add dropdown toggle for items with children
|
||||||
|
$headingClass = 'nav-link mod-menu-main__heading';
|
||||||
|
if ($item->deeper) {
|
||||||
|
$headingClass .= ' dropdown-toggle';
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<span class="<?php echo $headingClass . ' ' . $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||||
31
src/templates/html/mod_menu/default_separator.php
Normal file
31
src/templates/html/mod_menu/default_separator.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package Joomla.Site
|
||||||
|
* @subpackage mod_menu
|
||||||
|
*
|
||||||
|
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||||
|
*
|
||||||
|
* Main Menu - Separator item layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
|
||||||
|
$anchor_css = $item->anchor_css ?: '';
|
||||||
|
|
||||||
|
$linktype = $item->title;
|
||||||
|
|
||||||
|
if ($item->menu_icon) {
|
||||||
|
// The link is an icon
|
||||||
|
if ($itemParams->get('menu_text', 1)) {
|
||||||
|
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||||
|
} else {
|
||||||
|
// If the icon itself is the link, it needs a visually hidden text
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<span class="dropdown-divider mod-menu-main__separator <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
|
||||||
69
src/templates/html/mod_menu/default_url.php
Normal file
69
src/templates/html/mod_menu/default_url.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package Joomla.Site
|
||||||
|
* @subpackage mod_menu
|
||||||
|
*
|
||||||
|
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||||
|
*
|
||||||
|
* Main Menu - URL item layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
use Joomla\CMS\Filter\OutputFilter;
|
||||||
|
use Joomla\CMS\HTML\HTMLHelper;
|
||||||
|
|
||||||
|
$attributes = [];
|
||||||
|
|
||||||
|
if ($item->anchor_title) {
|
||||||
|
$attributes['title'] = $item->anchor_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->anchor_css) {
|
||||||
|
$attributes['class'] = $item->anchor_css;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->anchor_rel) {
|
||||||
|
$attributes['rel'] = $item->anchor_rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
$linktype = $item->title;
|
||||||
|
|
||||||
|
if ($item->menu_icon) {
|
||||||
|
// The link is an icon
|
||||||
|
if ($itemParams->get('menu_text', 1)) {
|
||||||
|
// If the link text is to be displayed, the icon is added with aria-hidden
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
|
||||||
|
} else {
|
||||||
|
// If the icon itself is the link, it needs a visually hidden text
|
||||||
|
$linktype = '<span class="p-2 ' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->browserNav == 1) {
|
||||||
|
$attributes['target'] = '_blank';
|
||||||
|
$attributes['rel'] = 'noopener noreferrer';
|
||||||
|
} elseif ($item->browserNav == 2) {
|
||||||
|
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
|
||||||
|
|
||||||
|
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add dropdown toggle for items with children
|
||||||
|
$linkClass = 'nav-link mod-menu-main__link';
|
||||||
|
if ($item->deeper) {
|
||||||
|
$linkClass .= ' dropdown-toggle';
|
||||||
|
$attributes['data-bs-toggle'] = 'dropdown';
|
||||||
|
$attributes['role'] = 'button';
|
||||||
|
$attributes['aria-expanded'] = 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge existing class with our class
|
||||||
|
if (isset($attributes['class'])) {
|
||||||
|
$attributes['class'] .= ' ' . $linkClass;
|
||||||
|
} else {
|
||||||
|
$attributes['class'] = $linkClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
|
||||||
9
src/templates/html/mod_menu/index.html
Normal file
9
src/templates/html/mod_menu/index.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
<name>MokoCassiopeia</name>
|
<name>MokoCassiopeia</name>
|
||||||
<version>03.08.02</version>
|
<version>03.08.03</version>
|
||||||
<creationDate>2026-02-27</creationDate>
|
<creationDate>2026-02-27</creationDate>
|
||||||
<author>Jonathan Miller || Moko Consulting</author>
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
INGROUP: MokoCassiopeia
|
INGROUP: MokoCassiopeia
|
||||||
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
|
||||||
PATH: ./updates.xml
|
PATH: ./updates.xml
|
||||||
VERSION: 03.08.02
|
VERSION: 03.08.03
|
||||||
BRIEF: Update manifest XML file for MokoCassiopeia
|
BRIEF: Update manifest XML file for MokoCassiopeia
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<type>template</type>
|
<type>template</type>
|
||||||
<client>site</client>
|
<client>site</client>
|
||||||
|
|
||||||
<version>03.08.02</version>
|
<version>03.08.03</version>
|
||||||
<creationDate>2026-02-27</creationDate>
|
<creationDate>2026-02-27</creationDate>
|
||||||
<author>Jonathan Miller || Moko Consulting</author>
|
<author>Jonathan Miller || Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
|
|||||||
Reference in New Issue
Block a user