From 2cb89efc88e7ba1f541384204913e5e58d3c0454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gon=C3=A7alves?= Date: Sat, 2 Aug 2025 22:31:40 -0300 Subject: [PATCH 1/4] feat(panels): add support for customizable topbar Livewire component Introduce the ability to set a customizable Livewire component for the topbar via `topbarLivewireComponent`. Updated `HasTopbar` trait to handle dynamic registration of the topbar component, providing greater flexibility in panel customization. --- .../src/Panel/Concerns/HasComponents.php | 2 +- .../panels/src/Panel/Concerns/HasTopbar.php | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/panels/src/Panel/Concerns/HasComponents.php b/packages/panels/src/Panel/Concerns/HasComponents.php index cff4409358..4d0f22b743 100644 --- a/packages/panels/src/Panel/Concerns/HasComponents.php +++ b/packages/panels/src/Panel/Concerns/HasComponents.php @@ -493,7 +493,7 @@ trait HasComponents $this->queueLivewireComponentForRegistration(Notifications::class); $this->queueLivewireComponentForRegistration(Sidebar::class); $this->queueLivewireComponentForRegistration(SimpleUserMenu::class); - $this->queueLivewireComponentForRegistration(Topbar::class); + $this->queueLivewireComponentForRegistration($this->getTopbarLivewireComponent()); if ($this->hasEmailVerification() && is_subclass_of($emailVerificationPromptRouteAction = $this->getEmailVerificationPromptRouteAction(), Component::class)) { $this->queueLivewireComponentForRegistration($emailVerificationPromptRouteAction); diff --git a/packages/panels/src/Panel/Concerns/HasTopbar.php b/packages/panels/src/Panel/Concerns/HasTopbar.php index b7d8428db2..c44b26a3ac 100644 --- a/packages/panels/src/Panel/Concerns/HasTopbar.php +++ b/packages/panels/src/Panel/Concerns/HasTopbar.php @@ -3,14 +3,29 @@ namespace Filament\Panel\Concerns; use Closure; +use Filament\Livewire\Topbar; +use Livewire\Component; trait HasTopbar { protected bool | Closure $hasTopbar = true; - public function topbar(bool | Closure $condition = true): static + protected string | Closure | null $topbarLivewireComponent = null; + + public function topbar(bool | Closure $condition = true, string | Closure | null $livewireComponent = null): static { $this->hasTopbar = $condition; + $this->topbarLivewireComponent($livewireComponent); + + return $this; + } + + /** + * @param class-string | Closure | null $component + */ + public function topbarLivewireComponent(string | Closure | null $component): static + { + $this->topbarLivewireComponent = $component; return $this; } @@ -19,4 +34,12 @@ trait HasTopbar { return (bool) $this->evaluate($this->hasTopbar); } + + /** + * @return class-string + */ + public function getTopbarLivewireComponent(): string + { + return $this->evaluate($this->topbarLivewireComponent) ?? Topbar::class; + } } From 354dede23b76e3a02435bfbb03a6ef1c8d176ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gon=C3=A7alves?= Date: Sat, 2 Aug 2025 22:33:42 -0300 Subject: [PATCH 2/4] refactor(panels): remove unused Topbar Livewire component import Clean up unused `Topbar` import in `HasComponents` to streamline codebase. --- packages/panels/src/Panel/Concerns/HasComponents.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/panels/src/Panel/Concerns/HasComponents.php b/packages/panels/src/Panel/Concerns/HasComponents.php index 4d0f22b743..27880ff2d5 100644 --- a/packages/panels/src/Panel/Concerns/HasComponents.php +++ b/packages/panels/src/Panel/Concerns/HasComponents.php @@ -9,7 +9,6 @@ use Filament\Livewire\GlobalSearch; use Filament\Livewire\Notifications; use Filament\Livewire\Sidebar; use Filament\Livewire\SimpleUserMenu; -use Filament\Livewire\Topbar; use Filament\Pages\Page; use Filament\Resources\Pages\Page as ResourcePage; use Filament\Resources\RelationManagers\RelationGroup; From 13e9c5fc051106421e364bf27ec86fa543f9f26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gon=C3=A7alves?= Date: Sat, 2 Aug 2025 23:25:11 -0300 Subject: [PATCH 3/4] refactor(panels): use dynamic topbar livewire component Update to dynamically fetch the topbar Livewire component via `FilamentManager::getTopbarLivewireComponent()` instead of hardcoding the class reference, improving flexibility for topbar customization. --- .../panels/resources/views/components/layout/index.blade.php | 2 +- packages/panels/src/FilamentManager.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/panels/resources/views/components/layout/index.blade.php b/packages/panels/resources/views/components/layout/index.blade.php index 7887dab856..f957e416ab 100644 --- a/packages/panels/resources/views/components/layout/index.blade.php +++ b/packages/panels/resources/views/components/layout/index.blade.php @@ -28,7 +28,7 @@ @if ($hasTopbar) {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_BEFORE, scopes: $renderHookScopes) }} - @livewire(\Filament\Livewire\Topbar::class) + @livewire(filament()->getTopbarLivewireComponent()) {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_AFTER, scopes: $renderHookScopes) }} @endif diff --git a/packages/panels/src/FilamentManager.php b/packages/panels/src/FilamentManager.php index e4fd7c622a..1a0edd1c88 100644 --- a/packages/panels/src/FilamentManager.php +++ b/packages/panels/src/FilamentManager.php @@ -488,6 +488,11 @@ class FilamentManager return $this->getCurrentOrDefaultPanel()->getProfilePage(); } + public function getTopbarLivewireComponent(): string + { + return $this->getCurrentOrDefaultPanel()->getTopbarLivewireComponent(); + } + public function getTenantProfilePage(): ?string { return $this->getCurrentOrDefaultPanel()->getTenantProfilePage(); From 713a6ec9c1f7c63c8d8d190723162bc3f1d16359 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Mon, 4 Aug 2025 09:05:01 +0100 Subject: [PATCH 4/4] clean up & docs --- docs/06-navigation/01-overview.md | 18 ++++++++++++++++++ packages/panels/src/Facades/Filament.php | 2 ++ packages/panels/src/FilamentManager.php | 4 ++++ .../panels/src/Panel/Concerns/HasTopbar.php | 3 +-- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/06-navigation/01-overview.md b/docs/06-navigation/01-overview.md index 4edd174154..b21a9f59d0 100644 --- a/docs/06-navigation/01-overview.md +++ b/docs/06-navigation/01-overview.md @@ -552,6 +552,24 @@ public function panel(Panel $panel): Panel } ``` +### Replacing the sidebar and topbar Livewire components + +You may completely replace the Livewire components that are used to render the sidebar and topbar, passing your own Livewire component class name into the `sidebarLivewireComponent()` or `topbarLivewireComponent()` method: + +```php +use App\Livewire\Sidebar; +use App\Livewire\Topbar; +use Filament\Panel; + +public function panel(Panel $panel): Panel +{ + return $panel + // ... + ->sidebarLivewireComponent(Sidebar::class) + ->topbarLivewireComponent(Topbar::class); +} +``` + ## Disabling breadcrumbs The default layout will show breadcrumbs to indicate the location of the current page within the hierarchy of the app. diff --git a/packages/panels/src/Facades/Filament.php b/packages/panels/src/Facades/Filament.php index 9b25df2b87..a21ab7d1d3 100644 --- a/packages/panels/src/Facades/Filament.php +++ b/packages/panels/src/Facades/Filament.php @@ -26,6 +26,7 @@ use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Facade; +use Livewire\Component; /** * @method static bool arePasswordsRevealable() @@ -105,6 +106,7 @@ use Illuminate\Support\Facades\Facade; * @method static string | null getTenantProfileUrl(array $parameters = []) * @method static string | null getTenantRegistrationUrl(array $parameters = []) * @method static Theme getTheme() + * @method static class-string getTopbarLivewireComponent() * @method static ThemeMode getDefaultThemeMode() * @method static string | null getUserAvatarUrl(Model | Authenticatable $user) * @method static Model | null getUserDefaultTenant(HasTenants | Model | Authenticatable $user) diff --git a/packages/panels/src/FilamentManager.php b/packages/panels/src/FilamentManager.php index 1a0edd1c88..7f6d712b74 100644 --- a/packages/panels/src/FilamentManager.php +++ b/packages/panels/src/FilamentManager.php @@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Event; +use Livewire\Component; class FilamentManager { @@ -488,6 +489,9 @@ class FilamentManager return $this->getCurrentOrDefaultPanel()->getProfilePage(); } + /** + * @return class-string + */ public function getTopbarLivewireComponent(): string { return $this->getCurrentOrDefaultPanel()->getTopbarLivewireComponent(); diff --git a/packages/panels/src/Panel/Concerns/HasTopbar.php b/packages/panels/src/Panel/Concerns/HasTopbar.php index c44b26a3ac..ee5936daa8 100644 --- a/packages/panels/src/Panel/Concerns/HasTopbar.php +++ b/packages/panels/src/Panel/Concerns/HasTopbar.php @@ -12,10 +12,9 @@ trait HasTopbar protected string | Closure | null $topbarLivewireComponent = null; - public function topbar(bool | Closure $condition = true, string | Closure | null $livewireComponent = null): static + public function topbar(bool | Closure $condition = true): static { $this->hasTopbar = $condition; - $this->topbarLivewireComponent($livewireComponent); return $this; }