PHPackages                             leenuxus/jarenui - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. leenuxus/jarenui

ActiveLibrary[Templating &amp; Views](/categories/templating)

leenuxus/jarenui
================

A Jaren-UI compatible Livewire component library for Laravel — 50+ components, dark mode, CSS-variable theming.

v1.4.0(1mo ago)013MITBladePHP ^8.4

Since May 29Pushed 1mo agoCompare

[ Source](https://github.com/leenuxus/jarenui)[ Packagist](https://packagist.org/packages/leenuxus/jarenui)[ Docs](https://github.com/leenuxus/jarenui)[ RSS](/packages/leenuxus-jarenui/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (10)Versions (9)Used By (0)

JarenUI for Laravel Livewire
============================

[](#jarenui-for-laravel-livewire)

[![Latest Version](https://camo.githubusercontent.com/549bccf19ad5475f8811e63df6445a9d7ff07d22559b75dd783ec935d29282eb/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c65656e757875732f6a6172656e75692e737667)](https://packagist.org/packages/leenuxus/jarenui)[![PHP Version](https://camo.githubusercontent.com/9398c4768a7361f5f29db6d89bd0934096925c8a912d7262de7bb94a062e25ce/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6c65656e757875732f6a6172656e75692e737667)](https://packagist.org/packages/leenuxus/jarenui)[![License](https://camo.githubusercontent.com/96424469756d54a7e9ffe6114c49500208176bf48d65182d579c3a66d24662ac/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6c65656e757875732f6a6172656e7569)](LICENSE.md)

**50+ production-ready Livewire components** — dark mode, CSS-variable theming, Alpine.js interactivity, full ARIA accessibility, and zero Tailwind config required.

---

Requirements
------------

[](#requirements)

DependencyVersionPHP`^8.4`Laravel`^13`Livewire`^4.0`Alpine.js`^3.0`Tailwind CSS`^4.0` (optional — all styling uses CSS variables)---

Installation
------------

[](#installation)

```
composer require leenuxus/jarenui
php artisan jaren:install
```

That's it. The installer:

- Publishes `config/jarenui.php`
- Injects `@jarenStyles` into your layout ``
- Injects `` before your ``

### Manual setup

[](#manual-setup)

If you prefer not to use the installer:

```
{{-- In your layout  --}}
@jarenStyles

{{-- Before  --}}

```

### Alpine.js

[](#alpinejs)

JarenUI uses Alpine.js for interactivity. Load it in your layout or `app.js`:

```

```

---

Quick start
-----------

[](#quick-start)

```
{{-- Button --}}
Save changes
Delete

{{-- Input --}}

{{-- Select (searchable) --}}

{{-- Accordion --}}

        A Livewire component library…

{{-- Tabs --}}

    Overview
    Settings
    Overview content…
    Settings content…

{{-- Table (extend the base class) --}}

{{-- Kanban --}}

{{-- Toast from Livewire PHP --}}
$this->dispatch('jaren-toast', type: 'success', title: 'Saved!');
```

---

Artisan commands
----------------

[](#artisan-commands)

CommandDescription`php artisan jaren:install`Install jarenui (publish assets, inject into layout)`php artisan jaren:publish --views`Publish Blade views for customisation`php artisan jaren:publish --config`Publish config file`php artisan jaren:publish --assets`Publish CSS to `public/vendor/jarenui/``php artisan jaren:publish --stubs`Publish layout stub`php artisan jaren:make-table UsersTable --model=User`Generate a Table component`php artisan jaren:make-kanban ProjectKanban`Generate a Kanban component---

Theming
-------

[](#theming)

All visual tokens are CSS custom properties. Override any in your own CSS — no Tailwind config or build step needed:

```
/* resources/css/app.css */
:root {
    --accent:      #7c3aed;    /* Brand primary */
    --accent-bg:   #f5f3ff;
    --accent-text: #6d28d9;
    --radius:      8px;        /* Corner radius */
}
```

Or via `.env` / `config/jarenui.php`:

```
jarenui_ACCENT=#7c3aed
jarenui_THEME=violet
```

### Built-in themes

[](#built-in-themes)

Add a class to `` to activate a named theme:

ClassColour`theme-rose`Rose / pink`theme-violet`Violet / purple`theme-emerald`Emerald green`theme-amber`Amber / gold`theme-sharp`Reduced border radii`theme-rounded`Increased border radii### Dark mode

[](#dark-mode)

Set `data-theme="dark"` on `` (or use Tailwind's `.dark` class):

```

```

Toggle dynamically with Alpine:

```
Toggle dark
```

---

Component reference
-------------------

[](#component-reference)

### Layouts

[](#layouts)

**``** — Sticky app header with brand, nav, search, and actions slots.

**``** — Collapsible sidebar with sections, items, and user footer.

**``** — Standalone horizontal nav bar.

---

### Primitives

[](#primitives)

**``**

```

    Label

```

**``**

```
Text
```

**``**

```

```

**``**

```

```

---

### Form

[](#form)

**``**

```

```

Password with toggle

```

```

> **Note:** `toggleable` occupies the trailing addon slot. Do not combine it with `clearable`, `copyable`, `icon-end`, or `suffix` on the same input.

**``**

```

```

**``**

```

```

**``**

```

```

**`` + ``**

```

```

**``**

```

```

**``**

```

```

**``**

```

```

**``**

```

```

**``** — wraps any control with label + hint + error

```

```

---

### Navigation

[](#navigation)

**``**

```

        Answer text…

```

**``**

```

```

**``**

```

    Menu
    Profile

    Delete

```

**``**

```

    Overview
    Content…

```

**``**

```
{{-- With Livewire paginator: --}}

{{-- Manual: --}}

```

---

### Overlay

[](#overlay)

**``**

```

    Delete?
    This cannot be undone.
    Body content…

        Cancel
        Delete

```

Open from PHP: `$this->dispatch('open-modal', name: 'confirm')`Open from JS: `$dispatch('open-modal', 'confirm')`

**``**

```

```

**``**

```

    Open
    Popover content here…

```

---

### Feedback

[](#feedback)

**``** — Driven by the `jaren.toast` Livewire component.

```
// From Livewire:
$this->dispatch('jaren-toast', type: 'success', title: 'Saved!', message: 'All good.', duration: 4000);

// Using HasToast trait:
use jarenui\Concerns\HasToast;
$this->toast()->success('Saved!', 'Changes applied.');
$this->toast()->persistent()->action('Undo', 'undo-delete')->danger('Deleted', 'Row removed.');
```

**``**

```

    Body text here.

```

**``**

```

```

**``**

```

```

---

### Display

[](#display)

**``**

```

        View all

    $42,810

```

**``**

```

```

**``**

```

        24 tests passing…

```

---

### Full-stack Livewire components

[](#full-stack-livewire-components)

**Table** — extend `jarenui\Livewire\Table`:

```
php artisan jaren:make-table UsersTable --model=User
```

```

```

**Kanban** — extend `jarenui\Livewire\Kanban`:

```
php artisan jaren:make-kanban ProjectKanban
```

```

```

---

Calendar
--------

[](#calendar)

A full-featured calendar component for date selection. Supports single dates, multiple dates, and date ranges.

### Basic usage

[](#basic-usage)

```

{{-- With initial value --}}

{{-- Bound to Livewire --}}

```

### Multiple dates

[](#multiple-dates)

```

```

```
public array $dates = [];
```

### Date range

[](#date-range)

```

```

```
use JarenUI\DateRange;

public ?DateRange $range;

public function mount(): void
{
    $this->range = new DateRange(now(), now()->addDays(7));
}
```

### Props

[](#props)

PropType / ValuesDefault`wire:model`Livewire property binding—`value``Y-m-d` / `Y-m-d,Y-m-d` / `Y-m-d/Y-m-d`—`mode``single` `multiple` `range``single``min``Y-m-d` or `'today'`—`max``Y-m-d` or `'today'`—`unavailable`comma-separated `Y-m-d` list—`size``xs` `sm` `base` `lg` `xl` `2xl``base``months`integer1 (2 for range)`min-range`integer (days)—`max-range`integer (days)—`start-day``0`–`6` (0 = Sunday)user locale`with-today`bool`false``selectable-header`bool — click month/year to jump`false``fixed-weeks`bool — always show 6 rows`false``week-numbers`bool`false``open-to``Y-m-d`—`force-open-to`bool`false``static`bool — display only, no interaction`false``navigation`bool — show prev/next buttons`true``locale`BCP-47 string e.g. `fr`, `ja-JP`browser### DateRange object

[](#daterange-object)

```
use JarenUI\DateRange;

$range = new DateRange(now()->subDays(6), now());

$range->start();          // Carbon — start date
$range->end();            // Carbon — end date
$range->length();         // int — number of days inclusive
$range->contains($date);  // bool
$range->toArray();        // Carbon[] — one per day
(string) $range;          // '2026-05-22/2026-05-29'

// With Eloquent:
Order::whereBetween('created_at', $range)->get();
```

Persist in the session automatically:

```
use Livewire\Attributes\Session;

#[Session]
public ?DateRange $range;
```

### Events

[](#events)

The calendar dispatches an `jaren-calendar-change` Alpine event whenever the selection changes:

```
document.addEventListener('jaren-calendar-change', (e) => {
    console.log(e.detail.value); // 'Y-m-d' | string[] | {start, end}
});
```

---

Event Calendar
--------------

[](#event-calendar)

A full-featured Livewire calendar with month, week, and day views for displaying and managing events.

### Quick start

[](#quick-start-1)

Generate a calendar component:

```
php artisan jaren:make-event-calendar MeetingsCalendar --model=Meeting
```

Use in Blade:

```

```

### Static events (no database)

[](#static-events-no-database)

```
@php
use JarenUI\CalendarEvent;

$events = [
    new CalendarEvent(
        id:    1,
        title: 'Team standup',
        start: '2026-05-30 09:00',
        end:   '2026-05-30 09:30',
        color: 'blue',
        description: 'Daily sync',
    ),
];
@endphp

```

### Loading from a database

[](#loading-from-a-database)

Override `fetchEvents()` in your subclass. It receives the visible date window as two Carbon instances:

```
class MeetingsCalendar extends \JarenUI\Livewire\EventCalendar
{
    public function fetchEvents(Carbon $from, Carbon $to): array
    {
        return CalendarEvent::fromCollection(
            Meeting::whereBetween('starts_at', [$from, $to])->get(),
            startKey:       'starts_at',
            endKey:         'ends_at',
            titleKey:       'title',
            colorKey:       'category_color',
            descriptionKey: 'notes',
        );
    }
}
```

`fetchEvents()` is called automatically whenever the view or visible period changes.

### CalendarEvent

[](#calendarevent)

```
use JarenUI\CalendarEvent;

// Construct directly
$event = new CalendarEvent(
    id:          1,
    title:       'Sprint planning',
    start:       '2026-05-30 10:00',
    end:         '2026-05-30 12:00',
    color:       'green',        // blue|green|amber|red|purple|teal|pink|coral|gray
    description: 'Plan Q3 sprint backlog',
    url:         'https://notion.so/sprint-doc',
    allDay:      false,
    meta:        ['room' => 'Conf room A'],
);

// Cast from an Eloquent model
$event = CalendarEvent::from($meeting,
    startKey: 'starts_at',
    endKey:   'ends_at',
);

// Cast from a collection
$events = CalendarEvent::fromCollection(
    Meeting::inMonth(2026, 5)->get(),
    startKey: 'starts_at',
    endKey:   'ends_at',
);

// Accessors
$event->date();             // '2026-05-30'
$event->startTime();        // '10:00'
$event->endTime();          // '12:00'
$event->durationMinutes();  // 120
$event->spansMultipleDays();// false
$event->toArray();          // array for wire:model / JSON
```

### Component props

[](#component-props)

PropType / ValuesDefault`events``CalendarEvent[]` or plain arrays`[]``view``month` `week` `day``month``show-toolbar`bool`true``show-detail`bool — event detail panel`true``creatable`bool — click empty date to create`false``start-day``0`–`6` (0 = Sunday, 1 = Monday)`0``locale`BCP-47 string e.g. `fr`, `ja-JP``en``available-views`array of view namesall three`day-start-hour`integer`7``day-end-hour`integer`20`### Override in subclass

[](#override-in-subclass)

```
class MeetingsCalendar extends \JarenUI\Livewire\EventCalendar
{
    public array  $availableViews = ['month', 'week'];  // hide day view
    public bool   $creatable      = true;
    public int    $startDay       = 1;                  // Monday
    public string $view           = 'week';             // default to week view
    public int    $dayStartHour   = 8;
    public int    $dayEndHour     = 18;

    public function fetchEvents(Carbon $from, Carbon $to): array { ... }
}
```

### Events dispatched

[](#events-dispatched)

EventPayloadWhen`jaren-event-selected``{event: array}`User clicks an event`jaren-event-created``{date: 'Y-m-d'}`User clicks empty date (creatable)`jaren-event-moved``{id, date, start, end}`Drag-and-drop (frontend)`jaren-view-changed``{view, year, month}`View or period changes`jaren-date-clicked``{date: 'Y-m-d'}`Any date clickListen in Livewire:

```
#[On('jaren-event-selected')]
public function onEventSelected(array $event): void
{
    $this->selectedId = $event['id'];
}

#[On('jaren-event-created')]
public function onEventCreated(string $date): void
{
    $this->dispatch('open-modal', name: 'create-event', date: $date);
}
```

### Event colours

[](#event-colours)

ValueAppearance`blue`Blue (default)`green`Green`amber`Amber / gold`red`Red`purple`Purple`teal`Teal`pink`Pink`coral`Coral / orange`gray`Neutral gray---

Wizard
------

[](#wizard)

A multi-step form component with a progress stepper, per-step validation, and built-in navigation.

### Generate a wizard

[](#generate-a-wizard)

```
php artisan jaren:make-wizard OnboardingWizard --steps=account,plan,features,review
```

This creates:

- `app/Livewire/OnboardingWizard.php` — the PHP class
- `resources/views/livewire/onboarding-wizard/account.blade.php`
- `resources/views/livewire/onboarding-wizard/plan.blade.php`
- `resources/views/livewire/onboarding-wizard/features.blade.php`
- `resources/views/livewire/onboarding-wizard/review.blade.php`

Use in Blade:

```

```

---

### Anatomy

[](#anatomy)

```
class OnboardingWizard extends \JarenUI\Livewire\Wizard
{
    // Step definitions — id + label (+ optional icon)
    public array $steps = [
        ['id' => 'account',  'label' => 'Account'],
        ['id' => 'plan',     'label' => 'Plan'],
        ['id' => 'review',   'label' => 'Review'],
    ];

    // One property bag per step
    public array $account = ['name' => '', 'email' => ''];
    public array $plan    = ['plan_id' => null];

    // Per-step validation rules
    protected array $stepRules = [
        'account' => [
            'account.name'  => 'required|string|max:100',
            'account.email' => 'required|email',
        ],
        'plan' => [
            'plan.plan_id' => 'required',
        ],
    ];

    // Render each step from a Blade partial
    public function renderAccount(): string
    {
        return view('livewire.onboarding-wizard.account', [
            'data' => $this->account,
        ])->render();
    }

    public function renderPlan(): string
    {
        return view('livewire.onboarding-wizard.plan', [
            'data' => $this->plan,
        ])->render();
    }

    // Called when Next is pressed on the last step
    public function submit(): void
    {
        User::create($this->account);
        Subscription::create(['user_id' => auth()->id(), ...$this->plan]);

        $this->complete();  // marks wizard as done, shows success panel
    }

    // Data attached to the jaren-wizard-completed event
    protected function completedData(): array
    {
        return ['account' => $this->account, 'plan' => $this->plan];
    }
}
```

---

### Component props

[](#component-props-1)

PropType / ValuesDefault`steps``array` — step definitions`[]``variant``default` `numbered` `minimal``default``size``sm` `md` `lg``md``show-icons`bool — use icons instead of nums`false``clickable`bool — click past steps to jump`true``show-progress`bool — linear progress bar`false`---

### Stepper variants

[](#stepper-variants)

VariantAppearance`default`Numbered dots with labels, connecting line, green when done`numbered`Same as default`minimal`Small dot pills — active dot expands to a pill```

```

---

### Hooks

[](#hooks)

```
// Called when about to leave a step — useful for cleanup
protected function onStepLeaving(string $stepId): void
{
    if ($stepId === 'payment') {
        // release any held resources
    }
}

// Called just after entering a step — useful for loading data
protected function onStepEntering(string $stepId): void
{
    if ($stepId === 'review') {
        $this->summary = $this->buildSummary();
    }
}

// Called when cancel() is triggered
protected function onCancel(): void
{
    session()->forget('wizard_progress');
}
```

---

### Events dispatched

[](#events-dispatched-1)

EventPayloadWhen`jaren-wizard-step-changed``{step: string, index: int}`Any step navigation`jaren-wizard-completed``{data: array}``complete()` is called`jaren-wizard-cancelled`—`cancel()` is calledListen in another Livewire component:

```
#[On('jaren-wizard-completed')]
public function onWizardDone(array $data): void
{
    $this->redirect(route('dashboard'));
}
```

---

### Custom complete panel

[](#custom-complete-panel)

Pass a `$complete` named slot to replace the default success screen:

```

            Welcome aboard!
            Your account is ready.

                Go to dashboard →

```

---

### Navigation methods (callable from Blade)

[](#navigation-methods-callable-from-blade)

```
Continue
Back
Jump to step 1
Cancel
```

---

Combobox
--------

[](#combobox)

A versatile combobox that handles basic autocomplete, multi-select, grouped options, async server-side search, and creatable options — all in one component.

### Basic autocomplete

[](#basic-autocomplete)

```

```

### Multi-select with pills

[](#multi-select-with-pills)

```

```

### Grouped options

[](#grouped-options)

```

```

### Creatable (add new options on the fly)

[](#creatable-add-new-options-on-the-fly)

```

```

### Async server-side search

[](#async-server-side-search)

Generate a Livewire-backed combobox:

```
php artisan jaren:make-combobox UserCombobox --model=User --search=name,email
```

Use it:

```

```

Or inline without subclassing:

```

```

---

### Option shape

[](#option-shape)

Every option can be a plain string (using key as value) or a full array:

```
[
    'value'       => 1,           // required — submitted value
    'label'       => 'Jane Doe',  // required — display text
    'group'       => 'Engineering', // optional — group header
    'meta'        => 'Admin',     // optional — right-aligned text
    'description' => 'Lead engineer', // optional — sub-label (with-descriptions)
    'badge'       => 'Pro',       // optional — pill badge (with-badges)
    'initials'    => 'JD',        // optional — avatar letters (with-avatars)
    'color'       => '#185FA5',   // optional — avatar background colour
    'disabled'    => false,       // optional — grey out and prevent selection
]
```

---

### Props

[](#props-1)

PropType / ValuesDefault`options`array of strings or option arrays`[]``multiple`bool`false``searchable`bool`true``clearable`bool`true``creatable`bool — allow adding new options`false``grouped`bool — group by `option['group']``false``async`bool — fire JS search event`false``max-selected`int (multiple mode)`null``close-on-select`bool`true` (single), `false` (multiple)`with-avatars`bool`false``with-badges`bool`false``with-descriptions`bool`false``size``xs` `sm` `md` `lg` `xl` `2xl``md``placeholder`string`'Select an option…'``search-placeholder`string`'Search…'``empty-text`string`'No options found'``label`string—`hint`string—`error`string—---

### Events dispatched

[](#events-dispatched-2)

EventPayloadWhen`jaren-combobox-change``{value, option}`Any selection change`jaren-combobox-create``{value, label}`New option created`jaren-combobox-search``{query, callback}`Async mode — call `callback(results)`Listen in Alpine:

```

```

### Async JS search (no Livewire)

[](#async-js-search-no-livewire)

For pure client-side async (e.g. fetching from an API):

```

```

The `callback` receives the results array and populates the dropdown automatically.

---

### AsyncCombobox Livewire component

[](#asynccombobox-livewire-component)

Override `search()` in your subclass for full control:

```
class CountryCombobox extends \JarenUI\Livewire\AsyncCombobox
{
    public string $label       = 'Country';
    public string $placeholder = 'Search countries…';
    public int    $minChars    = 2;
    public int    $limit       = 20;

    public function search(string $query): array
    {
        return Country::where('name', 'like', "%{$query}%")
            ->orderBy('name')
            ->limit($this->limit)
            ->get()
            ->map(fn ($c) => [
                'value'    => $c->code,
                'label'    => $c->name,
                'meta'     => $c->code,
                'badge'    => $c->region,
            ])
            ->toArray();
    }
}
```

---

Customising views
-----------------

[](#customising-views)

Publish views to override any component:

```
php artisan jaren:publish --views
```

Views land in `resources/views/vendor/jarenui/`. Laravel will prefer these over the package defaults.

---

Upgrading
---------

[](#upgrading)

```
composer update leenuxus/jarenui
php artisan jaren:publish --assets --force
```

---

Contributing
------------

[](#contributing)

```
git clone https://github.com/leenuxus/jarenui
cd livewire
composer install
vendor/bin/pest
```

---

License
-------

[](#license)

MIT — see [LICENSE.md](LICENSE.md).

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance90

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

8

Last Release

52d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8747538?v=4)[Leejohn Garcia](/maintainers/leenuxus)[@leenuxus](https://github.com/leenuxus)

---

Top Contributors

[![leenuxus](https://avatars.githubusercontent.com/u/8747538?v=4)](https://github.com/leenuxus "leenuxus (22 commits)")

---

Tags

laraveluicomponentsbladelivewiretailwindalpinedark-mode

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/leenuxus-jarenui/health.svg)

```
[![Health](https://phpackages.com/badges/leenuxus-jarenui/health.svg)](https://phpackages.com/packages/leenuxus-jarenui)
```

###  Alternatives

[robsontenorio/mary

Gorgeous UI components for Livewire powered by daisyUI and Tailwind

1.5k570.6k23](/packages/robsontenorio-mary)[livewire/flux

The official UI component library for Livewire.

9577.8M138](/packages/livewire-flux)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

728176.2k14](/packages/tallstackui-tallstackui)[moonshine/moonshine

Laravel administration panel

1.3k253.1k86](/packages/moonshine-moonshine)[hasinhayder/tyro-dashboard

Tyro Dashboard - Beautiful admin dashboard for managing Tyro roles, privileges, users, and settings

5443.8k](/packages/hasinhayder-tyro-dashboard)[wendelladriel/slidewire

Create beautiful presentations powered by Livewire

1342.9k](/packages/wendelladriel-slidewire)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
