UI Elements
Add navigation items, sidebar links and widgets to existing WemX pages from any extension, without editing core views.
Elements are WemX's injection points. Any extension can return an elements() array to add links to menus or render its own Blade views inside core pages, such as the dashboard, the order page or the customer profile.
public function elements(): array
{
return [
// a link
[
'element' => 'navigation-item',
'attributes' => ['name' => 'Status', 'href' => '/status', 'active' => 'status'],
],
// a widget (Blade view)
[
'element' => 'client-dashboard-top-view',
'view' => 'status::client_area.default.widgets.banner',
],
];
}Elements are saved to the database when the extension is enabled. After changing elements(), disable and re-enable the extension to apply the changes.
Link elements
Link elements take an attributes array.
| Element | Where it renders | Attributes |
|---|---|---|
navigation-item | Main client area navigation bar | name, href, active |
client-dropdown-item | Account dropdown (top right) | name, href, target, navigate |
footer-item | Client area footer | name, href |
admin-sidebar-item | Admin sidebar link | name, href, icon, active |
admin-sidebar-item-dropdown | Admin sidebar group with children | name, icon, active, items[] (each: name, href, icon, active, permission) |
activeis the page key that highlights the link. It's matched against theactivePageyour view passes to the layout. It can also be an array of keys.iconis a Tabler icon name, for exampleticketordownload.navigate: trueuses Livewire's SPA-style navigation.
[
'element' => 'admin-sidebar-item-dropdown',
'attributes' => [
'name' => 'Tickets',
'icon' => 'ticket',
'active' => ['tickets', 'ticket-departments'],
'items' => [
['name' => 'Overview', 'href' => '/admin/tickets', 'icon' => 'inbox', 'active' => 'tickets', 'permission' => 'admin.tickets'],
['name' => 'Departments', 'href' => '/admin/ticket-departments', 'icon' => 'folder', 'active' => 'ticket-departments', 'permission' => 'admin.ticket-departments'],
],
],
],For admin links, put a permission on each dropdown item, so staff only see the links they're allowed to open. Always protect the routes themselves with the permission: middleware too.
View elements (widgets)
View elements take a view name, and are rendered with @includeIf inside the core page.
Client area
| Element | Location | Variables |
|---|---|---|
client-dashboard-top-view | Top of the customer dashboard | $user |
client-dashboard-sidebar-view | Dashboard sidebar | $user |
client-dashboard-bottom-view | Bottom of the dashboard | $user |
client-order-top-view | Top of the order page | $order |
client-order-sidebar-bottom-view | Bottom of the order page's sidebar | $order |
client-order-bottom-view | Bottom of the order page | $order |
client-login-top-view / client-login-bottom-view | Above or below the login form | — |
client-register-top-view / client-register-bottom-view | Above or below the registration form | — |
Admin area
| Element | Location | Variables |
|---|---|---|
admin-dashboard-top-view | Top of the admin dashboard | — |
admin-dashboard-main-view | Main column of the dashboard | — |
admin-dashboard-sidebar-view | Dashboard sidebar | — |
admin-order-sidebar-view | Admin order page sidebar | $order |
admin-customer-bottom-view | Bottom of the admin customer page | $user |
admin-customer-edit-menu-item | An extra tab on the admin customer page. Takes view plus attributes: identifier, name, show | $user |
Typical uses:
- Server extensions: a Login to panel button and live usage on
client-order-top-view; remote server details onadmin-order-sidebar-view. - Modules: a summary card on the dashboard, such as "You have 1 open ticket"; a related-records table on the customer page.
- Login/registration: an SSO or Login with Discord button on
client-login-bottom-view.
Example: an order widget
@if($order->isActive() && $order->hasExternalUser())
<x-theme::card>
<x-theme::text.h4>Control panel</x-theme::text.h4>
<x-theme::text.p>Username: {{ $order->getExternalUser()->username }}</x-theme::text.p>
<x-theme::button.primary href="{{ $order->package->serverConnection->config['url'] }}" target="_blank">
Open panel
</x-theme::button.primary>
</x-theme::card>
@endif['element' => 'client-order-top-view', 'view' => 'server-acme::client.order-panel'],Views are rendered for every matching page, so check permissions and ownership inside the view before showing sensitive data.
Reading elements in a theme
Theme authors render elements with the extensionElements() helper:
@foreach(extensionElements(['client-order-top-view']) as $element)
@includeIf($element['view'], ['order' => $order])
@endforeachCustom themes should keep these loops in place, so extensions keep working.