mahdimajidzadeh/ds
RTL/Persian-first UI kit for Laravel Livewire that extends Flux UI, adding Persian typography and digits, Jalali dates, Toman/Rial pricing, and e-commerce components like product cards, quantity steppers, and countdowns.
An RTL / Persian-first UI kit for Laravel Livewire, built on top of Flux UI.
Majid DS does not replace Flux — it extends it. You keep every <flux:*> component exactly as it is, and gain an <mds:*> namespace with the pieces Flux doesn't have: Persian typography and digits, Jalali dates, Toman/Rial prices, and e-commerce components (product cards, quantity steppers, deal countdowns, checkout steppers, ratings).
<mds:product-card
title="گوشی موبایل سامسونگ مدل Galaxy S25"
image="/images/phone.jpg"
:amount="42500000"
:original="48900000"
:rating="4.6"
:reviews="342"
badge="ارسال امروز"
href="/products/galaxy-s25"
/>
| Area | What Majid DS adds |
|---|---|
| Typography | Vazirmatn font wired into Tailwind's --font-sans (@mdsFonts directive for the <link> tags) |
| Icons | Hugeicons via <mds:icon>, replacing heroicons across every mds:* component (heroicon names still work) |
| Numbers | Persian digits (۰۱۲۳), Persian separators (٬ / ٫), @fa / @faNum directives |
| Money | <mds:price>, @toman / @rial directives, configurable default currency |
| Dates | Dependency-free Jalali calendar (<mds:jalali-date>, @jalali, relative "۳ ساعت پیش") |
| E-commerce | <mds:product-card>, <mds:quantity>, <mds:discount-badge>, <mds:countdown> |
| Flows | <mds:stepper> (checkout steps), <mds:rating> / <mds:rating.input>, <mds:empty-state> |
| Pro alternatives | <mds:command> (⌘K palette), <mds:composer> (chat/prompt input), <mds:color-picker>, <mds:file-upload>, and <mds:timeline> — open versions of Flux Pro-only components |
All components are RTL-first (built with logical properties, so they also work LTR), support dark mode, and follow Flux's accent color tokens — customize --color-accent once and both libraries follow.
mds:* layer.CLAUDE.md/AGENTS.md at vendor/mahdimajidzadeh/ds/llms.txt so coding agents use the kit correctly.The whole docs/ folder is a static site: Settings → Pages → Source: main / /docs
publishes it at https://mahdimajidzadeh.github.io/majid-ds/, docs and demo alike. No
build step runs on GitHub — the pages are committed, so regenerate them when things change:
npm run docs # rebuilds the 56 reference pages + docs/assets/site.css
npm run pages # rebuilds the 20 demo pages in docs/demo/
Both sites share one stylesheet, docs/assets/site.css, built from
workbench/resources/css/site-input.css — so a
component CSS change can never ship to the docs but not the demo. The same input also
compiles to workbench/public/demo.css for npm run demo:serve.
| Group | Pages |
|---|---|
| Guides | Overview, Installation, Theming, Directives & helpers, AI agents |
| Layouts | The layout grid, Header, Sidebar, Aside |
| Components | The 30 free Flux components bundled with this package |
| mds components | All 15 mds:* components, including the five Flux Pro alternatives |
Flux Pro components are not documented. Nineteen of the components on fluxui.dev —
Accordion, Autocomplete, Calendar, Carousel, Chart, Composer, Context, Date picker,
Editor, Kanban, Pillbox, Popover, Slider, Tabs, Time picker and the rest — ship no code
in the free tier, so there is nothing to preview or reference. Five of them have mds:*
replacements (Command, Composer, Color picker, File upload, Timeline); for the others, see
Flux's own docs.
bin/build-docs.php assembles the pages from the content in bin/docs/ — one PHP file per group, holding each page's prose, examples and prop tables. The output is plain static HTML: nothing at read time needs PHP, Blade or a server.
Each example's preview is its own snippet, rendered once through Blade at build time.
That is deliberate: Flux computes its class strings at render time (a match over
colour, size and variant), so transcribing that markup by hand would give previews that
only resemble the components. Rendering it means the snippet you copy and the preview
above it are provably the same thing — and because the real flux.js is loaded, the
dropdowns, modals, tooltips and countdowns in the docs actually work.
bin/build-pages.php is the equivalent tool for the demo: it boots the workbench app
on a throwaway port, crawls /demo, /layouts and their /en counterparts, and writes
flat .html files into docs/demo/ with every link and asset rewritten to a relative
path — so the site works from a project subpath, a custom domain, or straight off the
file system.
livewire/flux ^2.0 (installed automatically)composer require mahdimajidzadeh/ds
1. CSS — in resources/css/app.css, import the Majid DS layer after Flux:
@import 'tailwindcss';
@import '../../vendor/livewire/flux/dist/flux.css';
@import '../../vendor/mahdimajidzadeh/ds/resources/css/mds.css';
/* Tailwind v4 skips gitignored paths, so point it at the kit's Blade views
or the utility classes inside them never get generated. */
@source '../../vendor/mahdimajidzadeh/ds/resources/views';
@custom-variant dark (&:where(.dark, .dark *));
2. Layout — set the document direction and load the font:
<html lang="fa" dir="rtl">
<head>
@mdsFonts {{-- Vazirmatn <link> tags; self-host for production traffic from Iran --}}
@fluxAppearance
</head>
<body>
...
@fluxScripts
</body>
</html>
That's it. <flux:*> and <mds:*> components now work side by side.
<mds:price><mds:price :amount="2500000" /> {{-- ۲٬۵۰۰٬۰۰۰ تومان --}}
<mds:price :amount="2500000" :original="3200000" /> {{-- + strikethrough & ۲۲٪ badge --}}
<mds:price :amount="14500000" currency="rial" size="sm" />
<mds:price :amount="1200000" :fa="false" /> {{-- Latin digits --}}
Props: amount, original, currency (toman | rial | none | literal label), decimals, size (sm|lg), fa, badge.
<mds:quantity>Cart quantity stepper. Works with plain forms (name) and Livewire (wire:model is forwarded to the hidden input, which always holds Latin digits):
<mds:quantity wire:model="qty" :min="1" :max="5" />
<mds:quantity name="quantity" :value="2" size="lg" />
<mds:rating> and <mds:rating.input><mds:rating :value="4.3" :count="126" /> {{-- display, supports half stars --}}
<mds:rating.input wire:model="score" /> {{-- interactive, forwards wire:model --}}
<mds:product-card>Composes flux:card, mds:rating, mds:price, and mds:discount-badge. The slot renders an actions area (e.g. an add-to-cart button):
<mds:product-card title="..." image="..." :amount="1890000" :rating="4.1" :reviews="87" href="...">
<flux:button variant="primary" size="sm" class="w-full">افزودن به سبد</flux:button>
</mds:product-card>
<mds:product-card title="..." image="..." unavailable /> {{-- grayscale + ناموجود --}}
Other props: original, currency, badge + badge-color (top corner flux:badge), fa.
<mds:stepper><mds:stepper :steps="['سبد خرید', 'آدرس و زمان ارسال', 'پرداخت', 'تأیید نهایی']" :current="2" />
current is 1-based; earlier steps render as completed (check icon), later ones as upcoming.
<mds:countdown><mds:countdown :until="$deal->ends_at" :days="false" /> {{-- ۰۷:۴۱:۵۵ (wall-clock, LTR) --}}
<mds:countdown :until="$deal->ends_at" labels size="lg" /> {{-- Digikala-style labeled boxes --}}
<mds:countdown :until="$deal->ends_at" expired-text="این پیشنهاد به پایان رسید" />
Server-rendered initial value (no blank flash), then ticks with Alpine.
<mds:jalali-date><mds:jalali-date :date="now()" /> {{-- ۲۹ مرداد ۱۴۰۵ --}}
<mds:jalali-date :date="now()" format="l j F Y" /> {{-- پنجشنبه ۲۹ مرداد ۱۴۰۵ --}}
<mds:jalali-date :date="now()" format="Y/m/d" /> {{-- ۱۴۰۵/۰۵/۲۹ --}}
<mds:jalali-date :date="$order->created_at" ago /> {{-- ۳ ساعت پیش --}}
Renders a semantic <time datetime="...">. Format tokens: Y y n m j d F l D plus time passthroughs H G h g i s A a.
<mds:command>An open implementation of Flux Pro's command palette, API-compatible with flux:command. Client-side filtering (with Persian text normalization: Arabic ي/ك and Arabic-Indic digits match their Persian forms), arrow-key navigation, Enter to select, and group headings that hide while searching:
<mds:command>
<mds:command.input placeholder="جستجوی فرمان..." clearable />
<mds:command.items>
<mds:command.heading>ناوبری</mds:command.heading>
<mds:command.item icon="shopping-bag" kbd="⌘O" wire:click="...">سفارشهای من</mds:command.item>
<mds:command.item icon="heart" href="/wishlist">علاقهمندیها</mds:command.item>
</mds:command.items>
</mds:command>
For a global ⌘K palette, pair it with Flux's modal (the shortcut prop and bare variant are free):
<flux:modal.trigger name="search" shortcut="cmd.k">
<flux:input as="button" placeholder="جستجو..." icon="magnifying-glass" kbd="⌘K" />
</flux:modal.trigger>
<flux:modal name="search" variant="bare" class="my-[12vh] w-full max-w-[30rem]">
<mds:command>
<mds:command.input placeholder="جستجو در همهجا..." closable autofocus />
<mds:command.items>...</mds:command.items>
</mds:command>
</flux:modal>
Props — command.input: icon (default magnifying-glass), clearable, closable (closes the containing modal); command.item: icon, icon-variant, kbd, href (renders <a> instead of <button>); command.items: empty (no-results text, default «نتیجهای یافت نشد.»).
<mds:composer>An open implementation of Flux Pro's composer, API-compatible with flux:composer. A textarea that grows with the text, an action bar around it, and Ctrl/⌘ + Enter to submit the enclosing form — the input every chat and AI-prompt screen needs:
<form wire:submit="send">
<mds:composer wire:model="message" label="پیام" label:sr-only placeholder="پیام خود را بنویسید...">
<x-slot name="actionsLeading">
<flux:button size="sm" variant="subtle" square><mds:icon icon="paper-clip" class="size-4" /></flux:button>
</x-slot>
<x-slot name="actionsTrailing">
<flux:button type="submit" size="sm" variant="primary" square><mds:icon icon="paper-airplane" class="size-4" /></flux:button>
</x-slot>
</mds:composer>
</form>
Four slots wrap the input: header (attachment previews, a reply-to line), footer, actionsLeading and actionsTrailing. A fifth, input, replaces the textarea itself — that is where Flux drops its Pro editor, and where any rich-text control goes.
<mds:composer rows="1" max-rows="6" inline submit="enter" ... /> {{-- one row, actions beside it, Enter sends --}}
<mds:composer variant="input" label="پیام پشتیبانی" ... /> {{-- form-control corner radius --}}
<mds:composer :maxlength="500" counter ... /> {{-- «۱۲ / ۵۰۰» under the action bar --}}
rows is the height it starts at and max-rows the height it stops growing at; past that the input scrolls. submit="enter" promotes the bare Enter to sending and leaves Shift + Enter as the newline — Ctrl/⌘ + Enter sends either way, and an open IME composition keeps its Enter. Sending calls form.requestSubmit(), so wire:submit and native validation behave exactly as they do on a click.
The counter counts characters rather than bytes — «سلام» is ۴ — and renders in Persian digits unless you pass :fa="false". disabled makes the whole box inert, action buttons included, and validation errors come from the bag for name (or from an explicit error), the same as every other field in the kit.
Props: name, value, placeholder, label (+ label:sr-only), description (+ description:sr-only), rows, max-rows, maxlength, counter, inline, variant, submit, autofocus, dir (auto follows what is being typed), disabled, invalid, error, fa. wire:model lands on the textarea; everything else lands on the wrapper.
<mds:color-picker>An open implementation of Flux Pro's color picker, API-compatible with flux:color-picker. Saturation/value canvas, hue slider, alpha slider (for alpha formats), hex input, swatch palette, and an EyeDropper button:
<mds:color-picker label="رنگ اصلی" wire:model="color" clearable dropper />
<mds:color-picker type="button" value="#8b5cf6" /> {{-- chip-only trigger --}}
<mds:color-picker format="rgba" value="rgba(59, 130, 246, 0.5)" /> {{-- adds an alpha slider --}}
<mds:color-picker :swatches="[['#ef4444', 'قرمز'], '#3b82f6']" /> {{-- custom palette --}}
<mds:color-picker :swatches="false" /> {{-- no palette --}}
Props: value, name, wire:model (forwarded to the hidden input; emits input events), format (hex default, hexa, rgb, rgba, hsl, hsla — pasted colors in any of these forms are parsed and normalized), type (input | button), label, description, placeholder, clearable, dropper (hidden automatically where the EyeDropper API is unsupported), size (sm), disabled, invalid.
The popover layout is composable — pass a slot to build your own from color-picker.area, color-picker.slider (channel="hue|alpha"), color-picker.input, color-picker.swatches / color-picker.swatch, and color-picker.dropper:
<mds:color-picker type="button">
<div class="flex flex-col gap-3">
<mds:color-picker.input placeholder="#000000" />
<mds:color-picker.area />
<mds:color-picker.slider channel="hue" />
</div>
</mds:color-picker>
The canvas and sliders are intentionally left-to-right even on RTL pages (the universal convention for color controls); labels and field layout follow the page direction.
<mds:file-upload> and <mds:file-item>An open implementation of Flux Pro's file upload, API-compatible with flux:file-upload. Drag-and-drop, click-to-browse, a compact inline variant, and a progress bar driven by Livewire's own upload events. Under the chrome it is a real <input type="file">, so wire:model, plain form posts, and keyboard access all work:
<mds:file-upload wire:model="photos" label="بارگذاری تصاویر" multiple accept="image/*">
<mds:file-upload.dropzone text="JPG، PNG یا GIF تا ۱۰ مگابایت" with-progress />
</mds:file-upload>
<div class="mt-3 flex flex-col gap-2">
@foreach ($photos as $index => $photo)
<mds:file-item
:heading="$photo->getClientOriginalName()"
:image="$photo->temporaryUrl()"
:size="$photo->getSize()"
>
<x-slot name="actions">
<mds:file-item.remove wire:click="removePhoto({{ $index }})" />
</x-slot>
</mds:file-item>
@endforeach
</div>
<mds:file-item :size="162400" /> renders «۱۵۹ کیلوبایت» — sizes go through Persian::fileSize(), and file names get dir="auto" so Latin names stay readable in an RTL list. Pass invalid for rejected files.
Props — file-upload: name ([] appended when multiple), multiple, accept, label, description, error (falls back to $errors->first($name) when omitted), invalid, disabled, fa; file-upload.dropzone: heading, text, icon (default cloud-arrow-up), inline, with-progress; file-item: heading, text, image, size, icon, invalid, fa, plus an actions slot; file-item.remove: icon, label (its aria-label).
Any markup in the slot inherits the upload behavior, so custom uploaders are just HTML. The wrapper carries data-dragging and data-loading (target them with Tailwind's in-data-dragging: / in-data-loading:) and sets --mds-file-upload-progress (42%) and --mds-file-upload-progress-as-string ('۴۲٪') for custom progress UIs:
<mds:file-upload wire:model="avatar" accept="image/*">
<div class="size-20 rounded-full bg-zinc-100 in-data-dragging:border-accent in-data-loading:opacity-50">
<flux:icon icon="user" variant="solid" />
</div>
</mds:file-upload>
<mds:icon>Majid DS uses Hugeicons instead of heroicons. Every mds:* component's icon prop routes through <mds:icon>, so the whole kit shares one icon language:
<mds:icon icon="shopping-cart-01" /> {{-- a Hugeicons name --}}
<mds:icon icon="magnifying-glass" /> {{-- a heroicon name, aliased --}}
<mds:icon icon="truck-delivery" class="size-4 text-accent" />
<mds:icon icon="notification-01" :stroke="2" /> {{-- thicker strokes --}}
<mds:icon icon="alert-02" label="هشدار" /> {{-- role="img" + aria-label --}}
The free Stroke Rounded set (6,200 icons) ships with the afatmustafa/blade-hugeicons dependency, so it works out of the box. Sizing and colour are plain Tailwind classes; unlabelled icons are aria-hidden, and a label promotes them to role="img".
Heroicon names keep working. Two maps handle the vocabulary gap: ALIASES translates heroicon names with no Hugeicons counterpart (magnifying-glass → search-01, x-mark → cancel-01, cloud-arrow-up → cloud-upload), and OVERRIDES handles the six names Hugeicons also has but draws differently — its arrow-* are chevrons rather than arrows, its moon is full rather than crescent, and its map-pin is a pin on a map. A literal Hugeicons name always beats an alias, so icon="heart" gets you Hugeicons' own heart. Anything neither map covers falls back to flux:icon, which still renders heroicons — so nothing breaks.
:stroke is opt-in on purpose: 453 of the free icons vary their stroke weight deliberately, and forcing one width would flatten them.
Pro styles. Only Stroke Rounded is free. The other eight styles are never bundled — register your own licensed export and they resolve by name:
// config/mds.php
'icons' => [
'default' => 'hugeicons', // 'flux' switches the whole kit back to heroicons
'style' => 'stroke-rounded',
'sets' => [
'solid-rounded' => resource_path('svg/hugeicons/solid-rounded'),
],
],
<mds:icon icon="user" variant="solid-rounded" /> {{-- a Hugeicons style --}}
<mds:icon icon="user" variant="micro" /> {{-- a Flux variant, mapped --}}
variant takes either vocabulary, so markup written against flux:icon keeps rendering. Licensing: the free set is published to npm as MIT and redistributed by afatmustafa/blade-hugeicons; note that Hugeicons' own licence agreement claims to cover the free versions too, so if that matters to you, read both before shipping. Pro files stay in your app either way.
<mds:timeline>An open implementation of Flux Pro's timeline, API-compatible with flux:timeline. A CSS-grid rail with connector lines, step statuses, coloured indicators, and full-width blocks. The rail sits on the right in RTL, and a horizontal timeline flows right-to-left:
<mds:timeline horizontal>
<mds:timeline.item status="complete">
<mds:timeline.indicator><flux:icon icon="credit-card" variant="micro" /></mds:timeline.indicator>
<mds:timeline.content>
<flux:heading>پرداخت شد</flux:heading>
<flux:text>@jalali($order->paid_at)</flux:text>
</mds:timeline.content>
</mds:timeline.item>
<mds:timeline.item status="current">
<mds:timeline.indicator><flux:icon icon="truck" variant="micro" /></mds:timeline.indicator>
<mds:timeline.content><flux:heading>در حال ارسال</flux:heading></mds:timeline.content>
</mds:timeline.item>
<mds:timeline.item status="incomplete">
<mds:timeline.indicator><flux:icon icon="home" variant="micro" /></mds:timeline.indicator>
<mds:timeline.content><flux:heading>تحویل به مشتری</flux:heading></mds:timeline.content>
</mds:timeline.item>
</mds:timeline>
status drives the rail as well as the dot: complete paints the connector up to the next indicator in your accent colour, current gets an accent ring, incomplete is muted and dims its content.
{{-- Numbered checkout steps --}}
<mds:timeline size="lg" align="start">
<mds:timeline.item status="complete">
<mds:timeline.indicator>@fa(1)</mds:timeline.indicator>
<mds:timeline.content>
<flux:heading>سبد خرید</flux:heading>
<flux:text>کالاها را بررسی و تعداد را نهایی کنید.</flux:text>
</mds:timeline.content>
</mds:timeline.item>
</mds:timeline>
{{-- A full-width block, re-aligned to the rail's columns --}}
<mds:timeline.item>
<mds:timeline.block class="rounded-xl border border-zinc-200 bg-zinc-50 dark:border-white/10 dark:bg-white/5">
<mds:timeline.subgrid class="p-3">
<flux:avatar size="xs" circle src="..." />
<flux:text>مرسوله شما امروز از انبار تهران ارسال میشود.</flux:text>
</mds:timeline.subgrid>
</mds:timeline.block>
</mds:timeline.item>
Props — timeline: horizontal, align (start | baseline | center | end), size (lg); timeline.item: status (complete | current | incomplete), plus align / size overrides; timeline.indicator: variant="bare" (icon-only marker), status, color (the 17 Tailwind hues plus zinc, and it outranks status). timeline.content, timeline.block, and timeline.subgrid take no props.
Geometry is four CSS variables: --mds-timeline-item-gap, --mds-timeline-content-gap, --mds-timeline-indicator-size, and --mds-timeline-baseline (the first line-height align="baseline" centres on — raise it for large headings). Set them with an arbitrary class:
<mds:timeline class="[--mds-timeline-item-gap:3rem]">...</mds:timeline>
<mds:discount-badge> and <mds:empty-state><mds:discount-badge :percent="20" />
<mds:discount-badge :amount="80000" :original="100000" /> {{-- computes ۲۰٪ --}}
<mds:empty-state icon="shopping-cart" title="سبد خرید شما خالی است" description="...">
<flux:button variant="primary">مشاهده پیشنهادها</flux:button>
</mds:empty-state>
@fa(123) {{-- ۱۲۳ --}}
@faNum(2500000) {{-- ۲٬۵۰۰٬۰۰۰ --}}
@toman(2500000) {{-- ۲٬۵۰۰٬۰۰۰ تومان --}}
@rial(990) {{-- ۹۹۰ ریال --}}
@jalali('2026-08-20') {{-- ۲۹ مرداد ۱۴۰۵ --}}
use MajidDs\Mds;
use MajidDs\Support\{Persian, Jalali};
Mds::toman(2500000); // ۲٬۵۰۰٬۰۰۰ تومان
Mds::jalali(now(), 'Y/m/d'); // ۱۴۰۵/۰۵/۲۹
Mds::ago(now()->subHours(3)); // ۳ ساعت پیش
Mds::fileSize(162400); // ۱۵۹ کیلوبایت
Persian::digits('order 123'); // order ۱۲۳
Persian::latinDigits('۰۹۱۲'); // 0912
Jalali::fromGregorian(2026, 8, 20); // [1405, 5, 29]
Jalali::toGregorian(1405, 5, 29); // [2026, 8, 20]
The Jalali implementation is dependency-free and is tested against PHP's intl Persian calendar across a 110-year range.
php artisan vendor:publish --tag=mds-config
return [
'currency' => 'toman', // default currency for prices
'persian_digits' => true, // global default; override per component with :fa="..."
];
Publish the views and edit them — app-level views take precedence, exactly like Flux's own publish flow:
php artisan vendor:publish --tag=mds-views # -> resources/views/mds/
Components can also be used with standard component syntax: <x-mds::rating> ≡ <mds:rating>.
Two RTL demos ship in the workbench — a component showcase and a layout gallery:
composer install
npm install
npm run demo:css # compile the demo stylesheet (Tailwind v4)
npm run demo:serve # then open http://127.0.0.1:8720/demo
| Route | What it shows |
|---|---|
/demo |
Every free Flux component plus the whole <mds:*> set |
/layouts |
Gallery of all page layouts, with a wireframe and snippet for each |
/layouts/header |
Top navbar only — header, main and footer all contained |
/layouts/sidebar |
Full-height sidebar (sidebar before header) |
/layouts/sidebar-header |
Full-width header above the sidebar (header first) |
/layouts/collapsible |
Sidebar that collapses to an icon rail on desktop |
/layouts/mobile |
Sidebar fixed on desktop, off-canvas below lg |
/layouts/aside |
Three columns: sidebar, main and a sticky flux:aside |
/layouts/sticky |
Sticky header, sidebar and aside with a long scrolling main |
/layouts/container |
container prop and flux:container width control |
Every route above also exists under /en — /en/demo, /en/layouts/aside and so
on — rendered left-to-right in English. Both locales are what npm run pages
snapshots into docs/ (20 pages); see Documentation for
publishing them.
The Persian copy in the workbench views is the translation key, so the Blade stays readable in the language the kit is designed for:
<flux:button :href="$mdsUrl('/layouts')" icon="squares-2x2">{{ __('چیدمانهای صفحه') }}</flux:button>
workbench/lang/en.json maps each Persian string to
English via Laravel's JSON translations. An unmapped key falls through to itself,
so fa needs no translation file at all.
Locale also drives the kit's own formatting. Every mds:* component reads
config('mds.persian_digits') and config('mds.currency') at render time, so the
route sets them once per locale and digits, separators and the currency label
switch across the whole page — ۲٬۵۰۰٬۰۰۰ تومان becomes 2,500,000 Toman without
touching a single component call.
A few strings are hardcoded Persian inside the kit with no prop to override them,
so they stay Persian on the English pages: the ٪ sign on <mds:discount-badge>,
the unit labels and expiry text on <mds:countdown>, ناموجود on
<mds:product-card>, the Jalali month names, and Persian::ago(). The English
demo carries a callout naming them, and the build script counts what is left on
each English page so a new untranslated string shows up in the build output.
Every layout page carries a floating switcher, so you can jump between them (and
toggle dark mode) without going back to the gallery. Layout arrangement is decided
by the order of the children: a <flux:sidebar> placed before <flux:header>
claims the full height, a <flux:header> placed first spans the full width — in
RTL the sidebar lands on the right with no extra classes.
Run the test suite:
composer test
MIT for this package. Note that livewire/flux has its own license; the free component set is used here, and Flux Pro features remain subject to Flux's licensing.
How can I help you explore Laravel packages today?