Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Rretzko's avatar
Level 15

Livewire popover doesn't close when clicked

Hi - I'm following the Livewire 3 screencast on Product Filtering. The popover button displays but is open by default and does not close when clicked. Any help on this is appreciated. Popover code

<x-popover>
    <x-popover.button class="flex items-center gap-2 rounded-lg border pl-3 pr-2 py-1 text-gray-600 text-sm">
            <div>All Products</div>
            <x-heroicons.chevronDown />
     </x-popover.button>

     <x-popover.panel class="border border-gray-100 shadow-xl z-10 w-64 overflow-hidden">
             <div class="flex flex-col divide-y divide-gray-100">
                     <label class="flex items-center px-3 py-2 gap-2 cursor-pointer hover:bg-gray-100">
                         <input value=""  type="checkbox" class="rounded border-gray-300">
                         <div class="text-sm text-gray-800">Name</div>
                     </label>
             </div>
      </x-popover.panel>
</x-popover>

popover files

// x-popover.button
<button type="button"  id="popoverButton" x-popover:button {{ $attributes }}>
    {{ $slot }}
</button>

// x-popover.close
div x-on:click="$popover.close()">
    {{ $slot }}
</div>

// x-popover.index
<div x-data x-popover class="relative" {{ $attributes }}>
    {{ $slot }}
</div>

// x-panel
@props(['position' => 'bottom-center'])

<div
    x-popover:panel
    x-cloak
    x-transition.out.opacity
    x-anchor.{{ $position }}.offset.1="document.getElementById('popoverButton')"
    {{ $attributes->merge([
        'class' => 'absolute left-0 mt-2 bg-white rounded-md',
    ]) }}
>
    {{ $slot }}
</div>
0 likes
1 reply
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

It seems like you're trying to implement a popover component with Livewire and Alpine.js. The popover should open when the button is clicked and close when clicked again or when clicking outside of the popover. To achieve this, you need to set up Alpine.js to manage the popover's visibility state.

Here's a solution that should help you get the popover working as expected:

<!-- x-popover.index -->
<div x-data="{ open: false }" @click.away="open = false" class="relative" {{ $attributes }}>
    <!-- Use @click to toggle the 'open' state -->
    <x-popover.button @click="open = !open" class="flex items-center gap-2 rounded-lg border pl-3 pr-2 py-1 text-gray-600 text-sm">
        <div>All Products</div>
        <x-heroicons.chevronDown />
    </x-popover.button>

    <!-- Use x-show to control the visibility of the panel based on the 'open' state -->
    <x-popover.panel x-show="open" class="border border-gray-100 shadow-xl z-10 w-64 overflow-hidden">
        <div class="flex flex-col divide-y divide-gray-100">
            <label class="flex items-center px-3 py-2 gap-2 cursor-pointer hover:bg-gray-100">
                <input value="" type="checkbox" class="rounded border-gray-300">
                <div class="text-sm text-gray-800">Name</div>
            </label>
        </div>
    </x-popover.panel>
</div>

Make sure you have Alpine.js included in your project for this to work. The x-data directive initializes the Alpine component with a reactive open property. The @click.away directive listens for click events outside of the component to close the popover. The @click directive on the button toggles the open state, and the x-show directive on the panel uses this state to show or hide the popover.

If you're still having trouble, ensure that you don't have any JavaScript errors in your console and that Alpine.js is properly initialized. Also, check that you're using the correct version of Alpine.js that supports the directives you're using.

Please or to participate in this conversation.