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 Themes Laravel Package

asignua/filament-themes

asignua/filament-themes adds theme management to Filament admin panels, letting you register, organize, and switch between custom themes. It provides a straightforward way to integrate theme selection into your Filament resources and pages.

View on GitHub
Deep Wiki
Context7

Getting Started

  • composer require hasnayeen/themes, then publish and run the migration (theme_settings table). If you prefer user-column storage, publish the config first and skip the migration — you'll add the columns to users yourself.
  • Register the plugin on the panel you want themable in your PanelProvider: ->plugin(ThemesPlugin::make()). Nothing renders until the plugin is attached to a panel, so a missing Themes page is almost always a registration problem, not a config problem.
  • Pick your storage mode on day one: theme_settings table if you have multiple panels, multiple guards, or plan to add panels later; user model columns if you have one panel and want to avoid the extra query. Migrating between the two is manual work, so treat this as a one-way decision.
  • First use case worth shipping: set a panel-wide default theme in config (your brand theme), then enable per-user override so each admin can pick Nord/Dracula/etc. without touching code.
  • Where to look first: config/themes.php (theme lists, storage, defaults), the plugin's Themes page class (to see how cards/previews are composed), and one built-in theme class (Nord or Ocean) — it is the shortest reference for the hasnayeen/themes contract you'll implement for custom themes.

Implementation Patterns

Default + override precedence. Configure a panel-wide theme as the fallback and let per-user choice win. This gives you a safe branded default for new users and lets power users personalise. Document the precedence in your onboarding, because "why does my theme reset?" is the first support question.

Per-panel theme lists for branding boundaries. Use the per-panel list to expose only themes that make sense for that audience — e.g. Ocean + your brand theme for a customer-facing panel, the full six for an internal admin panel. This is also your cheapest way to hide a theme you haven't contrast-tested yet, without deleting it.

Custom themes as classes, registered in config. Implement the hasnayeen/themes contract, define light and dark palettes plus the primary colour, then register the class in config/themes.php. Keep the class dumb — palettes only, no logic — so it stays trivially testable and diffable in review.

Primary colour via swatch or free hex. Use the swatches as the guided path for non-designers and the #rrggbb field for brand matching. Wrap the free-hex case with your own validation (valid hex, and a contrast check against your intended surfaces) before it ever reaches production.

Gate for the "locked" case. canChangeTheme is the right hook for kiosk displays, tenant-managed branding, or "only admins may change this". Implement it via a Gate definition or policy method rather than branching inside the page — it keeps the decision in one place and makes it testable.

Multi-panel / multi-tenant. Combine per-panel lists with theme_settings storage and key your rows by panel (and tenant, if you have them). One tenant's branding refresh then can't leak into another's panel.

Testing. Write a Livewire test that selects a theme, asserts persistence, and asserts the gate blocks unauthorised users. For every custom theme, add a contrast test mirroring the package's own AA assertions — the built-in guarantees don't extend to your classes.

Translations. Ten languages ship in-box; publish the lang files only for the handful of strings you want to reword (e.g. "Theme" → "Appearance"), rather than overriding the whole set.

Gotchas and Tips

  • WCAG AA coverage stops at the built-ins. The package's tests guarantee contrast for the six shipped themes only. Any custom theme or free-hex primary colour is your responsibility. Enforce 4.5:1 for normal text and 3:1 for large text/UI components in CI, or you will ship an unreadable admin panel and find out from users.
  • Test dark previews, not just light. A palette that passes in light mode can fail badly in dark. Review both previews on the Themes page and in an actual dark-mode panel before releasing a custom theme.
  • Free hex is a footgun. Users can paste anything — including a near-white primary that makes buttons invisible on white cards. Validate format server-side and consider rejecting low-contrast values with a helpful message rather than silently accepting them.
  • Custom CSS won't follow the theme. Only markup using Filament's colour tokens re-themes. Any hardcoded Tailwind greys or hand-written hex in your own views will stay put and look broken next to Dracula. Audit custom blade/CSS when you enable theming.
  • User-column storage has schema coupling. Column names must match what the package expects; get them wrong and the Themes page silently falls back to the default. Read the published config before writing the migration, and add the columns in the same deploy that enables the plugin.
  • Gate::before will bypass canChangeTheme. If you have a super-admin bypass returning true, theme locking won't apply to those users. That's usually fine, but verify it's the intent.
  • Stale rows after renames. Rows in theme_settings keyed by panel or tenant name go stale when you rename one. Prefer stable identifiers, and add a small cleanup command or migration when you rename panels.
  • Cache clearing. Run php artisan config:cache/config:clear after editing theme lists — a newly registered theme that "doesn't appear" is nearly always config cache. Also clear views if you publish the Themes page.
  • v1.0.0 means API churn. Pin the version in composer.json and keep your theme registrations in one config file plus one small service provider, so a future upgrade is a single-file change. Check compatibility against your Filament major version explicitly — theming plugins are tightly coupled to Filament's colour system.
  • Extension points to lean on: the theme contract (custom palettes), published config (lists/defaults/storage), published translations, and the gate. Prefer these over subclassing the Themes page, which is the most likely thing to change between releases.
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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk