Search Modal with Alpine.js, Tailwind and Transitions

April 23rd, 2023

How do you make a modal with search input with Alpine.js, Tailwind, and some nice transitions on enter and leave?

Search form in navigation menu

menu.blade.php

  • define alpine properties in x-data="{ }", showSearchInput is set to false at start

  • x-cloak

  • form action="/search" goes to route /search

  • @csrf token

  • <x-search-modal> blade component, everything between that goes to slot

  • toggle showSearchInput on click to svg magnifying glass

1<div x-data="{showSearchInput: false}" x-cloak>
2 {{-- ... --}}
3 
4 {{-- SEARCH --}}
5 <form action="/search" class="flex gap-1 items-center">
6 @csrf
7 <x-search-modal>
8 <input name="q" type="text" class="rounded-lg text-3xl font-semibold tracking-wide text-cyan-500 focus:border-cyan-400 shadow-xl border-4 px-4 py-2 w-full" @update="showSearchInput = false">
9 </x-search-modal>
10 <svg @click="showSearchInput = !showSearchInput" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor" class="text-cyan-300 w-6 h-6">
11 <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
12 </svg>
13 </form>

Search modal blade component with AlpineJs transitions

search-modal.blade.php

  • show search modal only when showSearchInput is set to true

  • close modal on keydown 'Escape': set showSearchInput to false

  • transition modal: from opacity 0% to opacity 100%, duration of transition 500ms

  • overlay bg-neutral-500/50: bg-neutral-500 with opacity 50%

  • transition slot (all inputs): duration 300ms

    • from opacity 0% to opacity 100% and

    • translate from above down: translate-y-4 to translate-y-0

1<div x-show="showSearchInput"
2 x-trap="showSearchInput"
3 @keydown.window.esc="showSearchInput = false"
4 x-transition:enter="transition ease-out duration-500"
5 x-transition:enter-start="opacity-0"
6 x-transition:enter-end="opacity-100"
7 x-transition:leave="transition ease-in duration-500"
8 x-transition:leave-start="opacity-100"
9 x-transition:leave-end="opacity-0"
10 class="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true"
11>
12 {{-- overlay --}}
13 <div @click="showSearchInput = false" class="fixed inset-0 bg-neutral-500/50 transition-opacity"></div>
14 
15 <div x-show="showSearchInput"
16 x-transition:enter="transition ease-out duration-300"
17 x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
18 x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
19 x-transition:leave="transition ease-in duration-300"
20 x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
21 x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
22 class="fixed inset-0 z-10 overflow-y-auto top-32 w-3/4 xl:w-1/2 mx-auto"
23 >
24 
25 {{ $slot }}
26 
27 </div>
28</div>

Related Posts