Componente para Sub-Menu * Laravel/Breeze * Tailwind

Cuando instalas Laravel/Breeze la plantilla del menú de navegación tiene el menú principal a la izquierda y un dropdown a la derecha, sin embargo no hay ningún componente dentro del menú principal que se pueda usar para un sub-menú.

El paquete Laravel/Breeze agrega plantillas específicas para el menú y además usa Tailwind, algo que es muy nuevo para mí, y luego de tener unos problemas al momento de instalar Laravel/Breeze y conflicto con las dependencias, finalmente pude trabajar en otras cosas, hasta que llegué a la parte del menú.

El componente del menú tiene un dropdown que muestra acciones al usuario como cerrar la sesión.

Al lado derecho está el dropdown disponible

Para el proyecto que estoy trabajando necesito tener un menú principal con varias opciones:

Menú que necesito

Componentes

Siguiendo la misma lógica de los componentes originales procedí a crear dos componentes para versión móvil y de escritorio.

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>

Estilos

Algo de CSS para ajustar la posición y detalles del elemento.

.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;
    }
}

Actualizar el componente

Por último actualicé el archivo de la plantilla correspondiente al componte del menú de navegación.

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>

Resultado Final

Image by Free-Photos from Pixabay

Compartir

Leave a Reply

Your email address will not be published. Required fields are marked *