Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Bootstrap Hover Dropdown Laravel Package

cwspear/bootstrap-hover-dropdown

jQuery plugin that brings Bootstrap dropdowns to life on hover. Adds configurable delay, menu close on mouseout, and touch-friendly behavior while keeping Bootstrap’s markup and styles. Useful for navbars and multi-level menus.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer

    composer require cwspear/bootstrap-hover-dropdown
    

    or via npm (if using the JS bundle):

    npm install bootstrap-hover-dropdown
    
  2. Include CSS/JS

    • Laravel Mix/Webpack: Import the JS in your entry file:
      import 'bootstrap-hover-dropdown';
      
    • Standalone: Add to your Blade template:
      <link href="{{ asset('vendor/bootstrap-hover-dropdown/css/bootstrap-hover-dropdown.css') }}" rel="stylesheet">
      <script src="{{ asset('vendor/bootstrap-hover-dropdown/js/bootstrap-hover-dropdown.js') }}"></script>
      
  3. Basic Usage Convert a standard Bootstrap dropdown to hover-triggered:

    <div class="dropdown">
      <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Hover Me
      </button>
      <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
        <a class="dropdown-item" href="#">Action</a>
        <a class="dropdown-item" href="#">Another action</a>
      </div>
    </div>
    

    No extra JS needed—the package auto-initializes on pages with Bootstrap 4/5.


First Use Case: Admin Dashboard

Replace click-triggered dropdowns (e.g., user profile menus) with hover for faster navigation:

<div class="dropdown d-inline-block ms-3">
  <button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
    <i class="fas fa-user-circle"></i>
  </button>
  <div class="dropdown-menu dropdown-menu-right">
    <a class="dropdown-item" href="/profile">Profile</a>
    <a class="dropdown-item" href="/settings">Settings</a>
    <div class="dropdown-divider"></div>
    <a class="dropdown-item" href="/logout">Logout</a>
  </div>
</div>

Implementation Patterns

1. Dynamic Initialization

  • Lazy Loading: Use data-hover-dropdown to opt-in/out per dropdown:
    <div class="dropdown" data-hover-dropdown="true">...</div>
    
  • Programmatic Control: Initialize manually in JS:
    $(document).ready(function() {
      $('.dropdown').hoverDropdown(); // jQuery syntax
      // OR
      new HoverDropdown(); // Vanilla JS (if using ES6 module)
    });
    

2. Integration with Laravel Blade

  • Dynamic Classes: Toggle hover behavior based on user role:
    <div class="dropdown {{ auth()->user()->is_admin ? 'data-hover-dropdown' : '' }}">
      <!-- Dropdown content -->
    </div>
    
  • Partial Views: Reuse dropdowns in components:
    @component('components.dropdown', [
        'items' => ['Dashboard', 'Reports', 'Logout'],
        'hover' => true
    ])@endcomponent
    

3. Customizing Delay & Behavior

  • Config via Data Attributes:
    <div class="dropdown"
         data-hover-dropdown
         data-hover-dropdown-delay="300"  <!-- 300ms delay -->
         data-hover-dropdown-auto-close="false"> <!-- Persist on hover -->
    </div>
    
  • Global Config: Override defaults in JS:
    $.fn.hoverDropdown.defaults = {
      delay: 200,
      autoClose: true
    };
    

4. Mobile-First Approach

  • Media Query Toggle: Disable hover on mobile:
    <div class="dropdown {{ request()->isMobile() ? 'data-hover-dropdown="false"' : '' }}">
    
    Helper in app/Helpers.php:
    if (!function_exists('isMobile')) {
        function isMobile() {
            return request()->userAgent() === 'mobile';
        }
    }
    

5. Testing

  • Unit Tests: Mock dropdown initialization:
    public function testHoverDropdownInitializes()
    {
        $html = '<div class="dropdown" data-hover-dropdown></div>';
        $this->view->make('partials.dropdown', ['html' => $html]);
        $this->assertContains('hoverDropdown', $this->view->renderSection('scripts'));
    }
    
  • Feature Tests: Simulate hover events:
    it('opens dropdown on hover', () => {
        const dropdown = document.querySelector('.dropdown');
        fireEvent.mouseEnter(dropdown);
        expect(dropdown.querySelector('.dropdown-menu')).toBeVisible();
    });
    

Gotchas and Tips

Pitfalls

  1. Bootstrap Version Conflicts

    • Issue: Package may not work with Bootstrap 3 or custom builds missing dropdown JS.
    • Fix: Ensure bootstrap@4.x or bootstrap@5.x is included after this package.
      <!-- Correct order -->
      <link href="css/bootstrap.css" rel="stylesheet">
      <link href="css/bootstrap-hover-dropdown.css" rel="stylesheet">
      
  2. CSS Specificity Wars

    • Issue: Dropdown menus may not appear due to conflicting styles.
    • Fix: Use !important sparingly; target the package’s classes:
      .dropdown-menu {
          z-index: 1050 !important; /* Match Bootstrap’s default */
      }
      
  3. Double Initialization

    • Issue: Calling hoverDropdown() twice on the same element breaks functionality.
    • Fix: Use data-hover-dropdown or check for existing instances:
      if (!$('.dropdown').data('hoverDropdown')) {
          $('.dropdown').hoverDropdown();
      }
      
  4. Touch Devices

    • Issue: Hover may trigger unintentionally on touchscreens.
    • Fix: Combine with touch detection:
      if ('ontouchstart' in window) {
          $('.dropdown').removeData('hoverDropdown');
      }
      

Debugging Tips

  • Check Initialization: Verify the package runs:
    console.log($.fn.hoverDropdown); // Should log the function
    
  • Inspect Events: Listen for hover events:
    $('.dropdown').on('mouseenter', () => console.log('Hovered!'));
    
  • Disable Auto-Initialization: For testing, override the global init:
    $.fn.hoverDropdown.defaults.autoInit = false;
    

Extension Points

  1. Custom Animations Override the default fade/slide with CSS transitions:

    .dropdown-menu {
        transition: opacity 0.2s, transform 0.2s;
        opacity: 0;
        transform: translateY(10px);
    }
    .dropdown-menu.show {
        opacity: 1;
        transform: translateY(0);
    }
    
  2. Server-Side Rendering (SSR) For Laravel Vapor/Edge, ensure JS runs after hydration:

    document.addEventListener('DOMContentLoaded', () => {
        new HoverDropdown();
    });
    
  3. Accessibility Add ARIA attributes dynamically:

    $.fn.hoverDropdown = function() {
        this.attr('aria-haspopup', 'true');
        // ... rest of the plugin
    };
    
  4. Laravel Mix Optimization Extract the package’s JS into a separate chunk:

    // webpack.mix.js
    mix.js('resources/js/bootstrap-hover-dropdown.js', 'public/js')
         .extract(['bootstrap-hover-dropdown']);
    

Pro Tips

  • Performance: Use data-hover-dropdown="false" on dropdowns that shouldn’t hover (e.g., mobile-only menus).
  • Theming: Extend the package’s SCSS variables:
    // resources/scss/custom.scss
    @import '~bootstrap-hover-dropdown/scss/bootstrap-hover-dropdown';
    
    $hover-dropdown-bg: #343a40; // Dark theme
    $hover-dropdown-border-color: darken($hover-dropdown-bg, 5%);
    
  • Laravel Livewire: Reinitialize after updates:
    document.addEventListener('livewire:init', () => {
        new HoverDropdown();
    });
    
  • Dark Mode: Toggle classes dynamically:
    if (localStorage.getItem('dark-mode')) {
        $('.dropdown-menu').addClass('bg-dark text-light');
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
bugban/symfony
beyonder-capi/workflow-extensions-bundle
beyonder-capi/job-queue-bundle
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin