Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Active Laravel Package

arcanedev/laravel-active

Laravel Active provides helpers to detect the current route or URL and mark matching navigation links, menus, and tabs as active, with support for patterns and exclusions. A small utility package by ArcaneDev for building state-aware navigation in Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer; Laravel's package discovery registers the service provider automatically:

composer require arcanedev/laravel-active

If you want to change the CSS class it emits (default is active), publish the config:

php artisan vendor:publish
# pick the LaravelActive provider from the list

Then use the global active() helper anywhere a class string is expected — the canonical first use case is a navigation link:

<a href="{{ route('users.index') }}" class="{{ active('users.index') }}">
    Users
</a>

When the current route matches users.index, this renders class="active"; otherwise the class attribute is empty. That single behavior is the whole point of the package, so it pays off in layouts with sidebars, top navs, and tab bars.

Where to look first:

  1. The README's usage block — it is the real documentation for a package this size.
  2. config/laravel-active.php after publishing — the only knob most projects touch.
  3. The helper/facade source (src/) — it's small enough to read in a few minutes and tells you exactly which patterns are supported.

Start by wiring it into one nav partial, not every link in the app. Once the partial works, expand.

Implementation Patterns

Route-name matching is the primary path. Match a single name, an array of names, or a wildcard prefix:

{{-- single --}}
<a href="{{ route('dashboard') }}" class="{{ active('dashboard') }}">Dashboard</a>

{{-- a resource section: index, create, edit, show all light up together --}}
<a href="{{ route('users.index') }}" class="{{ active(['users.index', 'users.create', 'users.edit']) }}">Users</a>

{{-- wildcard: any route whose name starts with "admin." --}}
<a href="{{ route('admin.dashboard') }}" class="{{ active('admin.*') }}">Admin</a>

The array form is what you want for "section" highlighting where the parent item should stay active while the user is on a child screen.

Path matching for un-named routes. Not every link in a legacy app is a named route, and static/marketing pages often aren't. The package's second capability is matching the current request path, which is its main differentiator over a pure route-name helper:

<a href="/about" class="{{ active('about') }}">About</a>
<a href="/blog" class="{{ active('blog/*') }}">Blog</a>

Keep route-name matching for application screens and path matching for content pages; mixing the two in one nav is fine because the helper is consistent about returning a class string.

Centralize menu definitions. Avoid repeating active() calls across templates. Drive the nav from a config array and let one partial do the matching:

// config/navigation.php
return [
    ['label' => 'Dashboard', 'route' => 'dashboard', 'match' => 'dashboard'],
    ['label' => 'Users',     'route' => 'users.index', 'match' => ['users.*']],
    ['label' => 'Settings',  'route' => 'settings.edit', 'match' => ['settings.*']],
];
@foreach (config('navigation') as $item)
    <a href="{{ route($item['route']) }}"
       class="{{ active($item['match']) }}"
       @if (active($item['match'])) aria-current="page" @endif>
        {{ $item['label'] }}
    </a>
@endforeach

Note the second active() call for aria-current — the helper returns a string, not a boolean, so use it directly in the attribute when you need truthiness.

Wrap it in a Blade component. Once you have more than a handful of links, a <x-nav-link> component keeps templates clean and gives you one place to change the active class, add aria-current, or swap the helper out later:

{{-- resources/views/components/nav-link.blade.php --}}
@props(['href', 'match'])
@php $isActive = active($match) !== ''; @endphp
<a href="{{ $href }}"
   {{ $attributes->class(['active' => $isActive]) }}
   @if ($isActive) aria-current="page" @endif>
    {{ $slot }}
</a>

This is also the seam you use if you later decide to replace the package with Laravel's native request()->routeIs() / request()->is() — you change the component, not every template.

Combine with authorization/state. Active detection is presentation only; don't let it decide whether a link should exist. Gate the link with @can and let active() decorate it.

Test it like any other view concern. Feature-test the rendered class rather than the helper in isolation:

$this->get(route('users.index'))->assertSee('class="active"', false);

Gotchas and Tips

  • It returns a string, not a boolean. active() yields 'active' or an empty string. That means @if (active(...)) works, but active(...) === true never will, and an unmatched link gives you class="" rather than no attribute. If your CSS or HTML validation cares, use the ternary/!== '' pattern shown above.
  • Route names must match exactly. active('users.index') will not match users.index.edit — use active('users.*'). Conversely, wildcards are greedy: admin.* also matches admin.reports.export, which is usually what you want but can surprise you on nested sections.
  • Query strings and trailing slashes are the classic path-matching failure. /blog?page=2 and /blog/ may not match a pattern written as blog. Normalize your patterns and test with real URLs, including localized prefixes (/en/blog) if you use mcamara/laravel-localization or similar.
  • Route parameters are invisible to name matching but fatal to naive path matching. users/42/edit needs users/*/edit, not users/edit. Prefer route names anywhere a model is bound.
  • Check for helper collisions. active() is a global function. If another package or your own helpers.php defines it, loading order decides which wins. A quick function_exists('active') check in a scratch route saves an hour of confusion.
  • This package is quiet — last release was February 2022. It's tiny and dependency-light, so it generally keeps working, but verify the service provider boots on your Laravel version before building a nav system on it. If it breaks on a newer major, the fallback is two lines of native Laravel: request()->routeIs('users.*') and request()->is('blog/*'). Keep that in your back pocket.
  • Clear config cache after publishing or editing config. php artisan config:clear (and config:cache in deploy scripts) — a stale cached config is the usual reason a changed active class "doesn't apply."
  • Facade vs helper. If you reference Active:: and get a class-not-found, the alias isn't registered in your app config; either add it or stick to the global helper, which is what most codebases use anyway.
  • Extension points are thin by design. The config class name and the Blade component wrapper are the two places to customize. Anything more elaborate (e.g., matching based on a route parameter value, or marking a parent active for a completely different URL tree) should live in your own helper that calls active() internally — don't fork the package for it.
  • Debugging tip: when a link won't light up, dump the raw inputs first — dd(request()->route()?->getName(), request()->path()) — and compare against your pattern. Nine times out of ten the mismatch is a name typo or an unexpected path prefix, not the package.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package