hoceineel/filament-keyboard-shortcuts
Add customizable keyboard shortcuts to Filament admin panels for faster navigation and actions. Open resources, trigger commands, and streamline workflows without reaching for the mouse. Simple setup and seamless integration.
This package layers keyboard-driven navigation and a command sheet onto Filament panels. The fastest path to value is to register the plugin on a panel, open the app, and press g — every sidebar item shows its chord as a badge (beside the icon when collapsed), and typing narrows the set. That single interaction is the core loop: g + letters to jump, ?/sheet for discovery, Esc to dismiss.
Where to look first:
->navigationHints(false) live.First use case to wire up: navigate an existing admin panel without touching a resource. Press g, type the first letter of a page label, hit Enter if the prefix is ambiguous. Once that works, pin a chord on your busiest resource (see below) and verify the sidebar title/aria-description reflects it.
Pinning a chord per resource or page. Declare protected static ?string $keyboardShortcut = 'u'; on the resource/page class, or implement public static function getKeyboardShortcut(): ?string when the chord must be computed (per-tenant, per-role, feature-flagged). Overrides accept one or two characters, so 'u' and 'us' are both valid.
Letting the fallback do the work. On panels with many items the package derives two-letter chords from the label (g c u for “Customers”) before falling back to digits. Resist pinning everything: pin only the handful of destinations people hit daily, and let the derivation handle the long tail. This keeps the chord space stable as you add resources.
Grouping for the sheet. Because sheet rows are grouped by navigation group and sections flow into balanced columns, navigationGroups() ordering on the panel is now a UX decision, not just a sidebar one. Put high-traffic groups first.
Disabling hints selectively. ->navigationHints(false) is panel-scoped. Use it on panels where the badges would compete with dense custom sidebar rendering, while leaving the chord pill and sheet active — the two features are independent.
Search-in-sidebar panels. If the panel uses ->topbar(false) or GlobalSearchPosition::Sidebar, the shortcuts button renders inside the global search field, falling back to the topbar end or the sidebar footer. No extra configuration is needed, but check the rendered position on each panel layout you ship.
Testing your integration. The package ships JS unit tests and a Playwright suite against a Testbench workbench. Mirror that in CI (npm test, npm run test:e2e) if you customise chords or add resources whose derived shortcuts you care about — a chord collision is exactly the kind of thing a browser test catches and a PHP test does not.
aria-modal="true", which made Filament believe a modal was open and silently disabled global search and every ->keyBindings() action. If users reported “shortcuts stopped working after installing this”, this is the cause. The attribute is now only set while the sheet is open.Enter. Typing a prefix that matches multiple items does not auto-select. The chord pill shows the keys typed so far plus a “then a letter” hint — treat Enter as the confirm key when documenting shortcuts for your team.Esc is now immediate. It hides the pill straight away rather than waiting; don’t build onboarding copy that assumes a delay.shift+x or g+c no longer match labels that merely contain those letters. If you documented “search for the shortcut” as a discovery trick, the behaviour is narrower and more predictable now.g + a single letter is fastest; two-letter chords exist mainly to disambiguate large panels. Avoid pinning a two-letter chord that collides with a derived prefix.O vs 0 is intentional. Letter keys and badges use the panel font so they stay distinguishable. Don’t override badge typography with a monospace stack or you lose that.aria-description (and as title when Filament shows no tooltip). If you add custom tooltips, check you aren’t duplicating the chord announcement twice.prefers-reduced-motion; the active table row uses a direction-agnostic focus ring instead of an inline-start bar. Don’t re-add positional styling that assumes LTR.How can I help you explore Laravel packages today?