April 23rd, 2023
How do you make a modal with search input with Alpine.js, Tailwind, and some nice transitions on enter and leave?
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.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>