Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.1.1] - 2025-12-26

### Added - Enhanced navigation system with clickable parents

**Navigation Enhancements:**
- **Clickable Parent Menu Items** - Parent menu items can now be both clickable links AND dropdown toggles
- Click text to navigate to parent page
- Click chevron to toggle submenu
- Uses `hasClickableParents` attribute on Navigation block
- Preserves WordPress Interactivity API compatibility
- Includes fallback JavaScript for enhanced compatibility
- **Improved Chevron Positioning** - Better chevron icon placement in navigation menus
- Chevron icons properly nested inside buttons for HTML5 validation
- Cleaner DOM structure for accessibility
- Uses `hasImprovedChevrons` attribute on Navigation block
- **Custom Navigation Styles** - Comprehensive navigation styling system
- New `assets/styles/core-navigation.css` with organized CSS architecture
- Desktop dropdown styling with shadows and borders
- Mobile overlay menu styling
- CSS custom properties for consistent spacing and sizing
- Responsive design for all viewport sizes
- **Navigation Frontend Script** - Client-side enhancement for navigation functionality
- Automatically enqueued for all pages
- Handles clickable parent conversion
- Fixes HTML5 validation issues
- Lightweight (no dependencies)

### Changed - Pattern and style refinements

**Pattern Updates:**
- **header-standard** - Updated site title styling
- Changed font weight from 300 (light) to 600 (semi-bold) for better visibility
- Adjusted font size from "medium" to "base" for consistency
- Removed custom "has-bottom-border" class
- Added `hasClickableParents` and `hasImprovedChevrons` to navigation block
- **footer-simple** - Updated footer link colors
- Changed default text color from "secondary" to "main" for better contrast
- Updated link hover color from "main" to "primary" for better visual feedback
- **stats-showcase** - Improved avatar styling
- Removed hardcoded width/height (60px) from avatar image
- Added `is-avatar` class for consistent avatar sizing via theme.json
- Uses `var(--wp--custom--avatar-size)` for centralized sizing
- Maintains `is-style-rounded-full` and `is-style-rounded` classes

### Technical

- Frontend JavaScript uses vanilla DOM manipulation (no dependencies)
- CSS organized with table of contents and clear sections
- WordPress Interactivity API attributes preserved on converted elements
- HTML5 validation improved by proper chevron icon nesting
- Navigation enhancements work with all WordPress themes (not theme-specific)
- Avatar sizing now centralized via theme.json custom properties

## [1.1.0] - 2025-12-25

### Added - Spa & Wellness style variation and patterns
Expand Down
125 changes: 125 additions & 0 deletions assets/js/navigation-frontend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/**
* Navigation Frontend Enhancement
*
* 1. Accessibility fix: Move chevron icons inside buttons (all navigation blocks)
* 2. Clickable parents: Convert parent buttons to links with separate toggles
*/
document.addEventListener('DOMContentLoaded', () => {
// ============================================
// 1. ACCESSIBILITY FIX - Standard Navigation
// ============================================
// Fix navigation list structure by moving chevron inside button
// This resolves HTML5 validation issue where <span> is direct child of <li>
// Only needed for navigation blocks WITHOUT clickable parents (they handle it differently)
const standardNavs = document.querySelectorAll('.wp-block-navigation:not(.has-clickable-parents)');

standardNavs.forEach(nav => {
const navItems = nav.querySelectorAll('.wp-block-navigation-item.has-child');

navItems.forEach(item => {
const button = item.querySelector('.wp-block-navigation-submenu__toggle');
const chevron = item.querySelector(':scope > .wp-block-navigation__submenu-icon');

// Move chevron inside button if both exist and chevron is orphaned outside button
if (button && chevron && chevron.parentNode === item) {
button.appendChild(chevron);
}
});
});

// ============================================
// 2. CLICKABLE PARENTS FEATURE
// ============================================
// Converts parent menu buttons to clickable links with separate toggle buttons
// when the hasClickableParents attribute is enabled on the navigation block
const navs = document.querySelectorAll('.wp-block-navigation.has-clickable-parents');

navs.forEach(nav => {
// Find all parent menu items that have submenus and a parent URL
const parentItems = nav.querySelectorAll('li.has-child[data-parent-url]');

parentItems.forEach(li => {
const parentUrl = li.getAttribute('data-parent-url');
if (!parentUrl) return;

// Find the submenu toggle button
const button = li.querySelector('.wp-block-navigation-submenu__toggle');
if (!button) return;

// Get the menu item label
const label = button.querySelector('.wp-block-navigation-item__label');
const labelText = label ? label.textContent : '';

// Find the chevron icon
const chevronContainer = li.querySelector('.wp-block-navigation__submenu-icon');
const chevronSvg = chevronContainer ? chevronContainer.cloneNode(true) : null;

// Create wrapper div for link + toggle
const wrapper = document.createElement('div');
wrapper.className = 'moiraine-nav-parent-wrapper';

// Create clickable link for parent item
const link = document.createElement('a');
link.href = parentUrl;
link.className = 'moiraine-nav-parent-link wp-block-navigation-item__content';
link.innerHTML = label ? label.outerHTML : labelText;
link.setAttribute('aria-label', 'Go to ' + labelText);

// Create new toggle button for chevron
const toggle = document.createElement('button');
toggle.className = 'moiraine-nav-toggle';
toggle.setAttribute('aria-expanded', button.getAttribute('aria-expanded') || 'false');
toggle.setAttribute('aria-label', 'Toggle ' + labelText + ' submenu');

if (chevronSvg) {
toggle.appendChild(chevronSvg);
}

// Copy WordPress Interactivity API attributes from original button to toggle
const interactivityAttrs = [
'data-wp-interactive',
'data-wp-context',
'data-wp-on--click',
'data-wp-on-async--click',
'data-wp-bind--aria-expanded',
'data-wp-class--has-child',
'data-wp-class--is-open',
'aria-haspopup'
];

interactivityAttrs.forEach(attr => {
const value = button.getAttribute(attr);
if (value) {
toggle.setAttribute(attr, value);
}
});

// Add click handler for toggling dropdown (fallback if Interactivity API doesn't work)
toggle.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();

const isExpanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', !isExpanded);

// Toggle is-open class for CSS fallback
if (!isExpanded) {
li.classList.add('is-open');
} else {
li.classList.remove('is-open');
}
});

// Replace button with wrapper containing link + toggle
button.parentNode.insertBefore(wrapper, button);
wrapper.appendChild(link);
wrapper.appendChild(toggle);
button.remove();

// Remove the original chevron container if it still exists separately
if (chevronContainer && chevronContainer.parentNode === li) {
chevronContainer.remove();
}
});
});
});
Loading
Loading