Core
Widgets
The Widget module provides dashboard components — stats cards, charts, embedded tables, and custom views. Widgets live in wire-core and can be composed into responsive grid layouts on any Livewire component.
A single chart widget with heading, description, and a live quarter filter.
The Widget module provides dashboard components — stats cards, charts, embedded tables, and custom views. Widgets live in wire-core and can be composed into responsive grid layouts on any Livewire component.
Every widget shares the same fluent builder, so heading, visibility, authorization, column span, and polling work identically across all four types.
Widget types at a glance
| Widget | Class | Best for |
|---|---|---|
| Stats overview | StatsOverviewWidget |
KPIs, counters, and summary metrics with optional sparklines |
| Chart | ChartWidget |
Line, bar, pie, and doughnut charts powered by Chart.js |
| Table | TableWidget |
A compact wire-table embedded inside a dashboard card |
| Custom | CustomWidget |
Any Blade view rendered as a widget |
Mix widget types freely inside a single
WithWidgetsdashboard — each widget controls its own column span, visibility, and refresh interval. See Dashboard Layout.
Table of Contents
- Widget Base
- StatsOverviewWidget
- Stat
- ChartWidget
- TableWidget
- CustomWidget
- Polling
- Dashboard Layout (WithWidgets)
- Authorization
- Widget API Reference
Widget Base
All widgets extend NyonCode\WireCore\Widgets\Widget — an abstract class implementing Htmlable.
use NyonCode\WireCore\Widgets\Widget;
Every widget supports:
->heading(?string $heading) // widget title->description(?string $description) // subtitle text->lazy(bool $lazy = true) // defer rendering->columnSpan(int|string $span) // grid column span (1-12, 'full')->extraAttributes(array $attrs) // custom HTML attributes->hidden(bool|Closure $hidden) // visibility control->visible(bool|Closure $visible) // visibility control->permission(string $permission) // authorization via Gate->authorize(string $ability) // authorization via Gate ability->authorizeUsing(Closure $callback) // custom authorization callback
Widgets render via Blade views and support toHtml() / __toString() for direct output.
StatsOverviewWidget
Grid of stat cards — ideal for KPIs, counters, and summary metrics.
use NyonCode\WireCore\Widgets\StatsOverviewWidget;use NyonCode\WireCore\Widgets\Stat;
Basic Usage
StatsOverviewWidget::make() ->heading('Overview') ->columns(3) ->stats([ Stat::make('Total Revenue', '$45,231') ->description('12% increase') ->descriptionIcon('arrow-up') ->color('success'), Stat::make('New Users', '1,234') ->description('3% decrease') ->descriptionIcon('arrow-down') ->color('danger'), Stat::make('Orders', '856') ->description('Same as last month') ->color('gray'), ])
Grid Columns
->columns(int $columns) // 1-4 columns (clamped)
Default is 3 columns. The grid is responsive.
StatsOverviewWidget API
->stats(array $stats) // array of Stat instances->getStats(): array->columns(int $columns) // grid columns (1-4)->getGridColumns(): int
Stat
Individual stat card within a StatsOverviewWidget.
use NyonCode\WireCore\Widgets\Stat;
Full Example
Stat::make('Monthly Revenue', '$12,430') ->description('8% increase from last month') ->descriptionIcon('arrow-up') ->color('success') ->icon('currency-dollar') ->chart([7, 3, 4, 5, 6, 3, 5, 8]) ->extraAttributes(['class' => 'ring-2 ring-green-200'])
Sparkline Chart
->chart(array $data) // array of numeric data points for SVG sparkline
Stat::make('Active Users', '2,847') ->chart([12, 15, 18, 14, 22, 25, 28, 32]) ->color('primary')
Stat API
Stat::make(string $label, string $value)->description(?string $description) // secondary text->descriptionIcon(?string $icon) // icon next to description->color(?string $color) // 'success', 'danger', 'warning', 'primary', 'gray'->icon(?string $icon) // stat card icon->chart(array $data) // sparkline data points (int|float)->extraAttributes(array $attrs) // custom HTML attributes->getLabel(): string->getValue(): string->getDescription(): ?string->getDescriptionIcon(): ?string->getColor(): ?string->getIcon(): ?string->getChart(): ?array->hasChart(): bool
ChartWidget
Chart widget with Chart.js integration. Supports line, bar, pie, and doughnut charts.
use NyonCode\WireCore\Widgets\ChartWidget;
Requires Chart.js. The widget renders a
<canvas>and initializes it through Alpine. Include Chart.js on the page — via CDN or your bundle — or the canvas stays empty and a console warning is logged. Dataset styling (borderColor,fill,tension, …) is passed straight through to Chart.js.
Basic Usage
ChartWidget::make() ->heading('Revenue Over Time') ->type('line') ->labels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']) ->datasets([ [ 'label' => 'Revenue', 'data' => [1200, 1900, 3000, 5000, 2300, 3200], 'borderColor' => '#3B82F6', ], ])
Chart Types
->type('line') // line chart (default)->type('bar') // bar chart->type('pie') // pie chart->type('doughnut') // doughnut chart
Dynamic Data with Closures
Datasets and labels accept Closures. The active filter value is passed as argument:
ChartWidget::make() ->heading('Sales') ->type('bar') ->filter(['2025' => '2025', '2026' => '2026'], '2026') ->labels(fn (?string $filter) => match($filter) { '2025' => ['Q1', 'Q2', 'Q3', 'Q4'], '2026' => ['Q1', 'Q2'], default => [], }) ->datasets(fn (?string $filter) => [ ['label' => 'Sales', 'data' => $filter === '2025' ? [100, 200, 150, 300] : [180, 250]], ])
Filter Dropdown
->filter(array $options, ?string $default = null)
Adds a dropdown filter on the widget. The selected value is passed to dataset/label closures.
ChartWidget::make() ->heading('Revenue') ->filter([ 'week' => 'This Week', 'month' => 'This Month', 'year' => 'This Year', ], 'month')
ChartWidget API
->type(string $type) // 'line', 'bar', 'pie', 'doughnut'->getType(): string->datasets(array|Closure $datasets) // Chart.js dataset format->getDatasets(): array->labels(array|Closure $labels) // x-axis labels->getLabels(): array->filter(array $options, ?string $default) // dropdown filter options->getFilterOptions(): ?array->hasFilter(): bool->getActiveFilter(): ?string->activeFilter(?string $filter) // set active filter programmatically
TableWidget
Embeds a wire-table inside a widget. Useful for compact data views in dashboards.
use NyonCode\WireCore\Widgets\TableWidget;
Basic Usage
TableWidget::make() ->heading('Recent Orders') ->table(fn (Table $table) => $table ->columns([ TextColumn::make('number')->searchable(), TextColumn::make('customer.name'), TextColumn::make('total')->money('CZK'), BadgeColumn::make('status')->colors([...]), ]) ->query(Order::query()->latest()->limit(10)) )
TableWidget API
->table(Closure $callback) // fn(Table $table): Table->getTableCallback(): ?Closure
CustomWidget
Renders a custom Blade view as a widget.
use NyonCode\WireCore\Widgets\CustomWidget;
Basic Usage
CustomWidget::make() ->heading('Quick Links') ->view('dashboard.quick-links') ->viewData(['links' => $this->getLinks()])
CustomWidget API
->view(string $view) // Blade view name->viewData(array $data) // data passed to view->getCustomView(): ?string
Polling
All widgets support auto-refresh via Livewire polling.
use NyonCode\WireCore\Widgets\Concerns\HasPolling;
Usage
StatsOverviewWidget::make() ->pollingInterval('30s') ->stats([...]) ChartWidget::make() ->pollingInterval('60s') ->pollingOnlyVisible() // pause polling when widget is off-screen
Polling API
->pollingInterval(?string $interval) // '5s', '10s', '30s', '60s', etc.->getPollingInterval(): ?string->isPolling(): bool->pollingOnlyVisible(bool $only = true) // only poll when visible in viewport->isPollingOnlyVisible(): bool->getPollingDirective(): ?string // returns wire:poll directive string
Polling is visibility-aware by default.
pollingOnlyVisibledefaults totrue, so widgets usewire:poll.visibleand pause requests while scrolled out of view. Call->pollingOnlyVisible(false)to keep refreshing off-screen.
Dashboard Layout (WithWidgets)
Use the WithWidgets trait on a Livewire component to compose a widget dashboard.
use NyonCode\WireCore\Widgets\Concerns\WithWidgets;use NyonCode\WireCore\Widgets\Contracts\HasWidgets;
Usage
class Dashboard extends Component implements HasWidgets{ use WithWidgets; protected function getWidgets(): array { return [ StatsOverviewWidget::make() ->columns(4) ->stats([ Stat::make('Users', User::count()), Stat::make('Orders', Order::count()), Stat::make('Revenue', '$' . number_format(Order::sum('total'), 2)), Stat::make('Products', Product::count()), ]), ChartWidget::make() ->heading('Monthly Revenue') ->type('line') ->columnSpan(2) ->labels($this->getMonthLabels()) ->datasets($this->getRevenueDatasets()), TableWidget::make() ->heading('Recent Orders') ->table(fn ($table) => $this->configureRecentOrdersTable($table)), ]; } protected function getWidgetColumns(): int { return 2; // 2-column grid layout }}