Guides
Installation
Composer, one CSS import, and two lines in your layout.
The service provider is auto-discovered. Livewire 3 and livewire/flux come along as dependencies.
composer require mahdimajidzadeh/ds
Stylesheet
Import the kit's layer after Flux's. The @source line is not optional: Tailwind v4 skips gitignored paths, so without it none of the utility classes inside the kit's Blade views get generated.
/* resources/css/app.css */
@import 'tailwindcss';
@import '../../vendor/livewire/flux/dist/flux.css';
@import '../../vendor/mahdimajidzadeh/ds/resources/css/mds.css';
@source '../../vendor/mahdimajidzadeh/ds/resources/views';
@custom-variant dark (&:where(.dark, .dark *));
Layout
Set the document direction and load your font. The kit ships no font and sets none — the Fonts section of the theming guide shows how to pick a Persian face and either self-host it or load it from Google Fonts.
<html lang="fa" dir="rtl">
<head>
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100..900&display=swap" rel="stylesheet">
@fluxAppearance
</head>
<body>
...
@fluxScripts
</body>
</html>
flux:* and mds:* components now work side by side.Content Security Policy
The interactive components register their Alpine behaviour in inline <script> blocks, so under a policy with script-src 'nonce-…' the kit needs the nonce. Register it with Laravel once per request — Vite::useCspNonce() — and every kit script picks it up through @mdsNonce. That is the registry Livewire's own tags read too, and Flux's two directives take it as an option, so one line covers the page. Two more things a strict policy needs: Alpine's standard build, the one Livewire bundles, evaluates x-data expressions and so requires 'unsafe-eval' in script-src; and the kit's server-rendered inline style attributes (chart geometry, colour swatches, hidden-until-Alpine states) need 'unsafe-inline' in style-src. Nonces cover scripts only.
Vite::useCspNonce() — covers Livewire, Flux and every mds:* script.// app/Http/Middleware/AddContentSecurityPolicy.php
public function handle(Request $request, Closure $next): Response
{
$nonce = Vite::useCspNonce(); // generates one; or pass your own
$response = $next($request);
$response->headers->set(
'Content-Security-Policy',
"script-src 'self' 'nonce-{$nonce}' 'unsafe-eval'; style-src 'self' 'unsafe-inline'",
);
return $response;
}
{{-- the layout: Livewire and the kit read the nonce by themselves; Flux takes it as an option --}}
@fluxAppearance(['nonce' => Vite::cspNonce()])
...
@fluxScripts(['nonce' => Vite::cspNonce()])
{{-- your own inline scripts can carry the same nonce --}}
<script @mdsNonce>…</script>
Requirements
PHP 8.2+, Laravel 11, 12 or 13, Livewire 3, livewire/flux ^2.0 and Tailwind CSS v4.
Configuration
Publish the config to change the default currency, turn Persian digits off globally, or register Pro icon styles.
php artisan vendor:publish --tag=mds-config
Reference
config/mds.php
| Prop | Description |
|---|---|
| currency | Default for mds:price and Persian::money(): toman, rial, none, or a literal label. |
| persian_digits | When true (the default), output is Persian: digits, separators, and every built-in string — unit labels, empty states, ARIA labels. When false, all of it is English. Every component reads this at render time, so flipping it per request switches the whole page. |
| icons.default | hugeicons or flux to go back to heroicons. |
| icons.style | Hugeicons style used when a component does not ask for one. |
| icons.fallback_style | Falls back to Stroke Rounded when a Pro style is not registered. |
| icons.sets | Pro style name → directory of SVGs from your own licence. |