feat: Allow the tenant menu to be searched (#18029)

* feat: Allow the tenant menu to be searched

* Define tenant name earlier

* chore: fix code style

* clean up

* automatically enable for more than 10 tenants

---------

Co-authored-by: jonerickson <jonerickson@users.noreply.github.com>
Co-authored-by: Dan Harrin <git@danharrin.com>
This commit is contained in:
Jon Erickson
2025-10-04 14:08:01 +01:00
committed by GitHub
co-authored by jonerickson Dan Harrin
parent d2f331ee7a
commit 3c72e3b557
6 changed files with 90 additions and 15 deletions
+17
View File
@@ -367,6 +367,23 @@ public function panel(Panel $panel): Panel
}
```
### Allowing the tenants to be searched
You can use the `searchableTenantMenu()` method in the [configuration](../panel-configuration) to allow the tenants to be searched:
```php
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->searchableTenantMenu();
}
```
This is automatically enabled when there are more than 10 tenants in a user's list. You can disable it using `searchableTenantMenu(false)`.
### Customizing the registration link
To customize the [registration](#adding-a-tenant-registration-page) link in the tenant menu, register a new item with the `register` array key, and pass a function that [customizes the action](../actions) object:
@@ -60,4 +60,13 @@ return [
'alt' => ':name logo',
],
'tenant_menu' => [
'search_field' => [
'label' => 'Tenant search',
'placeholder' => 'Search',
],
],
];
@@ -12,6 +12,8 @@
fn (\Illuminate\Database\Eloquent\Model $tenant): bool => ! $tenant->is($currentTenant),
));
$isSearchable = filled($canSwitchTenants) ? (filament()->isTenantMenuSearchable() ?? (count($tenants) >= 10)) : false;
$itemsBeforeAndAfterTenantSwitcher = collect($items)
->groupBy(fn (Action $item): bool => $canSwitchTenants && ($item->getSort() < 0), preserveKeys: true)
->all();
@@ -88,22 +90,49 @@
@endif
@if ($canSwitchTenants)
<x-filament::dropdown.list>
@foreach ($tenants as $tenant)
@php
$tenantUrl = filament()->getUrl($tenant);
$tenantImage = filament()->getTenantAvatarUrl($tenant);
@endphp
<div x-data="{ search: '' }">
<x-filament::dropdown.list>
@if ($isSearchable)
<div x-id="['input']">
<label x-bind:for="$id('input')" class="fi-sr-only">
{{ __('filament-panels::layout.tenant_menu.search_field.label') }}
</label>
<x-filament::dropdown.list.item
:href="$tenantUrl"
:image="$tenantImage"
tag="a"
>
{{ filament()->getTenantName($tenant) }}
</x-filament::dropdown.list.item>
@endforeach
</x-filament::dropdown.list>
<x-filament::input
x-bind:id="$id('input')"
x-model="search"
placeholder="{{ __('filament-panels::layout.tenant_menu.search_field.placeholder') }}"
type="search"
/>
</div>
@endif
@foreach ($tenants as $tenant)
@php
$tenantImage = filament()->getTenantAvatarUrl($tenant);
$tenantName = filament()->getTenantName($tenant);
$tenantUrl = filament()->getUrl($tenant);
@endphp
<div
x-show="
search === '' ||
@js($tenantName).replace(/ /g, '')
.toLowerCase()
.includes(search.replace(/ /g, '').toLowerCase())
"
>
<x-filament::dropdown.list.item
:href="$tenantUrl"
:image="$tenantImage"
tag="a"
>
{{ $tenantName }}
</x-filament::dropdown.list.item>
</div>
@endforeach
</x-filament::dropdown.list>
</div>
@endif
@if ($itemsAfterTenantSwitcher->isNotEmpty())
+1
View File
@@ -149,6 +149,7 @@ use Livewire\Component;
* @method static bool isServing()
* @method static bool isSidebarCollapsibleOnDesktop()
* @method static bool isSidebarFullyCollapsibleOnDesktop()
* @method static ?bool isTenantMenuSearchable()
* @method static void serving(Closure $callback)
* @method static void setCurrentPanel(Panel | string | null $panel = null)
* @method static void setServingStatus(bool $condition = true)
+5
View File
@@ -462,6 +462,11 @@ class FilamentManager
return $this->getCurrentOrDefaultPanel()->getTenantMenuItems();
}
public function isTenantMenuSearchable(): ?bool
{
return $this->getCurrentOrDefaultPanel()->isTenantMenuSearchable();
}
/**
* @return class-string<Model>|null
*/
@@ -23,6 +23,8 @@ trait HasTenancy
protected bool | Closure $hasTenantMenu = true;
protected bool | Closure | null $isTenantMenuSearchable = null;
protected ?string $tenantRoutePrefix = null;
protected ?string $tenantDomain = null;
@@ -67,6 +69,13 @@ trait HasTenancy
return $this;
}
public function searchableTenantMenu(bool | Closure | null $condition = true): static
{
$this->isTenantMenuSearchable = $condition;
return $this;
}
public function tenantMenu(bool | Closure $condition = true): static
{
$this->hasTenantMenu = $condition;
@@ -325,6 +334,11 @@ trait HasTenancy
]) ?? $action;
}
public function isTenantMenuSearchable(): ?bool
{
return $this->evaluate($this->isTenantMenuSearchable);
}
/**
* @return array<Action>
*/