PHPackages                             bernskioldmedia/laravel-livewire-widgets - 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. [Admin Panels](/categories/admin)
4. /
5. bernskioldmedia/laravel-livewire-widgets

ActiveLibrary[Admin Panels](/categories/admin)

bernskioldmedia/laravel-livewire-widgets
========================================

A framework for adding self-contained Livewire-powered widgets to your application.

0.3.0(2mo ago)01822MITPHPPHP ^8.2|^8.3|^8.4CI passing

Since Dec 29Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/bernskiold/laravel-livewire-widgets)[ Packagist](https://packagist.org/packages/bernskioldmedia/laravel-livewire-widgets)[ Docs](https://github.com/bernskioldmedia/laravel-livewire-widgets)[ RSS](/packages/bernskioldmedia-laravel-livewire-widgets/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (16)Versions (8)Used By (0)

A framework for adding self-contained Livewire-powered widgets to your application.
===================================================================================

[](#a-framework-for-adding-self-contained-livewire-powered-widgets-to-your-application)

[![Latest Version on Packagist](https://camo.githubusercontent.com/902ce6fa5e9b45f073302f1937ef335aa5d427d56ce7a83b31bd500f2b6836c4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6265726e736b696f6c646d656469612f6c61726176656c2d6c697665776972652d776964676574732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bernskioldmedia/laravel-livewire-widgets)[![GitHub Tests Action Status](https://camo.githubusercontent.com/15d3d1fff05906d81a879c34302400c54e4d0645dc0a7fc52282b3def0bec868/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6265726e736b696f6c646d656469612f6c61726176656c2d6c697665776972652d776964676574732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/bernskioldmedia/laravel-livewire-widgets/actions?query=workflow%3Arun-tests+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/e2036dcddf73070d95916172af3d06e5a21e6481ab3274180a1dd1fcb99f9093/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6265726e736b696f6c646d656469612f6c61726176656c2d6c697665776972652d776964676574732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bernskioldmedia/laravel-livewire-widgets)

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

[](#installation)

You can install the package via composer:

```
composer require bernskioldmedia/laravel-livewire-widgets
```

After requiring the package, you should import the base styles to your stylesheet. You can do this by importing the provided `widgets.css` file in your `app.scss` file:

```
@import "../../vendor/bernskioldmedia/laravel-livewire-widgets/resources/css/widgets.css";

/* Your styles */
```

**Tip:** Your import should be placed above any Tailwind imports to ensure that the styles are applied correctly. We'd recommend using the `@import` syntax instead of `@tailwind` when loading Tailwind's base, components and utilities.

After installing the package you should review the installation instructions for the [Laravel Highcharts](https://github.com/bernskioldmedia/laravel-highcharts) package if you plan on using the Chart Widget.

### Publishing Config and Views

[](#publishing-config-and-views)

You don't typically need to publish either the config file or the views.

You can publish the config file with:

```
php artisan vendor:publish --tag="laravel-livewire-widgets-config"
```

This is the contents of the published config file:

```
return [
    'livewire' => [
        'views' => [
            'chart-widget' => 'livewire-widgets::chart-widget',
            'statistic-widget' => 'livewire-widgets::statistic-widget',
        ],

        'skeletons' => [
            'base' => 'livewire-widgets::skeletons.widget',
            'chart-widget' => 'livewire-widgets::skeletons.chart-widget',
            'statistic-widget' => 'livewire-widgets::skeletons.statistic-widget',
        ],
    ],
];
```

Optionally, you can publish the views using

```
php artisan vendor:publish --tag="laravel-livewire-widgets-views"
```

Usage
-----

[](#usage)

### Supported Widget Types

[](#supported-widget-types)

This package supplies two opinionated widget, and one base widget that you can use to build your own.

- **Chart Widget.** A widget that displays a chart using our Laravel Highcharts package (bundled).
- **Statistic Widget.** A widget that displays a statistic with a label, a value and a change indicator.

See below for how to use each of these.

### Creating a Widget

[](#creating-a-widget)

To create a new widget create a new Livewire class that extends either one of the widget type classes, or the base `Widget` class. A good place to put these is in the `App\Livewire\Widgets` namespace.

**Note:** You do not need to create a view/blade file for your widget if you are using one of the pre-defined widgets ( see the list above).

#### Lazy Loading

[](#lazy-loading)

Unfortunately we haven't found a good way to default to lazy loading. As such as we recommend that you add the `#[Lazy]` attribute to your widget classes.

```
use BernskioldMedia\Laravel\Widgets\Widget;
use Livewire\Attributes\Lazy;

#[Lazy]
class MyWidget extends Widget
{
    //
}
```

#### Rendering a widget

[](#rendering-a-widget)

To render a widget, you can use the `livewire` Blade directive as any other Livewire component:

```

```

#### Chart Widget

[](#chart-widget)

Chart widgets are widgets that display a chart. They extend the `ChartWidget` class. To use this widget you must first set up the [Laravel Highcharts](https://github.com/bernskioldmedia/laravel-highcharts) package. Refer to its documentation for how to create charts.

To create a chart widget, extend the `ChartWidget` class and implement the `getChart` method.

```
use BernskioldMedia\Laravel\Widgets\ChartWidget;
use BernskioldMedia\LaravelHighcharts\Data\Chart;
use BernskioldMedia\LaravelHighcharts\Data\Series;

class MyChartWidget extends ChartWidget
{
    protected function getChart(): Chart
    {
        return Chart::create('line', 'highcharts')
            ->setTitle('My Chart')
            ->setSeries(Series::make([
                [1,2,3]
            ]));
    }
}
```

### Statistic Widget

[](#statistic-widget)

The Statistic Widget is a widget that displays a statistic with a label, a value and a change indicator.

To create a statistic widget, extend the `StatisticWidget` class and implement the `getValue` method.

```
use BernskioldMedia\Laravel\Widgets\StatisticWidget;

class MyStatisticWidget extends StatisticWidget
{
    protected function getValue(): int|float|null
    {
        return 123;
    }
}
```

To display a change indicator, implement the `ComparesValues` interface and return the previous value from the `getPreviousValue` method.

```
use BernskioldMedia\Laravel\Widgets\StatisticWidget;
use BernskioldMedia\Laravel\Widgets\Contracts\ComparesValues;

class MyStatisticWidget extends StatisticWidget implements ComparesValues
{
    protected function getValue(): int|float|null
    {
        return 123;
    }

    protected function getPreviousValue(): int|float|null
    {
        return 100;
    }
}
```

There are a few additional properties that you can set on the widget:

- `$showChange` - Default to true. Whether to show the change indicator.
- `$changeAsPercentage` - Default to true. Whether to show the change as a percentage (true) or absolute value (false).
- `$invertedChange` - Default to false. Whether a positive change is good (true) or bad (false).

### Widget Sizes

[](#widget-sizes)

Widgets are rendered in a responsive grid and can be rendered in different widths and heights.

All widths are available in the `WidgetWidths` enum, which we recommend over hardcoded string values. These equal:

- `1/4` - 25% width
- `1/3` - 33% width
- `1/2` - 50% width
- `2/3` - 66% width
- `3/4` - 75% width
- `1/1` - 100% width

Heights are based on the number of rows the widget should take up. As such, the height is dependent on the height of surrounding widgets. All heights are available in the `WidgetHeights` enum, which we recommend over hardcoded strings.

The following heights are available:

- `1` - 1 row
- `2` - 2 rows
- `3` - 3 rows
- `4` - 4 rows

**Note:** Rows do not have a base height by themselves.

By default widgets are rendered in a 1/4 width and 1 row height. You can change this by overriding the `width`and `height` properties on your widget.

```
class MyWidget extends Widget
{
    protected string $width = WidgetWidths::Half->value;
    protected string $height = WidgetHeights::One->value;
}
```

You can also set the width and height when loading the widget in your view:

```

```

### Adding a title

[](#adding-a-title)

You can add support for a title by implementing the `HasTitle` trait on your widget. The Chart Widget and Statistic Widget both have this included.

This trait adds a `title` property to your widget. You can set this property when loading the widget in your view, which offers a simple way of customizing the title on load. You may also provide a default title by returning a string from the `defaultTitle` method.

```
use BernskioldMedia\Laravel\Widgets\Concerns\HasTitle;

class MyWidget extends Widget
{
    use HasTitle;

    protected static function defaultTitle(): string
    {
        return 'My Widget';
    }
}
```

The title is available in your view as `$widgetTitle`.

### Adding a description

[](#adding-a-description)

You can add support for a description by implementing the `HasDescription` trait on your widget. The Chart Widget and Statistic Widget both have this included. This trait adds a `description` property to your widget. You can set this property when loading the widget in your view, which offers a simple way of customizing the description on load. You may also provide a default description by returning a string from the `defaultDescription` method.

```
use BernskioldMedia\Laravel\Widgets\Concerns\HasDescription;

class MyWidget extends Widget
{
    use HasDescription;

    protected static function defaultDescription(): string
    {
        return 'My Widget';
    }
}
```

The description is available in your view as `$widgetDescription`.

### Supporting Filters

[](#supporting-filters)

You can add support for filters by implementing the `Filterable` trait on your widget as well as the `SupportsFilters`interface. This trait adds a `filters` property to your widget. You can set this property when loading the widget in your view, which offers a simple way of customizing the filters on load.

You may also provide default filters by returning an array from the `defaultFilters` method.

```
use BernskioldMedia\Laravel\Widgets\Concerns\Filterable;
use BernskioldMedia\Laravel\Widgets\Contracts\SupportsFilters;

class MyWidget extends Widget implements SupportsFilters
{
    use Filterable;

    protected static function defaultFilters(): array
    {
        return [
            'startDate' => today()->subDays(7),
            'endDate' => today(),
        ];
    }
}
```

The default filters will be overridden with any filters you pass when loading the widget.

You may also provide a list of forced filters which cannot be overridden by the user when loading the widget. You do this by overriding the `forcedFilters` method.

```
use BernskioldMedia\Laravel\Widgets\Concerns\Filterable;
use BernskioldMedia\Laravel\Widgets\Contracts\SupportsFilters;

class MyWidget extends Widget implements SupportsFilters
{
    use Filterable;

    protected static function forcedFilters(): array
    {
        return [
            'startDate' => today()->subDays(7),
            'endDate' => today(),
        ];
    }
}
```

The trait also adds convenience methods for interacting with filters:

```
// Get all filters
$this->getFilters();

// Get a specific filter (or null if it doesn't exist)
$this->getFilter('startDate');

// Get a specific filter or return a custom value
$this->getFilter('startDate', today());

// Set a filter
$this->setFilter('startDate', today());

// Set multiple filters
$this->setFilters([
    'startDate' => today(),
    'endDate' => today()->addDays(7),
]);

// Check if a filter exists
$this->hasFilter('startDate');

// Remove a filter
$this->removeFilter('startDate');

// Clear all custom filters.
$this->resetFilters();
```

### Defining a custom view

[](#defining-a-custom-view)

Because of the helper methods we include, adding a view is slightly different. Instead of using the `render` method, you define the static `view` method and return the view name.

```
protected static function view(): string
{
    return 'widgets.my-widget';
}
```

You can pass additional data to the view by returning an array from the `getViewData` method:

```
protected static function getViewData(): array
{
    return [
        'myData' => 'Test',
    ];
}
```

### Placeholders

[](#placeholders)

The package ships with default placeholders for each widget type, as well as a plain base widget placeholder. To use your our placeholder view, return the view name from the `placeholderView` method:

```
protected static function placeholderView(): string
{
    return 'widgets.skeletons.my-widget';
}
```

You can pass data to the placeholder view by returning an array from the `placeholderData` method. You should merge your data with the parent method's data.

```
protected static function getPlaceholderData(): array
{
    return array_merge(
        parent::getPlaceholderData(),
        [
            'title' => 'My Widget',
        ]
    );
}
```

### Customizing the Styles

[](#customizing-the-styles)

We have tried to make the styles we ship as unopinionated as possible to only provide the structure you most likely will need regardless of appearance. As such, you will want to apply additional customization to the widget classes to make them fit your application.

You may customize the widget grid gap and widget padding by using the following CSS variables:

```
:root {
    --ww-widgets-gap: 1.5rem;
    --ww-widget-padding: 1rem;
}
```

#### Responsive Widget Grid

[](#responsive-widget-grid)

By default, widgets are rendered in a responsive grid. The grid is based on CSS Grid and is responsive in a slightly opinionated way. This means that each widget only has a specific width configured, which is the width it will take up on desktop. On smaller screens, the width is automatically adjusted.

The base grid is:

- 2 columns by default
- 4 columns on `md` screens (and above)
- 12 columns on `lg` screens (and above)

Each Widget Width corresponds to a number of columns:

- `1/4` - 1 column
- `1/3` - 1 column (base), 2 columns (`md`), 4 columns (`lg`)
- `1/2` - 1 column (base), 2 columns (`md`), 6 columns (`lg`)
- `2/3` - 2 columns (base), 8 columns (`lg`)
- `3/4` - 2 columns (base), 3 columns (`md`), 9 columns (`lg`)
- `1/1` - 2 columns (base), 4 columns (`md`), 12 columns (`lg`)

You may customize this setup by overriding the corresponding width classes in your own stylesheet.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Credits
-------

[](#credits)

- [Bernskiold Media](https://github.com/bernskioldmedia)
- [Erik Bernskiold](https://github.com/erikbernskiold)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

44

—

FairBetter than 91% of packages

Maintenance87

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity55

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 ~424 days

Total

3

Last Release

63d ago

PHP version history (2 changes)0.1.0PHP ^8.2

0.2.0PHP ^8.2|^8.3|^8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8409819?v=4)[Bernskiold](/maintainers/bernskiold)[@bernskiold](https://github.com/bernskiold)

---

Top Contributors

[![ErikBernskiold](https://avatars.githubusercontent.com/u/1166728?v=4)](https://github.com/ErikBernskiold "ErikBernskiold (38 commits)")

---

Tags

dashboardlaravellaravel-packagelivewirewidgetslaravellivewirewidgetsbernskioldmedia

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/bernskioldmedia-laravel-livewire-widgets/health.svg)

```
[![Health](https://phpackages.com/badges/bernskioldmedia-laravel-livewire-widgets/health.svg)](https://phpackages.com/packages/bernskioldmedia-laravel-livewire-widgets)
```

###  Alternatives

[filament/support

Core helper methods and foundation code for all Filament packages.

2328.3M218](/packages/filament-support)[tallstackui/tallstackui

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

721160.4k12](/packages/tallstackui-tallstackui)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

119.2k](/packages/tomshaw-electricgrid)[andreia/filament-ui-switcher

Add a modal with options to switch between different UI layouts and styles (colors, fonts, font sizes).

245.8k](/packages/andreia-filament-ui-switcher)[mwguerra/web-terminal

A web-based terminal component for Filament/Laravel with command whitelisting and multiple connection types

284.5k](/packages/mwguerra-web-terminal)[a2insights/filament-saas

Filament Saas for A2Insights

171.5k](/packages/a2insights-filament-saas)

PHPackages © 2026

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