From 5e5d6a4e897764ff8e948d4ad5447d4bc5dc08a8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Thu, 16 Apr 2026 18:29:43 -0500 Subject: [PATCH] Offline page redesign, remove brand showcase tab, force a11y/theme to bottom-right - Offline page: full-viewport Joomla offline_image background, centered glass card overlay with logo glow, message, offline position, login accordion, copyright - Favicon: added to offline page, HTML-escaped paths in helper - Removed brand showcase tab, added footer CSS vars to CSS Variables tab - Forced a11y toolbar and theme FAB to bottom-right (removed position selectors) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/helper/favicon.php | 2 +- src/index.php | 4 +- src/language/en-GB/tpl_mokocassiopeia.ini | 8 +- src/language/en-US/tpl_mokocassiopeia.ini | 8 +- src/media/css/offline.css | 273 +++++++++++----------- src/offline.php | 266 +++++++++++---------- src/templateDetails.xml | 13 +- 7 files changed, 298 insertions(+), 276 deletions(-) diff --git a/src/helper/favicon.php b/src/helper/favicon.php index 2567e86..028eaf2 100644 --- a/src/helper/favicon.php +++ b/src/helper/favicon.php @@ -162,7 +162,7 @@ class MokoFaviconHelper */ public static function getHeadTags(string $basePath): string { - $basePath = rtrim($basePath, '/'); + $basePath = htmlspecialchars(rtrim($basePath, '/'), ENT_QUOTES, 'UTF-8'); return '' . "\n" . '' . "\n" diff --git a/src/index.php b/src/index.php index e30eb97..70db6f6 100644 --- a/src/index.php +++ b/src/index.php @@ -41,7 +41,7 @@ $params_favicon_source = (string) $this->params->get('favicon_source', ''); $params_theme_enabled = $this->params->get('theme_enabled', 1); $params_theme_control_type = (string) $this->params->get('theme_control_type', 'radios'); $params_theme_fab_enabled = $this->params->get('theme_fab_enabled', 1); -$params_theme_fab_pos = $this->params->get('theme_fab_pos', 'br'); +$params_theme_fab_pos = 'br'; // Accessibility params $params_a11y_toolbar = $this->params->get('a11y_toolbar_enabled', 1); @@ -51,7 +51,7 @@ $params_a11y_contrast = $this->params->get('a11y_high_contrast', 1); $params_a11y_links = $this->params->get('a11y_highlight_links', 1); $params_a11y_font = $this->params->get('a11y_readable_font', 1); $params_a11y_animations = $this->params->get('a11y_pause_animations', 1); -$params_a11y_pos = (string) $this->params->get('a11y_toolbar_pos', 'tl'); +$params_a11y_pos = 'br'; // Detecting Active Variables $option = $input->getCmd('option', ''); diff --git a/src/language/en-GB/tpl_mokocassiopeia.ini b/src/language/en-GB/tpl_mokocassiopeia.ini index 945950b..0116bc3 100644 --- a/src/language/en-GB/tpl_mokocassiopeia.ini +++ b/src/language/en-GB/tpl_mokocassiopeia.ini @@ -259,16 +259,14 @@ TPL_MOKOCASSIOPEIA_CSS_VARS_VM_DESC="Surfaces & text
+/* Copyright (C) 2026 Moko Consulting This file is part of a Moko Consulting project. @@ -30,7 +30,7 @@ $params = $this->params ?: $app->getTemplate(true)->params; $direction = $this->direction ?: 'ltr'; /* ----------------------- - Load ONLY template.css + theme palettes (with min toggle) + Load CSS + theme palettes ------------------------ */ $useMin = !((int) $params->get('development_mode', 0) === 1); $assetSuffix = $useMin ? '.min' : ''; @@ -59,30 +59,30 @@ if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templ $doc->addStyleSheet($base . 'theme/dark.custom' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-dark-custom']); } -/* Load user assets last (after all other styles and scripts) */ +/* Load user assets last */ $doc->addStyleSheet($base . 'user' . $assetSuffix . '.css', ['version' => 'auto'], ['id' => 'moko-user']); -/* Bootstrap CSS/JS for accordion behavior; safe to keep. */ +/* Bootstrap CSS/JS for accordion */ HTMLHelper::_('bootstrap.loadCss', true, $doc); HTMLHelper::_('bootstrap.framework'); -/* Load template.js for theme switcher and other functionality */ +/* Load template.js for theme switcher */ $doc->addScript($jsBase . 'template' . $assetSuffix . '.js', ['version' => 'auto', 'defer' => true], ['id' => 'moko-template-js']); -/* Load user.js last for custom user scripts */ +/* Load user.js last */ $doc->addScript($jsBase . 'user' . $assetSuffix . '.js', ['version' => 'auto', 'defer' => true], ['id' => 'moko-user-js']); /* ----------------------- - Title + Meta (Include Site Name in Page Titles) + Title + Meta ------------------------ */ $sitename = (string) $app->get('sitename'); $baseTitle = Text::_('JGLOBAL_OFFLINE') ?: 'Offline'; -$snSetting = (int) $app->get('sitename_pagetitles', 0); // 0=no, 1=before, 2=after +$snSetting = (int) $app->get('sitename_pagetitles', 0); if ($snSetting === 1) { - $doc->setTitle(Text::sprintf('JPAGETITLE', $sitename, $baseTitle)); // Site Name BEFORE + $doc->setTitle(Text::sprintf('JPAGETITLE', $sitename, $baseTitle)); } elseif ($snSetting === 2) { - $doc->setTitle(Text::sprintf('JPAGETITLE', $baseTitle, $sitename)); // Site Name AFTER + $doc->setTitle(Text::sprintf('JPAGETITLE', $baseTitle, $sitename)); } else { $doc->setTitle($baseTitle); } @@ -91,11 +91,21 @@ $doc->setMetaData('robots', 'noindex, nofollow'); /* ----------------------- Offline content from Global Config ------------------------ */ -$displayOfflineMessage = (int) $app->get('display_offline_message', 1); // 0|1|2 +$displayOfflineMessage = (int) $app->get('display_offline_message', 1); $offlineMessage = trim((string) $app->get('offline_message', '')); /* ----------------------- - Brand: logo from params OR siteTitle (matches index.php) + Offline image from Joomla Global Config (System > Global Configuration > Site > Offline Image) + Used as the full-viewport background image. +------------------------ */ +$offlineImage = trim((string) $app->get('offline_image', '')); +$bgStyle = ''; +if ($offlineImage !== '') { + $bgStyle = 'background-image: url(\'' . htmlspecialchars(Uri::root(false) . $offlineImage, ENT_QUOTES, 'UTF-8') . '\');'; +} + +/* ----------------------- + Brand: logo from template params OR siteTitle ------------------------ */ $brandHtml = ''; $logoFile = (string) $params->get('logoFile'); @@ -110,9 +120,8 @@ if ($logoFile !== '') { 0 ); } else { - // If no logo file, show the title (defaults to "MokoCassiopeia" if not set) $siteTitle = $params->get('siteTitle', 'MokoCassiopeia'); - $brandHtml = '' + $brandHtml = '' . htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8') . ''; } @@ -120,6 +129,20 @@ if ($logoFile !== '') { $brandTagline = (string) ($params->get('brand_tagline') ?: $params->get('siteDescription') ?: ''); $showTagline = (int) $params->get('show_brand_tagline', 0); +// Favicon +$params_favicon_source = (string) $params->get('favicon_source', ''); +$faviconHeadTags = ''; +if ($params_favicon_source) { + require_once JPATH_ROOT . '/templates/' . $this->template . '/helper/favicon.php'; + $faviconSourceAbs = JPATH_ROOT . '/' . ltrim($params_favicon_source, '/'); + $faviconOutputDir = JPATH_ROOT . '/images/favicons'; + $faviconUrlBase = Uri::root(true) . '/images/favicons'; + + if (MokoFaviconHelper::generate($faviconSourceAbs, $faviconOutputDir)) { + $faviconHeadTags = MokoFaviconHelper::getHeadTags($faviconUrlBase); + } +} + // Theme params $params_theme_enabled = (int) $params->get('theme_enabled', 1); @@ -135,7 +158,7 @@ if (!empty($params_googlesitekey)) { } /* ----------------------- - Login routes & Users + Login routes ------------------------ */ $action = Route::_('index.php', true); $return = base64_encode(Uri::base()); @@ -156,10 +179,12 @@ if (class_exists('\Joomla\Component\Users\Site\Helper\RouteHelper')) { + + + - - - - - - - countModules('offline-header')) : ?> -
-
- -
-
- - -
+ +
+
-
-
-
-
- - - - - - - + +
+
- -
-

-

-
- -
-

-

- -

-
- + + + + + + + - - countModules('offline')) : ?> -
- -
- + + +
+

+

+
+ +
+

+

+
+ - -
-
-

- -

-
-
-
-
- + + countModules('offline')) : ?> +
+ +
+ -
- - -
+ +
+
+

+ +

+
+
+ +
+ -
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- -
+
+ + +
- - - - -
+
+ +
- - -
-
+ + + + +
+ + +
-
-
+ + + +
- + + countModules('offline-footer')) : ?> +
+ +
+ + diff --git a/src/templateDetails.xml b/src/templateDetails.xml index 5499cb6..c432c8c 100644 --- a/src/templateDetails.xml +++ b/src/templateDetails.xml @@ -295,7 +295,8 @@ - + @@ -312,7 +313,8 @@ - + @@ -365,6 +367,7 @@ + @@ -372,12 +375,6 @@ - - -
- - -