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

Filament Sticky Table Header Laravel Package

watheqalshowaiter/filament-sticky-table-header

Makes Filament table headers stick to the top while scrolling, keeping column labels visible in long tables. Supports Filament 3, 4, and 5 with quick installation, and works with Laravel 10+ and PHP for a lightweight usability boost in any admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a zero-configuration plugin — there is nothing to publish, no config file, and no per-table wiring. The whole setup is two commands and three lines of PHP.

1. Install:

composer require watheqalshowaiter/filament-sticky-table-header

2. Register the plugin in the panel provider (app/Providers/Filament/AdminPanelProvider.php):

use WatheqAlshowaiter\FilamentStickyTableHeader\StickyTableHeaderPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...->resources([...])
        ->plugins([
            StickyTableHeaderPlugin::make(),
        ]);
}

3. Publish the Filament assets — the plugin ships CSS/JS that must be registered with Filament's asset pipeline:

php artisan filament:assets

Where to look first: after registering, open any resource list page with more rows than fit on screen and scroll. That is the entire first use case — no code change needed per table. If nothing sticks, the asset step is the cause ~90% of the time (see Gotchas).

Second thing to try is the only option the package exposes — the scroll-to-top behaviour on pagination, which pairs naturally with sticky headers:

StickyTableHeaderPlugin::make()
    ->shouldScrollToTopOnPageChanged(enabled: true, behavior: 'smooth'), // or 'instant'

Note the method name is shouldScrollToTopOnPageChanged() (with a trailing "d") even though the README prose in one place writes shouldScrollToTopOnPageChange(). Trust the chained call in the code block.

Version check before you start: the plugin advertises Filament 3.x, 4.x, and 5.x, plus Laravel 10–13 and PHP 8.1–8.5. Confirm your filament/filament constraint resolves to a version the plugin supports — the 1.1.0 and 1.4.0/1.5.0 releases exist specifically because sticky positioning had to be re-implemented for Filament 4 and 5. Pin accordingly if you are on an older Filament 3 install.

Implementation Patterns

Panel-level registration, not table-level. This is the single most important mental model: the plugin is applied once per panel and affects every table in that panel — resources, relation managers, and custom tables all inherit it. You do not call anything from inside a Resource or Table class. Plan for it as a global UX decision for the panel, the same way you'd decide on a global theme.

Multi-panel apps: register selectively. If you have AdminPanelProvider and a customer-facing AppPanelProvider, you can apply sticky headers only where long tables are the norm:

// AdminPanelProvider — long data grids, worth it
->plugins([StickyTableHeaderPlugin::make()->shouldScrollToTopOnPageChanged()])

// AppPanelProvider — small tables, skip it
->plugins([])

Combine with pagination for the intended payoff. Sticky headers earn their keep when users page through large datasets and lose column context. If your tables use ->paginated(false) with short lists, the plugin adds little; if you use ->defaultPaginationPageOption(50) or ->paginated([25, 50, 100]), it's a clear win. Pair it with ->shouldScrollToTopOnPageChanged(enabled: true, behavior: 'smooth') so paging lands at the top of the new page with the header in its resting (non-stuck) state.

Treat it as a deploy-time asset dependency. php artisan filament:assets belongs in your deploy script, right after php artisan filament:upgrade or optimize:clear:

php artisan migrate --force
php artisan filament:assets
php artisan optimize

Add it to your CI/deploy pipeline once, and it stops being a recurring "sticky headers broke on production" ticket.

Verify against the awkward column layouts. If you use ->groups([...]) for column grouping, wide/scrollable tables, or ->reorderableColumns(), smoke-test those specifically — changelog 1.3.0 exists to fix a gap with column groups, and 1.2.0 addressed mobile screens and the header's stacking position relative to row actions and the filter dropdown. Your Filament version determines which of those fixes you actually have.

Gotchas and Tips

Assets not published is the #1 failure mode. A fresh clone, a new CI environment, or a Docker build that skips the publish step all produce exactly the symptom of "I installed it and nothing happened." Run php artisan filament:assets and hard-refresh the browser. If you use Vite with a custom Filament theme, publish the package assets after your theme build so nothing overwrites them.

The plugin has no documented per-table opt-out. Because registration is panel-wide, any table that looks wrong with a sticky header (short tables inside modals, tables nested in widgets, tables with a custom scroll container) has no first-class toggle. Realistic mitigations: move the plugin to a dedicated panel, or add targeted CSS in your custom theme to unstick specific wrappers. Budget for this if your panel mixes long grids with many tiny embedded tables.

Custom scroll containers break position: sticky silently. Sticky positioning only works relative to the nearest scrolling ancestor. If you've wrapped a table in a max-h-[600px] overflow-y-auto div, or your layout uses overflow-hidden on a parent, the header may stick to the wrong edge, appear outside the container, or not stick at all. Test with the same markup you ship — not a stripped-down demo page.

Z-index conflicts with dropdowns and bulk action bars. Changelog 1.2.1 and 1.2.0 are both about stacking order versus filter dropdowns and row actions in Filament 3. If your filter selects, column-visibility dropdown, or sticky bulk-action bar render behind the header after install, you're hitting a version-specific stacking bug — upgrade the plugin first before writing custom CSS; the fix is likely already out.

Upgrading Filament? Upgrade this plugin in the same commit. The 1.1.0 (Filament 4) and 1.4.0/1.5.0 (Filament 5) releases were reimplementations, not cosmetic bumps, because Filament's table markup changed. A Filament major bump with an old plugin version yields a header that either doesn't stick or sticks at the wrong offset. Constrain the plugin to a compatible range in composer.json and let it move together with Filament.

No config file means no cache to clear — but the browser cache is real. There's nothing in config/ to config:cache, so if behaviour looks stale after an upgrade, suspects are the browser cache and Filament's own asset cache. php artisan filament:assets plus a hard reload resolves almost everything.

Debugging checklist when it misbehaves, in order: (1) did filament:assets run in this environment, (2) is the plugin actually in the panel provider for this panel, (3) does the table sit inside a custom overflow container, (4) is a custom theme's CSS overriding the header classes, (5) is the plugin version matched to your Filament major. That sequence covers essentially every reported issue in the changelog history.

Low-risk adoption. The package is MIT, has no runtime service dependencies beyond the Filament asset pipeline, and is purely presentational — no database, no middleware, no model hooks. The realistic cost of trying it and reverting is one composer remove, deleting one line from ->plugins([]), and re-running filament:assets. Worth a five-minute spike on a real resource before committing to it panel-wide.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core