Elements & Overlays

Actions, feedback, overlays, navigation and data display. Everything here is themeable and keyboard friendly. The toasts and stepper are wired to Livewire.

Buttons #

Seven variants, four sizes, icons, icon-only squares and automatic Livewire loading states.

<x-duro::button>Primary</x-duro::button>
                <x-duro::button variant="outline" size="lg" icon-right="arrow-right">Continue</x-duro::button>
                <x-duro::button square icon="edit" variant="secondary" aria-label="Edit" />
                <x-duro::button wire:click="save" loading="save" icon="check">Save</x-duro::button>
                <x-duro::button :href="route('home')" variant="link">Back home</x-duro::button>

Badges & alerts #

Status at a glance, with dots, icons, solid fills and dismissible alerts.

primary accent neutral success warning danger info
Online Pending Solid Critical
<x-duro::badge variant="success" dot>Online</x-duro::badge>
                <x-duro::badge variant="danger" solid icon="alert-triangle">Critical</x-duro::badge>

                <x-duro::alert variant="warning" title="Trial ends soon" dismissible>
                    Your trial expires in 3 days.
                </x-duro::alert>

Overlays #

Modals and slide-overs with focus trapping, scroll locking and Escape to close. Open them from anywhere with a browser event.

<x-duro::button x-on:click="$dispatch('open-modal', 'invite')">Invite</x-duro::button>

                <x-duro::modal name="invite" title="Invite your team" icon="users">
                    <x-duro::input name="email" label="Email" wire:model="email" />
                    <x-slot:footer>
                        <x-duro::button wire:click="invite">Send invite</x-duro::button>
                    </x-slot:footer>
                </x-duro::modal>

                {{-- From Livewire: $this->dispatch('open-modal', 'invite'); --}}

Toast notifications #

Fire toasts from Alpine with duroToast() or from any Livewire action with $this->dispatch('duro-toast', …).

// In a Livewire component
                $this->dispatch('duro-toast', title: 'Changes saved', body: 'All good.', variant: 'success');

                // In Alpine / plain JavaScript
                duroToast({ title: 'Copied!', variant: 'info' });

Data display #

Stats with animated counters, avatars, progress bars, skeleton loaders and a timeline.

Revenue

$48,250

12.4% vs last month

Active users

1,893

4.1%

Churn

2.3%

0.4% improved
AL AT GH
AL AT GH LT +2
Storage used 64%
Sprint completion 88%
  1. Deployed v2.4

    Zero-downtime release to all regions.
  2. Review approved

    Ada approved the pull request.
  3. Project created

    The realm was forged.
<x-duro::stat label="Revenue" :value="48250" prefix="$" icon="trending-up" change="12.4%" />
                <x-duro::avatar name="Ada Lovelace" status="online" />
                <x-duro::progress label="Storage used" :value="64" />

                <x-duro::timeline>
                    <x-duro::timeline.item title="Deployed v2.4" time="2h ago" icon="rocket" active>…</x-duro::timeline.item>
                </x-duro::timeline>

Accordion, rating & one-time code #

Collapsible content plus two compact inputs that bind straight to Livewire with wire:model.

Yes. Buttons, dialogs and menus ship with ARIA roles, focus management and keyboard support.

Add a [data-theme] block of tokens to app.css and an entry to config/duro.php.

Only Tailwind via Vite. The components themselves are plain Blade.

Rate this kit

Livewire value: 4

Verification code

Livewire value: none

<x-duro::accordion>
                    <x-duro::accordion.item title="Is the kit accessible?" open>…</x-duro::accordion.item>
                </x-duro::accordion>

                <x-duro::rating wire:model.live="rating" />
                <x-duro::otp-input label="Verification code" wire:model="code" :length="6" />

Empty state & divider #

Guide people forward when there is nothing to show yet.

No projects yet

Projects group your tables, forms and dashboards into a single realm.

The divider ornament changes with every realm.