Currently, I'm working on a project using Laravel, I haven't used Laravel since version 5, I think, also I stopped programming for about a year for different personal reasons.
The thing is that a lot of things have changed and one of them is that now Laravel has this package to manage the authentication process: Laravel/Breeze.
Puedes leer la versión en Español en mi blog.
I had some issues at the beginning because I didn't have the latest version of PHP, but after I solved them I was able to focus on the next steps. Tailwind is something really new for me and Laravel/Breeze is working with templates and styles using that library, but one thing that is missing is the "sub-menu" for the main links.
The menu has the option to have a drop-down for the user actions on the right side:
For the project I'm working on, I need to have a sub-menu for some of the main menu items:
Components
Following the same logic of the original components, I've created two components:
nav-link-parent.blade.php
@props(['active'])
@php
$classes = ($active ?? false)
? 'parent-nav inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-semibold leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out cursor-pointer relative'
: 'parent-nav inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-semibold leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out cursor-pointer relative';
@endphp
<div x-data="{ open: false }" @click.away="open = false" @close.stop="open = false" @click="open = ! open" {{ $attributes->merge(['class' => $classes]) }} >
<div>
{{ $name }}
<div class="ml-1 inline-block relative top-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</div>
<div class="children border border-gray-300"
x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95">
{{ $children }}
</div>
</div>
responsive-nav-link-parent.blade.php
@props(['active'])
@php
$classes = ($active ?? false)
? 'parent-nav inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-semibold leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'parent-nav inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-semibold leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
@endphp
@props(['active'])
@php
$classes = ($active ?? false)
? 'parent-nav block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-semibold text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
: 'parent-nav block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-semibold text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
@endphp
<div x-data="{ open: false }" @click.away="open = false" @close.stop="open = false" @click="open = ! open" {{ $attributes->merge(['class' => $classes]) }} >
<div>
{{ $name }}
<div class="ml-1 inline-block relative top-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</div>
</div>
<div class="children border border-gray-300 mt-3"
x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95">
{{ $children }}
</div>
</div>
Style
Some CSS to set the right position for the elements.
app.css
.children {
background: #fff;
}
.children a,
.children .separator {
display: block;
margin: 5px 0px;
padding: 5px 10px;
}
.children .separator {
border-top-width: 2px;
}
.children a:hover {
color: #818cf8;
}
@media (min-width: 768px) {
.children {
position: absolute;
width: 155px;
top: 70px;
}
}
Update the Navigation layout
And last I've updated the navigation layout and have added two slots: name and children
navigation.blade.php
...
<x-nav-link-parent :href="'#'" :active="request()->routeIs('padron.')">
<x-slot name="name">Option A</x-slot>
<x-slot name="children">
<a href="#">Item A</a>
<span class="separator"></span>
<a href="#">Item B</a>
<a href="#">Item C</a>
<span class="separator"></span>
<a href="#">Item D</a>
</x-slot>
</x-nav-link-parent>
...
<x-responsive-nav-link-parent :href="'#'" :active="request()->routeIs('padron.')">
<x-slot name="name">Padrón</x-slot>
<x-slot name="children">
<a href="#">Buscador</a>
<span class="separator"></span>
<a href="#">Centros de votacion</a>
<a href="#">Juntas</a>
<span class="separator"></span>
<a href="#">Cartografia</a>
</x-slot>
</x-responsive-nav-link-parent>
Thanks for sharing. I wanted to implement something like this using Jetstream. Currently, it appears the parent is not clickable as a link. I can see some advantages to this but also some limitations. Ideally, I would think that clicking on the arrow would allow the options to appear but clicking on the word would take you to the parent link.