Add mobile-responsive overrides for 20 modules and 7 component views #81
@@ -18559,3 +18559,131 @@ nav[data-toggle=toc] .nav-link.active+ul{
|
||||
--alert-color: color-mix(in srgb, var(--warning) 90%, black);
|
||||
--alert-border-color: color-mix(in srgb, var(--warning) 20%, var(--body-bg));
|
||||
}
|
||||
|
||||
/* ===== MOD_SEARCH MOBILE RESPONSIVE STYLES ===== */
|
||||
.mod-search-responsive {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mod-search__form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mod-search__input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mod-search__input-wrapper--inline {
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.mod-search__input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
border: 1px solid var(--input-border-color, #dee2e6);
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--input-bg, #fff);
|
||||
color: var(--input-color, #212529);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.mod-search__input:focus {
|
||||
border-color: var(--color-primary, #0d6efd);
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
|
||||
.mod-search__button-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mod-search__button-wrapper--left,
|
||||
.mod-search__button-wrapper--right {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mod-search__button {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.375rem;
|
||||
white-space: nowrap;
|
||||
min-height: 44px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.mod-search__button--icon {
|
||||
padding: 0.5rem;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.mod-search__button--icon .icon-search {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
/* Mobile-first responsive adjustments */
|
||||
@media (max-width: 575.98px) {
|
||||
.mod-search__input {
|
||||
font-size: 16px;
|
||||
padding: 0.625rem 0.875rem;
|
||||
}
|
||||
|
||||
.mod-search__button {
|
||||
padding: 0.625rem 1.25rem;
|
||||
font-size: 1rem;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.mod-search__button--icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.mod-search__input-wrapper--inline {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mod-search__button-wrapper--left .mod-search__button,
|
||||
.mod-search__button-wrapper--right .mod-search__button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet improvements */
|
||||
@media (min-width: 576px) and (max-width: 767.98px) {
|
||||
.mod-search__input-wrapper--inline {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop enhancements */
|
||||
@media (min-width: 768px) {
|
||||
.mod-search__form {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mod-search__input-wrapper--inline {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.mod-search__button-wrapper--top,
|
||||
.mod-search__button-wrapper--bottom {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
126
src/templates/html/mod_search/README.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# mod_search Mobile Responsive Override
|
||||
|
||||
## Overview
|
||||
This directory contains a mobile-responsive override for Joomla's `mod_search` module, designed specifically for the MokoCassiopeia template.
|
||||
|
||||
## Features
|
||||
|
||||
### Mobile Responsiveness
|
||||
- **Flexible Layout**: Adapts to different screen sizes automatically
|
||||
- **Touch-Friendly**: Minimum 44px touch targets (48px on mobile)
|
||||
- **Readable Text**: 16px font size on mobile to prevent auto-zoom on iOS
|
||||
- **Proper Spacing**: Adequate padding and gaps for easy interaction
|
||||
|
||||
### Responsive Breakpoints
|
||||
- **Mobile (< 576px)**: Stacked layout, full-width buttons, larger touch targets
|
||||
- **Tablet (576px - 767px)**: Inline search field and button
|
||||
- **Desktop (≥ 768px)**: Optimized horizontal layout
|
||||
|
||||
### Button Position Support
|
||||
The override supports all standard mod_search button positions:
|
||||
- **Left**: Search button appears to the left of input field
|
||||
- **Right**: Search button appears to the right of input field (default)
|
||||
- **Top**: Search button appears above input field
|
||||
- **Bottom**: Search button appears below input field
|
||||
|
||||
### Icon Button Support
|
||||
Supports both text and icon-only search buttons:
|
||||
- Text buttons display customizable button text
|
||||
- Icon buttons show search icon (icon-search)
|
||||
|
||||
## Files
|
||||
|
||||
### default.php
|
||||
The main template override file that renders the search module with responsive HTML structure.
|
||||
|
||||
**Key Classes:**
|
||||
- `.mod-search-responsive`: Main wrapper class
|
||||
- `.mod-search__form`: Form container with flex layout
|
||||
- `.mod-search__input-wrapper`: Input field wrapper
|
||||
- `.mod-search__input`: Search input field
|
||||
- `.mod-search__button`: Search button
|
||||
- `.mod-search__button--icon`: Icon-only button variant
|
||||
|
||||
## CSS Styling
|
||||
|
||||
The mobile-responsive styles are defined in `/src/media/css/template.css` under the section:
|
||||
```
|
||||
/* ===== MOD_SEARCH MOBILE RESPONSIVE STYLES ===== */
|
||||
```
|
||||
|
||||
### Key CSS Features:
|
||||
1. **Flexbox Layout**: Uses modern flexbox for flexible, responsive layouts
|
||||
2. **CSS Variables**: Integrates with template's color scheme system
|
||||
3. **Mobile-First**: Base styles target mobile, with progressive enhancement
|
||||
4. **Accessible**: Proper focus states and ARIA labels
|
||||
5. **Touch-Optimized**: Appropriate sizing for touch interaction
|
||||
|
||||
## Usage
|
||||
|
||||
This override is automatically used when:
|
||||
1. The MokoCassiopeia template is active
|
||||
2. A mod_search module is published on the site
|
||||
|
||||
No additional configuration is required beyond standard mod_search module settings.
|
||||
|
||||
## Module Parameters
|
||||
|
||||
All standard mod_search parameters are supported:
|
||||
- **Width**: Input field width (in characters) - note: overridden by responsive CSS
|
||||
- **Button Text**: Custom text for the search button
|
||||
- **Button Position**: left, right, top, or bottom
|
||||
- **Image Button**: Use icon instead of text button
|
||||
- **Max Length**: Maximum search query length
|
||||
- **Menu Item**: Target search results page
|
||||
|
||||
## Accessibility Features
|
||||
|
||||
- Hidden label for screen readers
|
||||
- ARIA labels on input and button
|
||||
- Proper focus indicators
|
||||
- Semantic HTML structure
|
||||
- Keyboard navigation support
|
||||
|
||||
## Browser Support
|
||||
|
||||
- Modern browsers with flexbox support
|
||||
- Responsive on all device sizes
|
||||
- Works with iOS Safari (no auto-zoom on input focus)
|
||||
- Compatible with touch and mouse input
|
||||
|
||||
## Customization
|
||||
|
||||
To customize the appearance, you can:
|
||||
1. Override CSS variables in `user.css`
|
||||
2. Modify classes in `default.php`
|
||||
3. Add custom styles targeting `.mod-search-responsive`
|
||||
|
||||
Example custom CSS:
|
||||
```css
|
||||
.mod-search-responsive {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.mod-search__input {
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.mod-search__button {
|
||||
border-radius: 25px;
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
The override has been designed to work across:
|
||||
- Mobile devices (320px+)
|
||||
- Tablets (768px+)
|
||||
- Desktop screens (1200px+)
|
||||
- Touch and click interactions
|
||||
- Portrait and landscape orientations
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
Licensed under GNU General Public License version 2 or later
|
||||
94
src/templates/html/mod_search/default.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage mod_search
|
||||
*
|
||||
* @copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* Mobile responsive override for mod_search module
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// Get module parameters
|
||||
$width = (int) $params->get('width', 20);
|
||||
$maxlength = (int) $params->get('maxlength', 200);
|
||||
$button_text = $params->get('button_text', '');
|
||||
$button_pos = $params->get('button_pos', 'right');
|
||||
$imagebutton = $params->get('imagebutton', 0);
|
||||
$set_itemid = (int) $params->get('set_itemid', 0);
|
||||
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// Add responsive wrapper class
|
||||
$wrapperClass = 'mod-search mod-search-responsive ' . $moduleclass_sfx;
|
||||
$inputClass = 'mod-search__input form-control';
|
||||
$buttonClass = 'mod-search__button btn btn-primary';
|
||||
|
||||
// Build the search button
|
||||
if ($imagebutton) {
|
||||
$buttonHtml = '<button class="' . $buttonClass . ' mod-search__button--icon" type="submit" aria-label="' . Text::_('JSEARCH_FILTER_SUBMIT') . '">'
|
||||
. '<span class="icon-search" aria-hidden="true"></span>'
|
||||
. '</button>';
|
||||
} else {
|
||||
$button_text = $button_text ?: Text::_('JSEARCH_FILTER_SUBMIT');
|
||||
$buttonHtml = '<button class="' . $buttonClass . '" type="submit">'
|
||||
. htmlspecialchars($button_text, ENT_COMPAT, 'UTF-8')
|
||||
|
The file uses
The file uses `ENT_COMPAT` for htmlspecialchars() calls, but the PR description states that output escaping should use `ENT_QUOTES`. There's also inconsistency across the codebase - Community Builder component files use `ENT_QUOTES` while module overrides use `ENT_COMPAT`.
`ENT_QUOTES` is more secure as it encodes both double and single quotes, preventing potential XSS attacks in contexts where attributes use single quotes. For consistency and security, all files should use `ENT_QUOTES`.
|
||||
. '</button>';
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
The variables The variables `$width` (line 18) and `$output` (line 43) are defined but never used in the template. The `$width` parameter was likely meant for the input field but responsive CSS overrides it. The `$output` variable has no purpose in this code. Consider removing these unused variables to improve code clarity.
|
||||
|
||||
// Menuitem option
|
||||
$mitemid = $set_itemid > 0 ? $set_itemid : $app->input->getInt('Itemid');
|
||||
|
The variable Alternatively, you can call it directly inline: The variable `$app` is used on line 46 but is never defined in this file. This will cause a fatal error. You should add a use statement and define the variable, for example:
```php
use Joomla\CMS\Factory;
$app = Factory::getApplication();
```
Alternatively, you can call it directly inline:
```php
$mitemid = $set_itemid > 0 ? $set_itemid : Factory::getApplication()->input->getInt('Itemid');
```
|
||||
?>
|
||||
|
||||
<div class="<?php echo $wrapperClass; ?>">
|
||||
<form action="<?php echo JRoute::_('index.php?option=com_search'); ?>" method="post" class="mod-search__form">
|
||||
<?php if ($button_pos === 'top') : ?>
|
||||
<div class="mod-search__button-wrapper mod-search__button-wrapper--top">
|
||||
<?php echo $buttonHtml; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="mod-search__input-wrapper <?php echo $button_pos !== 'top' && $button_pos !== 'bottom' ? 'mod-search__input-wrapper--inline' : ''; ?>">
|
||||
<?php if ($button_pos === 'left') : ?>
|
||||
<div class="mod-search__button-wrapper mod-search__button-wrapper--left">
|
||||
<?php echo $buttonHtml; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<label for="mod-search-searchword<?php echo $module->id; ?>" class="visually-hidden">
|
||||
<?php echo Text::_('COM_SEARCH_SEARCH'); ?>
|
||||
</label>
|
||||
<input
|
||||
id="mod-search-searchword<?php echo $module->id; ?>"
|
||||
name="searchword"
|
||||
class="<?php echo $inputClass; ?>"
|
||||
type="search"
|
||||
maxlength="<?php echo $maxlength; ?>"
|
||||
placeholder="<?php echo Text::_('COM_SEARCH_SEARCH'); ?>"
|
||||
aria-label="<?php echo Text::_('COM_SEARCH_SEARCH'); ?>"
|
||||
/>
|
||||
|
||||
<?php if ($button_pos === 'right') : ?>
|
||||
<div class="mod-search__button-wrapper mod-search__button-wrapper--right">
|
||||
<?php echo $buttonHtml; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($button_pos === 'bottom') : ?>
|
||||
<div class="mod-search__button-wrapper mod-search__button-wrapper--bottom">
|
||||
<?php echo $buttonHtml; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="task" value="search" />
|
||||
<input type="hidden" name="option" value="com_search" />
|
||||
<input type="hidden" name="Itemid" value="<?php echo $mitemid; ?>" />
|
||||
</form>
|
||||
</div>
|
||||
1
src/templates/html/mod_search/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title></title></head><body></body></html>
|
||||
Copyright year is inconsistent across files. Some files (like mod_search/default.php) use 2025 while Community Builder component files use 2026. Since we're currently in February 2026, all new files added in this release should consistently use (C) 2026 for consistency.