A visual mega menu builder for Filament 5 with drag-and-drop nesting, ADA-compliant frontend rendering, and Layup-powered mega menu panels.
- PHP 8.3+
- Laravel 12 or 13
- Filament 5
- crumbls/layup ^1.0
composer require crumbls/navcraftRun the migrations:
php artisan migrateRegister the plugin in your Filament panel provider:
use Crumbls\NavCraft\NavCraftPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
NavCraftPlugin::make(),
]);
}Publish the config (optional):
php artisan vendor:publish --tag=navcraft-configPublish the views for customization (optional):
php artisan vendor:publish --tag=navcraft-viewsNavigate to Menus in your Filament panel. Create a menu with a name, slug, and status.
On the edit page, the tree builder lets you:
- Add items -- click the dashed "Add item" button at the bottom
- Edit items -- click the pencil icon to open a slide-over with label, type, URL/route, appearance settings, and mega menu content
- Inline rename -- double-click any label to rename in place
- Drag and drop -- grab the handle to reorder or nest items under other items
- Duplicate -- click the copy icon to deep-clone an item and its children
- Delete -- click the trash icon for a confirmation dialog
- Collapse/expand -- click the chevron on items with children
- Search -- filter items by label using the search box
- Undo/redo -- toolbar buttons or use the history to step back
| Type | Description | Supports Children |
|---|---|---|
| URL | Absolute or relative link (/about, https://example.com) |
Yes |
| Route | Named Laravel route with parameter support | Yes |
| Mega Menu | Layup page builder content panel | No |
The edit form is organized into two tabs:
Content -- label, type, URL or route (with auto-detected parameters), open-in-new-tab toggle, and Layup builder for mega menus.
Appearance -- CSS classes and icon (Heroicon name).
@navCraftScripts
@navcraft('main-navigation')@navCraftScripts
<x-navcraft-menu slug="main-navigation" label="Main Navigation" /><x-navcraft-breadcrumb slug="main-navigation" />Automatically generates breadcrumbs based on the current URL matched against the menu tree.
@navCraftScripts must be included once on the page (before </body>). It loads the Alpine.js navigation component and Layup scripts for mega menu content.
Store settings in the menu's settings JSON column to configure behavior:
$menu->update(['settings' => [
'sticky' => true, // Sticky nav on scroll
'theme' => 'pill', // 'minimal', 'bordered', 'pill', 'underline'
'hover_mode' => 'hover', // 'click' or 'hover' for desktop dropdowns
'nav_pattern' => 'disclosure', // 'disclosure' (site nav, default) or 'menubar'
]]);These are also editable per menu in the Filament admin under Display.
Every color in the front-end views is driven by a CSS custom property, so you
can rebrand the whole menu without publishing or forking the Blade views.
Override any of these in your own stylesheet at :root (your unlayered rules
win over NavCraft's @layer defaults):
:root {
--nc-fg: #374151; /* default text */
--nc-fg-strong: #111827; /* hover / heading-strong text */
--nc-fg-muted: #6b7280; /* secondary text */
--nc-heading: #6b7280; /* mega-menu column headings */
--nc-accent: #2563eb; /* active item, chevron, CTA */
--nc-bg: #ffffff; /* nav bar background */
--nc-panel: #ffffff; /* dropdown / mega-panel background */
--nc-panel-soft: #f9fafb; /* featured-card background */
--nc-border: #e5e7eb; /* borders */
--nc-hover-bg: #f9fafb; /* item hover background */
--nc-ring: rgb(59 130 246 / 0.5); /* focus ring */
}Dark mode is handled by the same variables under .dark.
NavCraft's views use Tailwind utilities. Tell Tailwind to scan them by adding this to your CSS entrypoint (unless you publish the views into your app):
@source '../../vendor/crumbls/navcraft/resources/views';nav_pattern selects the ARIA pattern:
disclosure(default) — the WAI-ARIA APG pattern for site navigation: top-level buttons exposearia-expanded/aria-controls, nomenubarroles. Recommended for website headers.menubar— application-stylerole="menubar"/menuitem. Use only for true app menus, where users expect arrow-key roving focus.
Any mega item can show a featured card next to its auto-generated link
columns — set a title (and optional body / CTA) under the item's Content
tab, or in code via settings.featured:
$item->update(['settings' => ['featured' => [
'title' => 'Free admission, always',
'body' => 'Step into the story of your town.',
'cta_label' => 'Plan a visit',
'cta_url' => '/visit',
]]]);When the item has Layup content, that renders instead.
| Theme | Description |
|---|---|
minimal |
Clean, no decoration (default) |
bordered |
Border on hover and active items |
pill |
Background fill on hover and active |
underline |
Bottom border indicator |
The rendered navigation follows WCAG 2.1 AA:
<nav>landmark witharia-label- Disclosure pattern by default (plain list + buttons); optional
menubar/menuitemstructure vianav_patternfor app-style menus aria-haspopup="true"and dynamicaria-expandedon parent itemsaria-current="page"on the link matching the current URL- Active trail highlighting through the entire parent chain
- Keyboard navigation: Tab, Enter/Space to toggle, Escape to close, Arrow keys
role="region"witharia-labelon mega menu panels- External links:
target="_blank"withrel="noopener noreferrer"and sr-only "(opens in new window)" - Visible focus indicators on all interactive elements
- Mobile: hamburger with
aria-expandedandaria-controls, accordion submenus
The navigation automatically switches to a hamburger menu below the lg breakpoint. Submenus open as accordions. Mega menus render their full Layup content inline when expanded.
The MenuRenderer caches rendered HTML for 1 hour, keyed by slug and updated_at timestamp. Disable caching:
MenuRenderer::fromSlug('main-navigation', cached: false)->toHtml();| Column | Type | Description |
|---|---|---|
name |
string | Display name |
slug |
string | Unique identifier for rendering |
description |
string | Optional description |
status |
string | draft or published |
settings |
json | Theme, sticky, hover mode, etc. |
| Column | Type | Description |
|---|---|---|
menu_id |
FK | Parent menu |
parent_id |
FK | Parent item (nullable, self-referencing) |
type |
string | url, route, or mega |
label |
string | Display text |
url |
string | URL for url type |
route |
string | Route name for route type |
target |
string | _self or _blank |
order |
integer | Sort position |
css_class |
string | Custom CSS classes |
icon |
string | Heroicon component name |
content |
json | Layup content for mega type |
settings |
json | Route params, etc. |
cd packages/navcraft
vendor/bin/pest52 tests covering models, tree building, rendering, service provider, and deep cloning.
See CONTRIBUTING.md.
See VISION.md for the roadmap.
MIT -- see LICENSE.md