Files
Jonathan Miller a2dcf2f072
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
fix: skip overlay background on solid colour and gradient hero modes
The overlay's semi-transparent background was covering the gradient,
making it invisible. Color/gradient modes use controlled backgrounds
that don't need an overlay for text readability — the card handles
that. Overlay layout (flex positioning) is preserved.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-04 17:24:07 -05:00

167 lines
8.4 KiB
PHP

<?php
/**
* @package Joomla.Site
* @subpackage mod_mokojoomhero
*
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GPL-3.0-or-later
* SPDX-License-Identifier: GPL-3.0-or-later
*/
defined('_JEXEC') or die;
/** @var string $heroMode */
/** @var array $heroImages */
/** @var int $slideInterval */
/** @var string $fadeType */
/** @var string $videoUrl */
/** @var string $youtubeId */
/** @var string $vimeoId */
/** @var string $heroHeight */
/** @var string $heroHeightMobile */
/** @var string $overlayColor */
/** @var string $overlayType */
/** @var float $overlayOpacity */
/** @var string $textAlign */
/** @var string $verticalAlign */
/** @var string $textColor */
/** @var string $contentSource */
/** @var int $articleId */
/** @var bool $useArticleTitle */
/** @var string $heroContent */
/** @var string $articleTitle */
/** @var array $slides */
/** @var bool $showCard */
/** @var int $cardDelay */
/** @var string $contentAnimation */
/** @var int $contentAnimationDelay */
/** @var bool $parallaxEnabled */
/** @var float $parallaxSpeed */
/** @var bool $showMuteToggle */
/** @var string $videoPoster */
/** @var bool $showScrollIndicator */
/** @var string $bgColor */
/** @var string $gradientStart */
/** @var string $gradientEnd */
/** @var int $gradientAngle */
$moduleId = 'mod-mokojoomhero-' . $module->id;
// Convert hex overlay colour to rgba
$r = hexdec(substr($overlayColor, 1, 2));
$g = hexdec(substr($overlayColor, 3, 2));
$b = hexdec(substr($overlayColor, 5, 2));
$rgbaOpaque = "rgba($r, $g, $b, $overlayOpacity)";
$rgbaTransparent = "rgba($r, $g, $b, 0)";
// Build overlay background based on type
$overlayDirections = [
'gradient-bottom' => 'to bottom',
'gradient-top' => 'to top',
'gradient-left' => 'to left',
'gradient-right' => 'to right',
];
// Skip overlay on solid colour/gradient modes — background is already a controlled design choice
if ($heroMode === 'color' || $heroMode === 'gradient') {
$overlayBg = '';
} elseif ($overlayType !== 'solid' && isset($overlayDirections[$overlayType])) {
$dir = $overlayDirections[$overlayType];
$overlayBg = "background: linear-gradient($dir, $rgbaTransparent, $rgbaOpaque);";
} else {
$overlayBg = "background-color: $rgbaOpaque;";
}
// Map vertical alignment to CSS align-items
$valignMap = ['top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end'];
$valignCss = $valignMap[$verticalAlign] ?? 'center';
$heightAttr = htmlspecialchars($heroHeight, ENT_QUOTES, 'UTF-8');
?>
<?php if ($heroHeightMobile) : ?>
<style>#<?php echo $moduleId; ?> { --mokojoomhero-mobile-height: <?php echo htmlspecialchars($heroHeightMobile, ENT_QUOTES, 'UTF-8'); ?>; }</style>
<?php endif; ?>
<div id="<?php echo $moduleId; ?>" class="mokojoomhero" style="height: <?php echo $heightAttr; ?>;"
<?php if ($parallaxEnabled) : ?>
data-parallax="<?php echo $parallaxSpeed; ?>"
<?php endif; ?>
<?php if ($heroMode === 'images' && count($heroImages) > 1) : ?>
data-slides="<?php echo htmlspecialchars(json_encode($heroImages), ENT_QUOTES, 'UTF-8'); ?>"
data-interval="<?php echo $slideInterval; ?>"
data-transition="<?php echo htmlspecialchars($fadeType, ENT_QUOTES, 'UTF-8'); ?>"
<?php if ($slides) : ?>
data-slide-content="<?php echo htmlspecialchars(json_encode($slides), ENT_QUOTES, 'UTF-8'); ?>"
<?php endif; ?>
<?php endif; ?>
>
<?php // Background layer — solid colour, single image, slideshow, or video ?>
<?php if ($heroMode === 'color') : ?>
<div class="mokojoomhero__color" style="background-color: <?php echo htmlspecialchars($bgColor, ENT_QUOTES, 'UTF-8'); ?>;"></div>
<?php elseif ($heroMode === 'gradient') : ?>
<div class="mokojoomhero__color" style="background: linear-gradient(<?php echo $gradientAngle; ?>deg, <?php echo htmlspecialchars($gradientStart, ENT_QUOTES, 'UTF-8'); ?>, <?php echo htmlspecialchars($gradientEnd, ENT_QUOTES, 'UTF-8'); ?>);"></div>
<?php elseif ($heroMode === 'video' && $youtubeId) : ?>
<?php if ($videoPoster) : ?>
<div class="mokojoomhero__poster" style="background-image: url('<?php echo htmlspecialchars(\Joomla\CMS\Uri\Uri::root() . ltrim($videoPoster, '/'), ENT_QUOTES, 'UTF-8'); ?>');"></div>
<?php endif; ?>
<iframe class="mokojoomhero__video" src="https://www.youtube-nocookie.com/embed/<?php echo htmlspecialchars($youtubeId, ENT_QUOTES, 'UTF-8'); ?>?autoplay=1&mute=1&loop=1&playlist=<?php echo htmlspecialchars($youtubeId, ENT_QUOTES, 'UTF-8'); ?>&controls=0&showinfo=0&rel=0&modestbranding=1&playsinline=1&enablejsapi=1&origin=<?php echo htmlspecialchars(\Joomla\CMS\Uri\Uri::root(), ENT_QUOTES, 'UTF-8'); ?>" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<?php elseif ($heroMode === 'video' && $vimeoId) : ?>
<?php if ($videoPoster) : ?>
<div class="mokojoomhero__poster" style="background-image: url('<?php echo htmlspecialchars(\Joomla\CMS\Uri\Uri::root() . ltrim($videoPoster, '/'), ENT_QUOTES, 'UTF-8'); ?>');"></div>
<?php endif; ?>
<iframe class="mokojoomhero__video" src="https://player.vimeo.com/video/<?php echo htmlspecialchars($vimeoId, ENT_QUOTES, 'UTF-8'); ?>?autoplay=1&muted=1&loop=1&background=1" allow="autoplay" allowfullscreen></iframe>
<?php elseif (($heroMode === 'video' || $heroMode === 'localvideo') && $videoUrl) : ?>
<?php if ($videoPoster) : ?>
<div class="mokojoomhero__poster" style="background-image: url('<?php echo htmlspecialchars(\Joomla\CMS\Uri\Uri::root() . ltrim($videoPoster, '/'), ENT_QUOTES, 'UTF-8'); ?>');"></div>
<?php endif; ?>
<video class="mokojoomhero__video" autoplay muted loop playsinline<?php if ($videoPoster) : ?> poster="<?php echo htmlspecialchars(\Joomla\CMS\Uri\Uri::root() . ltrim($videoPoster, '/'), ENT_QUOTES, 'UTF-8'); ?>"<?php endif; ?>>
<source src="<?php echo htmlspecialchars($videoUrl, ENT_QUOTES, 'UTF-8'); ?>">
</video>
<?php elseif ($heroImages) : ?>
<?php foreach ($heroImages as $i => $img) : ?>
<div class="mokojoomhero__slide<?php echo $i === 0 ? ' mokojoomhero__slide--active' : ''; ?>"
style="background-image: url('<?php echo htmlspecialchars($img, ENT_QUOTES, 'UTF-8'); ?>');"
aria-hidden="<?php echo $i === 0 ? 'false' : 'true'; ?>">
</div>
<?php endforeach; ?>
<?php endif; ?>
<?php if (($heroMode === 'video' || $heroMode === 'localvideo') && $showMuteToggle) : ?>
<button class="mokojoomhero__mute-toggle" type="button" aria-label="Unmute video" data-muted="true">
<span class="mokojoomhero__mute-icon" aria-hidden="true">&#x1F507;</span>
</button>
<?php endif; ?>
<?php if ($showScrollIndicator) : ?>
<button class="mokojoomhero__scroll-indicator" type="button" aria-label="Scroll down">
<svg class="mokojoomhero__scroll-chevron" viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>
</button>
<?php endif; ?>
<?php // Overlay + content ?>
<div class="mokojoomhero__overlay" style="<?php echo $overlayBg; ?> align-items: <?php echo $valignCss; ?>;">
<div class="mokojoomhero__content<?php if ($contentAnimation !== 'none') : ?> mokojoomhero__content--anim-<?php echo htmlspecialchars($contentAnimation, ENT_QUOTES, 'UTF-8'); ?><?php endif; ?>" style="text-align: <?php echo htmlspecialchars($textAlign, ENT_QUOTES, 'UTF-8'); ?>; color: <?php echo htmlspecialchars($textColor, ENT_QUOTES, 'UTF-8'); ?>;<?php if ($contentAnimationDelay) : ?> animation-delay: <?php echo $contentAnimationDelay; ?>ms;<?php endif; ?>">
<?php
$displayTitle = ($contentSource === 'article' && $useArticleTitle && $articleTitle)
? $articleTitle
: $module->title;
$showTitle = ($contentSource === 'article' && $useArticleTitle && $articleTitle) || $module->showtitle;
?>
<?php if ($heroContent || $showTitle) : ?>
<?php if ($showCard) : ?>
<div class="mokojoomhero__card"<?php if ($cardDelay) : ?> style="animation-delay: <?php echo $cardDelay; ?>ms;" data-card-delay="<?php echo $cardDelay; ?>"<?php endif; ?>>
<?php if ($showTitle) : ?>
<h2 class="mokojoomhero__title"><?php echo htmlspecialchars($displayTitle, ENT_QUOTES, 'UTF-8'); ?></h2>
<?php endif; ?>
<?php echo $heroContent; ?>
</div>
<?php else : ?>
<?php if ($showTitle) : ?>
<h2 class="mokojoomhero__title"><?php echo htmlspecialchars($displayTitle, ENT_QUOTES, 'UTF-8'); ?></h2>
<?php endif; ?>
<?php echo $heroContent; ?>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</div>