Browse Source

auto-hide nav

windhamdavid 1 week ago
parent
commit
0fa23d9349
5 changed files with 475 additions and 0 deletions
  1. 131 0
      functions.php
  2. 0 0
      inc/block-patterns.php
  3. 0 0
      inc/custom-blocks.php
  4. 228 0
      js/auto-hide-nav.js
  5. 116 0
      style.css

+ 131 - 0
functions.php

@@ -169,4 +169,135 @@ function add_edit_link() {
 add_action( 'init', 'add_edit_link_shortcode' );
 add_action( 'init', 'add_edit_link_shortcode' );
 function add_edit_link_shortcode() {
 function add_edit_link_shortcode() {
   add_shortcode( 'edit-link', 'add_edit_link' );
   add_shortcode( 'edit-link', 'add_edit_link' );
+}
+
+/***********************************************************
+################ Auto-Hide Navigation ######################
+************************************************************/
+
+// Enqueue the auto-hide navigation JavaScript
+add_action( 'wp_enqueue_scripts', 'srh25_enqueue_navigation_script' );
+function srh25_enqueue_navigation_script() {
+    // Option 1: Use separate JavaScript file (commented out for debugging)
+    /*
+    wp_enqueue_script( 
+        'srh25-auto-hide-nav', 
+        get_stylesheet_directory_uri() . '/js/auto-hide-nav.js', 
+        array(), 
+        '1.0.1', 
+        true 
+    );
+    */
+    
+    // Option 2: Inline script (active for better compatibility)
+    wp_enqueue_script( 'jquery' );
+    
+    $navigation_script = "
+    jQuery(document).ready(function($) {
+        console.log('Auto-hide navigation: jQuery script loaded');
+        
+        let lastScrollTop = 0;
+        let scrollThreshold = 100;
+        
+        // Find header with multiple selectors
+        let header = $('header').first();
+        if (header.length === 0) {
+            header = $('.wp-site-header, .wp-block-template-part[data-area=\"header\"], [class*=\"header\"]').first();
+        }
+        
+        let body = $('body');
+        let headerHeight = 0;
+        
+        console.log('Header element found:', header.length > 0 ? header[0] : 'None');
+        
+        if (header.length === 0) {
+            console.warn('No header element found for auto-hide navigation');
+            return;
+        }
+        
+        // Add identifying class
+        header.addClass('srh-auto-hide-header');
+        
+        function calculateHeaderHeight() {
+            headerHeight = header.outerHeight() || 80;
+            document.documentElement.style.setProperty('--header-height', headerHeight + 'px');
+            console.log('Header height calculated:', headerHeight);
+        }
+        
+        calculateHeaderHeight();
+        $(window).on('resize', calculateHeaderHeight);
+        
+        $(window).on('scroll', function() {
+            let scrollTop = $(this).scrollTop();
+            
+            if (scrollTop > 50) {
+                body.addClass('header-offset');
+                header.addClass('header-scrolled');
+            } else {
+                body.removeClass('header-offset');
+                header.removeClass('header-scrolled');
+            }
+            
+            if (scrollTop > scrollThreshold) {
+                if (scrollTop > lastScrollTop) {
+                    // Scrolling down - hide header
+                    header.removeClass('header-visible').addClass('header-hidden');
+                } else {
+                    // Scrolling up - show header
+                    header.removeClass('header-hidden').addClass('header-visible');
+                }
+            } else {
+                // Near top - always show header
+                header.removeClass('header-hidden header-visible');
+            }
+            
+            lastScrollTop = scrollTop;
+        });
+        
+        $(document).on('mousemove', function(e) {
+            if (e.clientY < 100 && $(window).scrollTop() > scrollThreshold) {
+                header.removeClass('header-hidden').addClass('header-visible');
+            }
+        });
+        
+        $('a[href^=\"#\"]').on('click', function(e) {
+            let target = $(this.getAttribute('href'));
+            if (target.length) {
+                e.preventDefault();
+                $('html, body').animate({
+                    scrollTop: target.offset().top - headerHeight
+                }, 600);
+            }
+        });
+        
+        $(document).on('keydown', function(e) {
+            if (e.key === 'Tab' || e.key === 'Escape') {
+                header.removeClass('header-hidden').addClass('header-visible');
+            }
+        });
+        
+        header.find('a, button, input, textarea, select').on('focus', function() {
+            header.removeClass('header-hidden').addClass('header-visible');
+        });
+        
+        console.log('Auto-hide navigation: Initialization complete');
+    });
+    ";
+    
+    wp_add_inline_script( 'jquery', $navigation_script );
+}
+
+// Add CSS custom properties support for older browsers
+add_action( 'wp_head', 'srh25_navigation_css_vars' );
+function srh25_navigation_css_vars() {
+    ?>
+    <script>
+    // CSS custom properties fallback
+    if (!window.CSS || !CSS.supports('color', 'var(--fake-var)')) {
+        document.documentElement.style.setProperty = document.documentElement.style.setProperty || function(property, value, priority) {
+            this[property] = value;
+        };
+    }
+    </script>
+    <?php
 }
 }

+ 0 - 0
inc/block-patterns.php


+ 0 - 0
inc/custom-blocks.php


+ 228 - 0
js/auto-hide-nav.js

@@ -0,0 +1,228 @@
+/**
+ * Auto-Hide Navigation Script
+ * Smoothly hides navigation when scrolling down and shows it when scrolling up
+ */
+
+(function() {
+    'use strict';
+    
+    // Configuration
+    const config = {
+        scrollThreshold: 100,        // Start hiding after this many pixels
+        mouseRevealZone: 100,        // Show header when mouse is within this many pixels from top
+        animationDuration: 300,      // Animation duration in ms
+        debounceDelay: 10           // Scroll event debounce delay
+    };
+    
+    // State management
+    let state = {
+        lastScrollTop: 0,
+        isVisible: true,
+        headerHeight: 0,
+        ticking: false
+    };
+    
+    // DOM elements
+    let elements = {};
+    
+    // Initialize when DOM is ready
+    document.addEventListener('DOMContentLoaded', init);
+    
+    function init() {
+        // Find header elements - Twenty Twenty-Five specific selectors
+        elements.header = document.querySelector('header') || 
+                         document.querySelector('.wp-site-header') || 
+                         document.querySelector('.wp-block-template-part[data-area="header"]') ||
+                         document.querySelector('.wp-block-group.is-layout-constrained') ||
+                         document.querySelector('[class*="header"]');
+        
+        elements.body = document.body;
+        
+        // Debug: Log found header element
+        console.log('Auto-hide navigation: Header element found:', elements.header);
+        
+        if (!elements.header) {
+            console.warn('Auto-hide navigation: No header element found');
+            // Try to find any element that might be the header
+            const possibleHeaders = document.querySelectorAll('nav, [class*="nav"], [class*="header"], [class*="menu"]');
+            console.log('Possible header elements:', possibleHeaders);
+            return;
+        }
+        
+        // Add identifying class for our CSS
+        elements.header.classList.add('srh-auto-hide-header');
+        
+        // Setup
+        calculateHeaderHeight();
+        bindEvents();
+        
+        // Initial state
+        updateHeaderState();
+        
+        console.log('Auto-hide navigation initialized successfully');
+    }
+    
+    function calculateHeaderHeight() {
+        if (!elements.header) return;
+        
+        state.headerHeight = elements.header.offsetHeight || 80;
+        document.documentElement.style.setProperty('--header-height', state.headerHeight + 'px');
+    }
+    
+    function bindEvents() {
+        // Scroll event with debouncing
+        window.addEventListener('scroll', debounce(handleScroll, config.debounceDelay));
+        
+        // Resize event
+        window.addEventListener('resize', debounce(calculateHeaderHeight, 100));
+        
+        // Mouse movement for revealing header
+        document.addEventListener('mousemove', handleMouseMove);
+        
+        // Keyboard events for accessibility
+        document.addEventListener('keydown', handleKeydown);
+        
+        // Focus events for accessibility
+        if (elements.header) {
+            const focusableElements = elements.header.querySelectorAll('a, button, input, textarea, select, [tabindex]');
+            focusableElements.forEach(el => {
+                el.addEventListener('focus', showHeader);
+            });
+        }
+        
+        // Smooth scroll for anchor links
+        document.addEventListener('click', handleAnchorClick);
+    }
+    
+    function handleScroll() {
+        if (!state.ticking) {
+            requestAnimationFrame(updateHeaderState);
+            state.ticking = true;
+        }
+    }
+    
+    function updateHeaderState() {
+        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
+        
+        // Add scrolled class for styling
+        if (scrollTop > 50) {
+            elements.body.classList.add('header-offset');
+            elements.header.classList.add('header-scrolled');
+        } else {
+            elements.body.classList.remove('header-offset');
+            elements.header.classList.remove('header-scrolled');
+        }
+        
+        // Hide/show logic
+        if (scrollTop > config.scrollThreshold) {
+            if (scrollTop > state.lastScrollTop && state.isVisible) {
+                // Scrolling down - hide header
+                hideHeader();
+            } else if (scrollTop < state.lastScrollTop && !state.isVisible) {
+                // Scrolling up - show header
+                showHeader();
+            }
+        } else if (!state.isVisible) {
+            // Near top - always show header
+            showHeader();
+        }
+        
+        state.lastScrollTop = scrollTop;
+        state.ticking = false;
+    }
+    
+    function hideHeader() {
+        if (!state.isVisible) return;
+        
+        state.isVisible = false;
+        elements.header.classList.remove('header-visible');
+        elements.header.classList.add('header-hidden');
+        
+        // Dispatch custom event
+        dispatchCustomEvent('headerHidden');
+    }
+    
+    function showHeader() {
+        if (state.isVisible) return;
+        
+        state.isVisible = true;
+        elements.header.classList.remove('header-hidden');
+        elements.header.classList.add('header-visible');
+        
+        // Dispatch custom event
+        dispatchCustomEvent('headerVisible');
+    }
+    
+    function handleMouseMove(e) {
+        if (e.clientY < config.mouseRevealZone && 
+            window.pageYOffset > config.scrollThreshold && 
+            !state.isVisible) {
+            showHeader();
+        }
+    }
+    
+    function handleKeydown(e) {
+        // Show header on Tab or Escape for accessibility
+        if (e.key === 'Tab' || e.key === 'Escape') {
+            showHeader();
+        }
+    }
+    
+    function handleAnchorClick(e) {
+        const link = e.target.closest('a[href^=\"#\"]');
+        if (!link) return;
+        
+        const targetId = link.getAttribute('href').substring(1);
+        const target = document.getElementById(targetId);
+        
+        if (target) {
+            e.preventDefault();
+            
+            const offsetTop = target.getBoundingClientRect().top + window.pageYOffset - state.headerHeight;
+            
+            window.scrollTo({
+                top: offsetTop,
+                behavior: 'smooth'
+            });
+        }
+    }
+    
+    function dispatchCustomEvent(eventName) {
+        const event = new CustomEvent(eventName, {
+            detail: {
+                headerElement: elements.header,
+                isVisible: state.isVisible,
+                scrollTop: state.lastScrollTop
+            }
+        });
+        document.dispatchEvent(event);
+    }
+    
+    function debounce(func, wait) {
+        let timeout;
+        return function executedFunction(...args) {
+            const later = () => {
+                clearTimeout(timeout);
+                func(...args);
+            };
+            clearTimeout(timeout);
+            timeout = setTimeout(later, wait);
+        };
+    }
+    
+    // Public API
+    window.SRHNavigation = {
+        show: showHeader,
+        hide: hideHeader,
+        toggle: function() {
+            state.isVisible ? hideHeader() : showHeader();
+        },
+        getState: function() {
+            return { ...state };
+        },
+        updateConfig: function(newConfig) {
+            Object.assign(config, newConfig);
+        }
+    };
+    
+})();

+ 116 - 0
style.css

@@ -11,4 +11,120 @@ Author URI: https://davidwindham.com
 
 
 .logo-letter {
 .logo-letter {
   font-size: 115%;
   font-size: 115%;
+}
+
+main {
+  margin-top: 180px !important;
+  background-color: rgb(217, 190, 190);
+}
+
+/* Auto-hide Navigation Styles */
+header,
+.srh-auto-hide-header,
+.wp-site-header,
+.wp-block-template-part[data-area="header"] {
+  position: fixed !important;
+  top: 0;
+  left: 0;
+  width: 100%;
+  z-index: 9999;
+  background: rgba(255, 255, 255, 0.95);
+  backdrop-filter: blur(10px);
+  -webkit-backdrop-filter: blur(10px);
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
+              opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
+              background-color 0.3s ease;
+  transform: translateY(0);
+  opacity: 1;
+}
+
+/* Hidden state when scrolling down */
+header.header-hidden,
+.srh-auto-hide-header.header-hidden,
+.wp-site-header.header-hidden,
+.wp-block-template-part[data-area="header"].header-hidden {
+  transform: translateY(-100%);
+  opacity: 0;
+}
+
+/* Visible state when scrolling up */
+header.header-visible,
+.srh-auto-hide-header.header-visible,
+.wp-site-header.header-visible,
+.wp-block-template-part[data-area="header"].header-visible {
+  transform: translateY(0);
+  opacity: 1;
+}
+
+/* Enhanced background when scrolled */
+header.header-scrolled,
+.srh-auto-hide-header.header-scrolled,
+.wp-site-header.header-scrolled,
+.wp-block-template-part[data-area="header"].header-scrolled {
+  background: rgba(255, 255, 255, 0.98);
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
+}
+
+/* Ensure content doesn't jump when header becomes fixed */
+body {
+  padding-top: 0;
+  transition: padding-top 0.3s ease;
+}
+
+body.header-offset {
+  padding-top: var(--header-height, 80px);
+}
+
+/* Navigation links hover effects */
+header a,
+.srh-auto-hide-header a,
+.wp-site-header a,
+.wp-block-template-part[data-area="header"] a {
+  transition: color 0.2s ease, transform 0.2s ease;
+}
+
+header a:hover,
+.srh-auto-hide-header a:hover,
+.wp-site-header a:hover,
+.wp-block-template-part[data-area="header"] a:hover {
+  transform: translateY(-1px);
+}
+
+/* Mobile menu adjustments */
+@media (max-width: 768px) {
+  header,
+  .srh-auto-hide-header,
+  .wp-site-header,
+  .wp-block-template-part[data-area="header"] {
+    background: rgba(255, 255, 255, 0.98);
+  }
+  
+  body.header-offset {
+    padding-top: var(--header-height, 60px);
+  }
+}
+
+/* Smooth scroll behavior for the whole page */
+html {
+  scroll-behavior: smooth;
+}
+
+/* Optional: Add a subtle animation when page loads */
+header,
+.srh-auto-hide-header,
+.wp-site-header,
+.wp-block-template-part[data-area="header"] {
+  animation: slideDown 0.5s ease-out;
+}
+
+@keyframes slideDown {
+  from {
+    transform: translateY(-100%);
+    opacity: 0;
+  }
+  to {
+    transform: translateY(0);
+    opacity: 1;
+  }
 }
 }