mustafakhaleddev/nova-rtl-support
Adds right-to-left support to Laravel Nova, automatically flipping layouts, menus, forms, and UI components for Arabic, Hebrew, and other RTL languages. Lightweight setup aligns Nova styling so dashboards read naturally in RTL locales.
This package is a CSS-level RTL skin for Laravel Nova — it does not translate your admin panel, it flips the layout direction (sidebar, tables, forms, dropdowns, pagination) for locales such as Arabic, Hebrew, Farsi, and Urdu. It was built in the Nova 2.x era and has been archived since May 2019, so treat the repository source as the authoritative documentation rather than expecting current docs.
Minimal setup:
composer.json in the repo for the laravel/nova constraint before committing to it.
composer require mustafakhaleddev/nova-rtl-support
config/app.php.php artisan vendor:publish
/nova, search the <head> for the package's CSS file or a dir="rtl" attribute on <html>/<body>. If neither is present, the provider did not register a Nova asset — that is the first thing to fix.Where to look first:
README.md — install and asset-publishing steps.src/*ServiceProvider.php — the real behavior lives here: whether it calls Nova::style(), injects a view, or publishes CSS.resources/ (or dist/) — the actual CSS overrides; this tells you which Nova version's DOM it targets.composer.json — Nova/PHP constraints and whether the package is still installable on your stack.First use case: an Arabic-language Nova admin for an internal tool on Nova 2.x/3.x. Install, publish, set app()->setLocale('ar'), then click through the dashboard, a resource index, a detail form, and a modal to see what actually flips. Expect to fix a handful of selectors rather than get a perfect result out of the box.
Gate the asset by locale. Day-to-day, you rarely want RTL for every user. The cleanest pattern is to let the package register its CSS only when the current locale is RTL. If the provider always injects the stylesheet, wrap or replace that registration in your NovaServiceProvider::boot():
use Laravel\Nova\Nova;
public function boot()
{
parent::boot();
if (in_array(app()->getLocale(), ['ar', 'he', 'fa', 'ur'], true)) {
Nova::style('nova-rtl', public_path('vendor/nova-rtl/rtl.css'));
}
}
Keep this as a single, explicit list of RTL locales instead of inferring direction from translation files — it's easier to audit and avoids surprises with mixed-language teams.
Drive locale from user preference, not config/app.php. For multilingual admins, set the locale per request (a middleware reading users.locale, or the Accept-Language header) before Nova boots. If you change locale after the asset decision is made, the CSS will load but the document direction may not — check the order of your middleware.
Layer your own overrides after the package CSS. Don't fork the stylesheet for every tweak. Add a second Nova style asset registered after the package's so the cascade works in your favor:
Nova::style('nova-rtl-overrides', public_path('css/nova-rtl-overrides.css'));
Use [dir="rtl"] selectors in your overrides so the same file is safe to ship for LTR users.
Make custom tools, cards, and fields RTL-aware. The package only knows about Nova's built-in markup. Any custom Vue component you register needs its own direction handling. Prefer CSS logical properties (margin-inline-start, padding-inline-end, inset-inline-start) over margin-left/padding-right, or branch on a direction class:
[dir="rtl"] .my-card__icon { margin-left: 0; margin-right: .5rem; }
If your component reads direction in JS, expose it from a shared prop or document.dir rather than duplicating locale lists.
Pair it with a translation package. This package is presentation-only. Combine it with Nova localization files (or your own lang/vendor/nova/ar/*.php) so labels and the layout are consistent — an RTL layout with English labels looks worse than either alone.
Test visually, per screen. The pragmatic workflow is a short checklist per release: dashboard, resource index (with pagination and sorting arrows), detail form (text inputs, selects, date pickers, file uploads), modals, and the user menu. Screenshot before/after with the locale flipped; this catches the selectors that broke after a Nova upgrade faster than reading CSS.
ml-*, pl-*, text-left, flex utilities). On modern Nova you are effectively maintaining a fork; budget for that before adopting.Nova::style assets, custom tools, and theme packages may override the RTL rules. Inspect computed styles and, if needed, increase specificity with [dir="rtl"] .selector rather than !important.php artisan nova:publish where applicable, clear view/config cache, and hard-refresh. A stale mix-manifest or versioned filename makes it look like your change did nothing.public/vendor/<vendor>/<package> only when the tag is specified. If Nova::style() points at a path that doesn't exist, Nova fails quietly — verify the file exists on disk.<html dir="rtl" lang="ar"> (or whatever the package injects — verify), translated validation messages, RTL-aware date/number formatting, and locale-aware sorting. This package covers only the visual shell.rtl: variants, or a maintained RTL theme, will likely require less firefighting than resurrecting 2019 selectors.How can I help you explore Laravel packages today?