A privacy mode toggle for a Filament admin panel that blurs sensitive dashboard numbers with a single click — useful when screen-sharing before revealing revenue figures to a client.
A Filament admin panel with a privacy mode toggle that blurs sensitive dashboard numbers with a single click — useful for screen-sharing without exposing revenue figures. It uses an Alpine.js store persisted in localStorage and a Filament render hook to inject the toggle next to the global search bar, with a body-scoped CSS blur applied to anything tagged as sensitive.
The repository contains the complete Laravel + Filament project to demonstrate the functionality, including migrations/seeds for the demo data.
The Filament project is in the app/Filament folder.
Feel free to pick the parts that you actually need in your projects.
git clone.env.example file to .env and edit database credentials therecomposer installphp artisan key:generatephp artisan storage:linkphp artisan migrate --seed (it has some seeded data for your testing)/admin and log in with credentials [email protected] and password.
This project consists of four pieces working together: a body-scoped CSS rule that applies the blur, an Alpine.js store that toggles it, a Blade toggle button rendered via a Filament render hook, and a set of dashboard widgets that opt their sensitive values in.
The entire blur effect is driven by two CSS selectors, both scoped under a .privacy-mode class that lives on <body>. Turning privacy mode on or off is just a matter of toggling that one class.
resources/css/filament/privacy-mode.css
.privacy-mode .privacy-sensitive { filter: blur(8px); user-select: none; transition: filter 0.3s ease;} .privacy-mode .fi-wi-stats-overview-stat-value { filter: blur(8px); user-select: none; transition: filter 0.3s ease;}
The key points:
.privacy-mode class on body scopes everything — nothing is blurred until that class is added, and removing it restores the panel instantly.fi-wi-stats-overview-stat-value is Filament's built-in class for the large number inside every StatsOverviewWidget stat, so this rule blurs every stat value in the panel automatically — no per-widget wiring required.privacy-sensitive is the opt-in class for anything else — a whole stat card, a table cell, a description line, an infolist entry — giving you fine-grained control when the blanket rule isn't enoughfilter: blur(8px) with a 0.3s ease transition makes the toggle feel like a soft fade rather than a hard swap, and user-select: none prevents a curious viewer from selecting the blurred text to reveal itState lives in a tiny Alpine store registered on alpine:init. The store owns the enabled flag, the localStorage persistence, and the DOM side-effect that adds or removes the .privacy-mode class on document.body.