| name | moonshine-components-v4 |
| description | Use when working on MoonShine v4 FormBuilder, TableBuilder, ActionButton, layout components, navigation, modals, tabs, cards, metrics, overlays, or display components. |
MoonShine v4 Components
Component Basics
Every UI element in MoonShine extends MoonShineComponent, a Blade component with admin-panel helpers.
Namespace: MoonShine\UI\Components\*
Key Base Methods (all components)
Box::make()->canSee(fn(Box $ctx) => $user->isAdmin());
Box::make()->when($condition, fn(Box $ctx) => $ctx->dark());
Box::make()->unless($condition, fn(Box $ctx) => $ctx->dark());
Box::make('Title')->customView('my-view', ['key' => 'val']);
Box::make()->onBeforeRender(fn(Box $ctx) => );
Box::make()->addAssets([new Css(Vite::asset('resources/css/block.css'))]);
Box::make()->customAttributes(['class' => 'my-class', 'data-id' => 1]);
Box::make()->class('extra-class')->style(['color: red']);
// Alpine.js attributes
Div::make([])->xData(['title' => 'Hello']); // x-data
Text::make('Title')->xModel(); // x-model
Text::make('Title')->xIf('type', 1); // x-if
Text::make('Title')->xShow('type', '1'); // x-show
// Naming (required for events)
Box::make()->name('my-box');
// Macros
MoonShineComponent::macro('myMethod', fn() => /* ... */);
MoonShineComponent::mixin(new MyNewMethods());
Creating Custom Components
php artisan moonshine:component MyComponent
FormBuilder Quick Start
use MoonShine\UI\Components\FormBuilder;
use MoonShine\Support\Enums\FormMethod;
FormBuilder::make('/crud/update')
->fields([
Text::make('Title'),
Textarea::make('Description'),
])
->fill(['title' => 'Hello', 'description' => 'World'])
->submit('Save', ['class' => 'btn-primary'])
FormBuilder::make('/crud/update')
->name('main-form')
->async(events: [
AlpineJs::event(JsEvent::TABLE_UPDATED, 'crud-table'),
AlpineJs::event(JsEvent::FORM_RESET, 'main-form'),
])
->fields([Text::make('Title')])
FormBuilder::make()
->asyncMethod('updateSomething')
->fields([Text::make('Title')])
$form->apply(fn(Model $item) => $item->save());
FormBuilder::make('/crud/update')
->fields([Text::make('Text')])
->fillCast(User::query()->first(), new ModelCaster(User::class))
FormBuilder::make('/crud/update')->precognitive()
FormBuilder::make()
->dispatchEvent(AlpineJs::event(JsEvent::OFF_CANVAS_TOGGLED, 'default'))
See references/form-table-builders.md for full FormBuilder, TableBuilder, ActionButton, and ActionGroup API.
TableBuilder Quick Start
use MoonShine\UI\Components\Table\TableBuilder;
TableBuilder::make()
->fields([
ID::make()->sortable(),
Text::make('Title'),
])
->items([
['id' => 1, 'title' => 'First'],
['id' => 2, 'title' => 'Second'],
])
->buttons([
ActionButton::make('Edit', fn() => route('edit')),
ActionButton::make('Delete', fn() => route('delete'))->bulk(),
])
TableBuilder::make()
->fields([Text::make('Title'), Text::make('Slug')])
->items($collection)
->editable()
->reorderable(url: '/reorder', key: 'id')
->sticky()
->creatable(limit: 10, label: 'Add Row')
->name('my-table')
->async()
TableBuilder::make()
->name('dashboard-table')
->fields([ID::make(), Text::make('Title')])
->async()
->lazy()
->whenAsync(fn(TableBuilder $t) => $t->items(Http::get('/api/posts')->json()))
TableBuilder::make()->fields($fields)->items([$item])->vertical()
ActionButton Patterns
use MoonShine\UI\Components\ActionButton;
ActionButton::make('Click Me', '/url')->primary()->icon('pencil')
ActionButton::make('Open')
->inModal(title: 'Edit', content: 'Content', name: 'edit-modal')
ActionButton::make('Refresh', '/endpoint')
->async(events: [AlpineJs::event(JsEvent::TABLE_UPDATED, 'my-table')])
ActionButton::make('Delete', '/delete')
->withConfirm(title: 'Sure?', content: 'This is irreversible')
ActionButton::make('Export')
->method('exportData', params: fn($item) => ['resourceItem' => $item->getKey()])
ActionGroup::make([
ActionButton::make('Inline', '/')->showInLine(),
ActionButton::make('Dropdown', '/')->showInDropdown(),
ActionButton::make('Hidden', '/')->canSee(fn() => false),
])
ActionButton::make('Mass Delete', route('mass.delete'))->bulk()
Layout Components Catalog
| Component | Namespace | Key Methods |
|---|
| Grid | Layout\Grid | make($components, $gap = 6) |
| Column | Layout\Column | make($components, colSpan: 6, adaptiveColSpan: 12) |
| Box | Layout\Box | make($label, $components), dark(), icon() |
| Div | Layout\Div | make($components) |
| Flex | Layout\Flex | make($components), justifyAlign(), itemsAlign(), withoutSpace(), wrap(), unwrap() |
| Wrapper | Layout\Wrapper | make($components) |
| Fragment | Crud\Components\Fragment | make($components), name(), updateWith(), autoUpdate($ms), withSelectorsParams() |
| Tabs | Tabs | make([Tab::make()]), vertical() |
| Tab | Tabs\Tab | make($label, $components), active(), name(), icon(), labelAttributes() |
| Collapse | Collapse | make($label, $components, $open, $persist), icon() |
| Card | Card | make($title, $thumb, $url, $values, $subtitle, $overlay), header(), actions() |
| CardsBuilder | CardsBuilder | make($items, $fields), title(), subtitle(), thumbnail(), overlay(), columnSpan(), async(), paginator() |
See references/layout-components.md for full API with examples.
Navigation Components
use MoonShine\UI\Components\Layout\{TopBar, Sidebar, BottomBar, MobileBar, Menu};
use MoonShine\UI\Components\Breadcrumbs;
TopBar::make([
Fragment::make([Menu::make()->top()])->class('menu menu--horizontal'),
Fragment::make([Profile::make(), ThemeSwitcher::make()])->class('menu-actions'),
])
// Sidebar with collapsible option
Sidebar::make([
Fragment::make([Menu::make()])->class('menu menu--vertical'),
])->collapsed()
// BottomBar
BottomBar::make([Menu::make([MenuItem::make('/', 'Home')])])
// MobileBar (place above Sidebar/TopBar)
MobileBar::make([Menu::make()->top()])
// Menu (horizontal or vertical)
Menu::make([MenuItem::make('/', 'Dashboard')])->top()
Menu::make()->withoutScrollTo()
// Breadcrumbs
Breadcrumbs::make(['/' => 'Home', '/articles' => 'Articles'])
Common Component Combinations
Form inside Modal
Modal::make(
'Create User',
static fn() => FormBuilder::make(route('users.store'))
->async()
->fields([Text::make('Name'), Email::make('Email')])
->submit('Create'),
)->name('create-modal'),
ActionButton::make('New User')->toggleModal('create-modal')
Tabs with Tables and Forms
Tabs::make([
Tab::make('List', [
TableBuilder::make()
->fields([ID::make(), Text::make('Title')])
->items($articles)
->name('articles-table')
->async()
]),
Tab::make('Create', [
FormBuilder::make(route('articles.store'))
->fields([Text::make('Title'), Textarea::make('Body')])
->async(events: [AlpineJs::event(JsEvent::TABLE_UPDATED, 'articles-table')])
]),
])
Dashboard with Metrics
use MoonShine\UI\Components\Metrics\Wrapped\ValueMetric;
Grid::make([
Column::make([
ValueMetric::make('Total Orders')
->value(fn() => Order::count())
->icon('shopping-bag')
], colSpan: 4),
Column::make([
ValueMetric::make('Revenue')
->value(fn() => Order::sum('total'))
->valueFormat(fn($v) => '$' . number_format($v))
], colSpan: 4),
Column::make([
ValueMetric::make('Completion')
->value(fn() => Order::completed()->count())
->progress(fn() => Order::count())
], colSpan: 4),
])
Fragment for Partial Updates
use MoonShine\Crud\Components\Fragment;
Fragment::make([
TableBuilder::make()->fields($fields)->items($items)->name('data-table')
])->name('data-fragment'),
ActionButton::make('Reload')
->dispatchEvent(AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'data-fragment'))
Fragment::make([ValueMetric::make('Live')->value(fn() => rand(1, 100))])
->name('live-metric')
->autoUpdate(5000)
OffCanvas Side Panel
OffCanvas::make(
'Filters',
static fn() => FormBuilder::make()
->fields([Select::make('Status')->options($statuses)])
->submit('Apply'),
'Show Filters'
)->left()->name('filter-panel'),
JS Events Reference
| Event | Constant | Use |
|---|
| Form submit | JsEvent::FORM_SUBMIT | Trigger form submission |
| Form reset | JsEvent::FORM_RESET | Reset form fields |
| Table update | JsEvent::TABLE_UPDATED | Refresh async table |
| Table row update | JsEvent::TABLE_ROW_UPDATED | Refresh single row |
| Table reindex | JsEvent::TABLE_REINDEX | Reindex table fields |
| Table row added | JsEvent::TABLE_ROW_ADDED | Append cloned row |
| Modal toggle | JsEvent::MODAL_TOGGLED | Open/close modal |
| OffCanvas toggle | JsEvent::OFF_CANVAS_TOGGLED | Open/close side panel |
| Fragment update | JsEvent::FRAGMENT_UPDATED | Refresh fragment area |
| Tab active | JsEvent::TAB_ACTIVE | Activate tab by name |
| Cards updated | JsEvent::CARDS_UPDATED | Refresh async cards |
| Toast | JsEvent::TOAST | Show notification |
use MoonShine\Support\AlpineJs;
use MoonShine\Support\Enums\JsEvent;
AlpineJs::event(JsEvent::TABLE_UPDATED, 'component-name')
AlpineJs::event(JsEvent::TOAST, params: ToastEventParams::make(ToastType::SUCCESS, 'Done'))
Cross-references
- moonshine-resources-v4: Components are used extensively in resource pages (index, form, detail). FormBuilder and TableBuilder are the foundation of CRUD pages.
- moonshine-fields-v4: Fields are the building blocks placed inside FormBuilder, TableBuilder, and CardsBuilder. Field types, validation, and relationships are covered there.
- moonshine-appearance-v4: Layout components (Sidebar, Header, Footer, TopBar) and theming/styling details for the admin panel shell.
Reference Files
references/form-table-builders.md -- Full API for FormBuilder, TableBuilder, ActionButton, ActionGroup, FieldsGroup
references/layout-components.md -- Grid, Column, Box, Flex, Tabs, Collapse, Card, CardsBuilder, Heading, Link, Button, etc.
references/overlay-components.md -- Modal, OffCanvas, Dropdown, Popover, Alert, Flash, Spinner, Loader, When
references/display-components.md -- Badge, Boolean, Color, Rating, ProgressBar, Thumbnails, Carousel, Icon, Metrics, Profile, etc.