Skip to content

Instantly share code, notes, and snippets.

@joshuafredrickson
Last active February 3, 2022 17:59
Show Gist options
  • Save joshuafredrickson/54e8ea2fac070bac2b378fea353ee61f to your computer and use it in GitHub Desktop.
Save joshuafredrickson/54e8ea2fac070bac2b378fea353ee61f to your computer and use it in GitHub Desktop.
Megamenu in Blade using Alpine JS
@if (empty($navHeader) || ! $navHeader)
@php
return;
@endphp
@endif
<nav class="nav-primary" aria-label="Primary Navigation">
<ul class="flex flex-row -ml-4 text-sm menu lg:flex-grow">
@foreach ($navHeader as $item)
<li
class="block lg:inline-block mt-0 menu-item {{ $item->classes ?? '' }} {{ $item->children ? 'menu-item-has-children relative' : '' }}"
@if ($item->children)
x-data="dropdown()"
x-cloak
x-on:click="open"
@scroll.window="close"
@endif
>
<a
href="{{ $item->url }}"
target="{{ $item->target }}"
class="p-4 text-sm tracking-wider text-white uppercase transition-none border-none"
@if ($item->children)
:class="{
'active': show
}"
x-on:click.prevent
@endif
>
{!! $item->label !!}
</a>
@if ($item->children)
<div
class="absolute z-50 pt-4 ml-4 sub-menu transition-opacity {{ $item->mega_menu ? 'mega-menu' : '' }}"
x-show="isOpen({{ $item->defaultChild }})"
x-on:click.away="close"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
<div class="rounded shadow-md {{ $item->mega_menu ? 'flex' : '' }}">
<ul class="py-1 pl-4 pr-6 bg-gray-100 text-xs leading-tight rounded-l {{ $item->mega_menu ? 'flex-grow' : 'rounded-r' }}">
@foreach ($item->children as $child)
<li class="my-3 menu-item">
<a
href="{{ $child->url }}"
target="{{ $child->target }}"
class="font-semibold text-gray-700 uppercase whitespace-nowrap hover:text-red-400"
@if ($item->mega_menu)
:class="{
'text-red-500 show': activeChild === {{ $child->id }},
'text-gray-700': activeChild !== {{ $child->id }}
}"
{{-- x-on:click.prevent --}}
x-on:mouseenter="setActiveChild({{ $child->id }})"
@endif
>
{!! $child->label !!}
<span class="caret caret--opacity"><i class="far fa-chevron-right fa-sm"></i></span>
</a>
</li>
@endforeach
</ul>
@if ($item->mega_menu)
<div class="w-3/4 p-4 pl-6 bg-white rounded-r">
@foreach ($item->children as $child)
<div
class="flex h-full transition-opacity"
x-show="activeChild === {{ $child->id }}"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
>
@include('partials.mega-menu-' . $child->mega_menu_type)
</div>
@endforeach
</div>
@endif
</div>
</div>
@endif
</li>
@endforeach
</ul>
</nav>
<?php
namespace App\View\Composers;
use Roots\Acorn\View\Composer;
use Log1x\Navi\Facades\Navi;
use function App\get_parent;
use function acf_get_attachment;
class NavHeader extends Composer
{
use \App\Concerns\NavOverride;
/**
* List of views served by this composer.
*
* @var array
*/
protected static $views = [
'partials.header',
'partials.nav-mobile',
];
/**
* Data to be passed to view before rendering.
*
* @return array
*/
public function with()
{
$this->setNav();
return [
'navHeader' => $this->navHeader(),
'navOverride' => $this->navOverride,
'navLogo' => $this->navLogo(),
];
}
/**
* Returns a log1x/navi object for the primary menu
*
* @return object
*/
public function navHeader()
{
// Is it empty?
if (Navi::build($this->navMenu)->isEmpty()) {
return false;
}
// Build it.
$nav = Navi::build($this->navMenu)->toArray();
collect($nav)->map(function ($navItem) {
$navItem->mega_menu = get_field('mega_menu', $navItem->id);
if (! $navItem->children) {
return $navItem;
}
$navItem->defaultChild = current($navItem->children)->id;
/**
* Get children ACF
*/
collect($navItem->children)->map(function ($child) {
$child->mega_menu_type = get_field('mega_menu_type', $child->id);
switch ($child->mega_menu_type) {
case 'description':
$child->mega_menu_description = get_field('mega_menu_description', $child->id);
if (! $child->mega_menu_description['image']) {
$child->mega_menu_description['image'] = null;
}
break;
case 'links':
$child->mega_menu_links = get_field('mega_menu_links', $child->id);
break;
case 'link':
default:
break;
}
return $child;
});
return $navItem;
});
return $nav;
}
/**
* Sets the nav logo
*
* @return array
*/
public function navLogo()
{
if (! $this->navOverride) {
return [];
}
global $post;
// Check for parent menu override first
// Using get_post_meta here due to issues with get_field and previewing posts
$logoSvg = get_post_meta(get_parent(), 'icon', true) ?:
get_post_meta($post->ID, 'icon', true) ?:
false;
$logoPermalink = get_the_permalink(get_parent()) ?:
get_the_permalink($post->ID) ?:
home_url('/');
$logoTitle = get_the_title(get_parent()) ?:
get_the_title() ?:
'';
return [
'logo' => acf_get_attachment($logoSvg),
'title' => $logoTitle,
'permalink' => $logoPermalink,
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment