Fluent API Customization
All UI, theme, type registration, and slot customization is done via the fluent PHP API — not in config/scoutify.php. Register calls in AppServiceProvider::boot() (or any service provider).
use Matheusmarnt\Scoutify\Facades\Scoutify;use Matheusmarnt\Scoutify\Support\UiConfig;
public function boot(): void{ Scoutify::types()-> /* ... */ ; Scoutify::theme()-> /* ... */ ; Scoutify::configureUi(function (UiConfig $ui) { /* ... */ });}Scoutify::types() — Type Registration
Section titled “Scoutify::types() — Type Registration”Returns the singleton TypesConfig instance. All calls are additive and resolved on first use.
register()
Section titled “register()”Register an Eloquent model as a searchable type:
Scoutify::types()->register( \App\Models\User::class, label: 'Users', icon: 'user', // short name — prefix applied automatically color: 'indigo', // Tailwind color name or custom token);| Parameter | Type | Default | Description |
|---|---|---|---|
$class | class-string | — | Fully-qualified model class |
label | string | '' | Display name in the filter chip and group header |
icon | string | '' | Icon identifier (short name or full Blade Icons name) |
color | string | 'zinc' | Accent color — any Tailwind color name or a custom token registered via theme()->color() |
Chain multiple calls to register several models at once:
Scoutify::types() ->register(\App\Models\User::class, label: 'Users', icon: 'user', color: 'indigo') ->register(\App\Models\Post::class, label: 'Posts', icon: 'document-text', color: 'sky') ->register(\App\Models\Product::class, label: 'Products', icon: 'shopping-bag', color: 'emerald');iconPrefix()
Section titled “iconPrefix()”Set a global prefix prepended to short icon names before resolving via Blade Icons:
Scoutify::types()->iconPrefix('heroicon-o-');// 'user' → 'heroicon-o-user'If a model returns a full icon name (e.g. ri-user-line) that does not start with the prefix, it is used as-is.
Scoutify::theme() — CSS Class Overrides
Section titled “Scoutify::theme() — CSS Class Overrides”Returns the singleton ThemeConfig instance. Override any Tailwind class strings applied to modal elements. Unset methods fall back to the package defaults.
Available methods and defaults
Section titled “Available methods and defaults”| Method | Element | Default classes |
|---|---|---|
dialogPanel(string) | Outer positioning wrapper (no background) | relative w-full md:max-w-2xl |
dialogContent(string) | Inner content card (background, shadow, rounded corners) | flex max-h-[90dvh] min-h-0 flex-col overflow-hidden rounded-t-2xl bg-white pb-[env(safe-area-inset-bottom)] md:max-h-[80vh] md:rounded-xl md:shadow-2xl md:ring-1 md:ring-zinc-900/5 dark:bg-zinc-900 dark:md:ring-white/10 |
dialogScrim(string) | Backdrop overlay | absolute inset-0 bg-zinc-950/50 |
input(string) | Search input field | block w-full rounded-lg border border-zinc-200 bg-white py-2 text-sm text-zinc-900 placeholder-zinc-400 outline-none transition focus-visible:border-zinc-300 focus-visible:ring-2 focus-visible:ring-scoutify-accent/30 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:placeholder-zinc-500 [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden |
trigger(string) | Desktop trigger button (<x-scoutify::gs.trigger />) | group inline-flex h-9 min-w-16 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 text-sm text-zinc-500 transition hover:border-zinc-300 hover:text-zinc-700 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-scoutify-accent/40 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-400 dark:hover:border-zinc-600 dark:hover:text-zinc-200 |
triggerMobile(string) | Mobile trigger button (<x-scoutify::gs.trigger-mobile />) | lg:hidden inline-flex size-11 items-center justify-center rounded-lg border border-zinc-200 bg-white text-zinc-500 transition hover:border-zinc-300 hover:text-zinc-700 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-scoutify-accent/40 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-400 dark:hover:border-zinc-600 dark:hover:text-zinc-200 |
toggleActive(string) | Active state of filter toggle switch | bg-indigo-600 dark:bg-indigo-500 |
toggleInactive(string) | Inactive state of filter toggle switch | bg-zinc-200 dark:bg-zinc-700 |
accent(string) | Modal wrapper — injects --scoutify-accent CSS custom property | No default override — package CSS defines the scoutify-accent token |
previewButton(string) | Eye button on result rows (opens preview pane) — appended | inline-flex size-7 shrink-0 items-center justify-center rounded-md text-zinc-400 transition hover:bg-zinc-100 hover:text-zinc-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-zinc-800 dark:hover:text-zinc-300 |
downloadButton(string) | Download button on result rows and preview header — appended | inline-flex size-7 shrink-0 items-center justify-center rounded-md text-zinc-400 transition hover:bg-zinc-100 hover:text-zinc-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-zinc-800 dark:hover:text-zinc-300 (result rows); preview header uses size-8 variant |
previewBackButton(string) | Back arrow button in preview pane header — appended | inline-flex size-8 shrink-0 items-center justify-center rounded-lg text-zinc-500 transition hover:bg-zinc-100 hover:text-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-zinc-800 dark:hover:text-zinc-200 |
Customizing the modal background
Section titled “Customizing the modal background”Copy the default and change only the bg-* classes:
Scoutify::theme() ->dialogContent( 'flex max-h-[90dvh] min-h-0 flex-col overflow-hidden rounded-t-2xl ' . 'bg-slate-800 ' . // ← your custom background 'pb-[env(safe-area-inset-bottom)] md:max-h-[80vh] md:rounded-xl ' . 'md:shadow-2xl md:ring-1 md:ring-zinc-900/5 dark:bg-slate-900 dark:md:ring-white/10' );Widening the modal
Section titled “Widening the modal”dialogPanel controls max-width. Override only the sizing:
Scoutify::theme() ->dialogPanel('relative w-full md:max-w-4xl');Overriding the accent color
Section titled “Overriding the accent color”accent() accepts any CSS color value — a hex, rgb(), or CSS variable. It injects --scoutify-accent as an inline custom property on the modal wrapper, which cascades to all child elements. No Tailwind safelist needed:
Scoutify::theme()->accent('#7c3aed');// or: ->accent('var(--color-violet-600)') // Tailwind CSS 4 tokenAll focus rings, input borders, and highlighted elements reference --scoutify-accent through the package’s scoutify-accent token.
Customizing preview buttons
Section titled “Customizing preview buttons”previewButton(), downloadButton(), and previewBackButton() append classes to the element’s existing base — they do not replace them. Use them to add hover effects, backgrounds, or Tailwind overrides:
Scoutify::theme() ->previewButton('hover:bg-indigo-100 dark:hover:bg-indigo-900') ->downloadButton('hover:bg-emerald-100 dark:hover:bg-emerald-900') ->previewBackButton('hover:bg-zinc-200 dark:hover:bg-zinc-700');Custom color tokens
Section titled “Custom color tokens”Register named color tokens that models can reference via color: 'brand' in register():
Scoutify::theme()->color('brand', 'bg-violet-100 text-violet-700', 'dark:bg-violet-900/60 dark:text-violet-200');Then use in registration:
Scoutify::types()->register(\App\Models\Order::class, label: 'Orders', icon: 'shopping-cart', color: 'brand');Scoutify::configureUi() — Visibility Flags & Slots
Section titled “Scoutify::configureUi() — Visibility Flags & Slots”Pass a closure that receives a fresh UiConfig instance each time the modal boots:
use Matheusmarnt\Scoutify\Support\UiConfig;
Scoutify::configureUi(function (UiConfig $ui) { $ui->showTypeChips(false) ->showHintBar(false);});Visibility flags
Section titled “Visibility flags”| Method | Default | Description |
|---|---|---|
showTypeChips(bool) | true | Model-type filter chips above results |
showToggleOnlyActive(bool) | true | ”Active only” toggle |
showToggleIncludeTrashed(bool) | true | ”Include trashed” toggle |
showHintBar(bool) | true | Keyboard-shortcut hint bar at the bottom |
showIdleHint(bool) | true | Prompt text paragraph in the idle state — does not hide the magnifying-glass icon or recent-list |
Inject custom content into named positions inside the modal. Slots receive a SlotContext with the current search state:
| Slot key | Position | Behavior |
|---|---|---|
header-trailing | After the search input in the modal header | Appended |
idle-extra | After the idle state (before the user types) | Appended |
after-results | After the last result group | Appended |
empty-state | When a non-blank query returns 0 results | Replaces the default “No results” component; $ctx->query available |
use Matheusmarnt\Scoutify\Support\SlotContext;use Matheusmarnt\Scoutify\Support\UiConfig;
Scoutify::configureUi(function (UiConfig $ui) { // Blade view name $ui->slot('after-results', 'search.footer');
// Closure returning an HtmlString $ui->slot('empty-state', function (SlotContext $ctx) { return new \Illuminate\Support\HtmlString( "<p class=\"text-sm text-gray-400\">No results for \"{$ctx->query}\".</p>" ); });
// Blade component class-string $ui->slot('empty-state', \App\View\Components\SearchEmptyState::class);});SlotContext properties
Section titled “SlotContext properties”| Property | Type | Description |
|---|---|---|
$wire | Modal | Livewire component instance |
$query | string | Current search query string |
$results | Collection | Current results as a Laravel Collection — supports ->count(), ->first(), ->filter(), etc. |
$hasResults | bool | Whether results are non-empty |
$isIdle | bool | Whether the user has not typed yet |
A slot value can be:
- A Blade view name (string) — rendered with
SlotContext::toArray()as view data - A Closure receiving
SlotContext— returnHtmlString, aView, or a castable-to-string value - A Blade Component class-string — constructor parameters auto-matched from
SlotContext
Complete example
Section titled “Complete example”<?php
namespace App\Providers;
use App\Models\Order;use App\Models\Post;use App\Models\User;use Illuminate\Support\ServiceProvider;use Illuminate\Support\HtmlString;use Matheusmarnt\Scoutify\Facades\Scoutify;use Matheusmarnt\Scoutify\Support\SlotContext;use Matheusmarnt\Scoutify\Support\UiConfig;
class AppServiceProvider extends ServiceProvider{ public function boot(): void { Scoutify::types() ->iconPrefix('heroicon-o-') ->register(User::class, label: 'Users', icon: 'user', color: 'indigo') ->register(Post::class, label: 'Posts', icon: 'document-text', color: 'sky') ->register(Order::class, label: 'Orders', icon: 'shopping-cart', color: 'brand');
Scoutify::theme() ->dialogPanel('relative w-full md:max-w-4xl') ->color('brand', 'bg-violet-100 text-violet-700', 'dark:bg-violet-900/60 dark:text-violet-200');
Scoutify::configureUi(function (UiConfig $ui) { $ui->showHintBar(false) ->slot('empty-state', function (SlotContext $ctx) { return new HtmlString( "<p class=\"text-center text-sm text-gray-400 py-6\">No results for “{$ctx->query}”.</p>" ); }); }); }}