marque / deck
App layout shell for Marque platform - navigation, footer, theming
Requires
- php: ^8.3
- illuminate/support: ^13.0
- illuminate/view: ^13.0
- livewire/livewire: ^4.0
- marque/trove: ^4.0
Requires (Dev)
- laravel/pao: ^1.1
- mockery/mockery: ^1.6
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.7
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-21 13:06:58 UTC
README
App layout shell and shared Blade UI components for the Marque tracker platform.
deck provides the page shell (layout, navigation, footer) and a small set of Blade
components used across the Marque frontend packages: guise, disguise, usarrs,
parley and skipper. squidink and taxonomy deliberately use none of them, so
they work in an app without deck. It is the surface everything else
stands on, which is where the name comes from.
Formerly published as
marque/ise, andmarque/idbefore that.isewas the shared suffix ofgu-iseanddis-guise— accurate when those were its only two consumers, and misleading once it became the shell the whole suite builds on. See the upgrade guide;marque/iseis abandoned on Packagist, pointing here.
There is no UI-kit dependency. The components are plain Blade and Tailwind CSS, so consumers can publish and restyle them without forking views.
Installation
composer require marque/deck
Publish the config and views:
php artisan vendor:publish --tag=deck-config php artisan vendor:publish --tag=deck-views
Published views land in resources/views/vendor/deck and override the packaged ones.
Components
All components live under the deck:: namespace.
| Component | Purpose |
|---|---|
<x-deck::button> |
Button or link. variant (default, primary, outline, ghost, danger), size (sm, base, lg), icon, iconTrailing, href |
<x-deck::input> |
Text input. type, optional leading icon |
<x-deck::textarea> |
Multi-line input. rows |
<x-deck::field> |
Groups label + control + validation error. label, name |
<x-deck::label> |
Standalone label. for |
<x-deck::error> |
Validation error. Pass name, or content via the slot |
<x-deck::heading> |
Headings. size (sm, base, lg, xl, 2xl), optional level to force the tag |
<x-deck::text> |
Body text. as to change the tag |
<x-deck::table> |
Scroll container plus base table styling. Use standard thead/tbody/tr/td inside |
<x-deck::icon> |
Inline Heroicon by name |
Passing name to <x-deck::field> renders the label and wires up the validation error:
<x-deck::field :label="__('Name')" name="name"> <x-deck::input wire:model="name" required /> </x-deck::field>
Any extra attributes (including wire:model, class, required) pass through to the
underlying element, and class merges with the component's own classes.
Icons
<x-deck::icon> ships the Heroicons used by the Marque views — arrow-left,
arrow-down-tray, magnifying-glass, pencil, plus — inlined as SVG to avoid an
icon-package dependency. Add more by extending resources/views/components/icon.blade.php.
Navigation
The navigation renders whatever packages have registered — it names no Marque package and holds no list of its own, so a package we have never heard of appears in the nav exactly as a first-party one does.
Register from your own service provider's boot(), with a dependency on marque/trove
alone:
use Marque\Trove\Enums\Role; use Marque\Trove\Registry\NavItem; use Marque\Trove\Registry\NavRegistry; $this->app->make(NavRegistry::class)->register(new NavItem( identifier: 'acme-stats', label: 'Stats', route: 'acme.stats.index', icon: 'chart-bar', position: 40, // Visibility is an arbitrary rule, not just a role — "show this only if the // user has any invites left" is expressible. Omit it to show the item to // everyone, guests included. visible: fn (?object $user): bool => $user !== null, ));
A role gate is the common case and has a helper:
NavItem::forRole('acme-admin', 'Acme Admin', 'acme.admin', Role::Admin);
Items are ordered by position, then label. Registering a duplicate identifier throws
rather than silently replacing the existing entry.
An item whose route doesn't exist is left out of the nav rather than rendered, because
route() would throw on every page. That happens when an app registers a route at the same
method and URI as a package's, which replaces the package's route and its name.
/dashboard from a starter kit is the usual case. Before 2.0.1 every page failed with
RouteNotFoundException.
Admin screens are a separate registry — see
marque/skipper and AdminScreenRegistry. A nav item is a
top-level link evaluated per request; an admin screen is a routed panel entry with a role
floor. Same idea, different lifecycles, deliberately not one abstraction.
Styling
Components use Tailwind utility classes with dark: variants throughout. Tailwind 4
only generates classes it finds in the files it scans, and a fresh Laravel app scans
nothing under vendor/. Add an @source line to resources/css/app.css for each Marque
package that ships views:
@source '../../vendor/marque/deck/resources/views'; @source '../../vendor/marque/guise/resources/views';
php artisan marque:install writes these lines for the packages it installs.
Requirements
- PHP 8.3+
- Laravel 13+
- Livewire 4+
- Tailwind CSS
License
MIT. See LICENSE.