Files
2026-09-02 17:08:57 +00:00

184 lines
4.9 KiB
Markdown
Executable File

# Stylist Module
Tenant-aware styling module for Laravel 13 / nwidart Laravel Modules.
## Theme layout
Each theme is self-contained:
```text
resources/themes/{theme}/
├── theme.json
├── css/theme.css
└── views/
├── layouts/app.blade.php
├── components/page-hero.blade.php
└── livewire/theme-preview.blade.php
```
The active tenant/company resolves to a theme key such as `default`, `mpba`, or `abbott`.
## Rendering themed views
Use the helper from controllers, Blade components, and Livewire components:
```php
return stylist_view('layouts.app');
```
It checks views in this order:
```text
stylist-theme-{active-theme}::{view}
stylist-theme-{default-theme}::{view}
stylist::{view}
```
## Livewire
Keep the PHP component class shared and put the template in each theme:
```text
Livewire/ThemePreview.php
resources/themes/default/views/livewire/theme-preview.blade.php
resources/themes/mpba/views/livewire/theme-preview.blade.php
```
The component renders with:
```php
return stylist_view('livewire.theme-preview', ['stats' => $this->stats]);
```
## Tenant assignment
Add or use these fields on `companies`:
```text
theme_key
brand_primary
brand_secondary
brand_accent
logo_path
favicon_path
theme_settings
```
Then assign:
```php
$company->update(['theme_key' => 'mpba']);
```
## Publishing
```bash
php artisan vendor:publish --tag=stylist-config
# or
php artisan stylist:publish-assets
Themes are not published from or stored inside the module. Install them directly under `resources/themes`.
```
## Blade helpers
```blade
<html data-theme="{{ stylist()->current()->key() }}">
@themeVariables
@themeStylesheet
</html>
```
## Self-contained application themes
Application themes live in `resources/themes/{theme}` and own their runtime assets:
```text
resources/themes/example/
├── theme.json
├── css/theme.css
├── js/app.js
└── views/home.blade.php
```
Use `@themeStylesheet('css/theme.css')`, `@themeScript('js/app.js')`, or `theme_asset('images/example.svg')`. Assets are served from the selected theme directory by the `stylist.theme.asset` route; they do not need to be copied into `public/themes` or added to the global Vite inputs.
## Appearance and colour variants
Themes may declare `appearances` (`light`, `dark`, `auto`) and named `accents` in `theme.json`. Include `@themeVariables` in the document `<head>` before the theme stylesheet to prevent a flash of the wrong appearance. Add `@themeSwitcher` anywhere in a Blade layout for a ready-made runtime selector. User choices are stored in localStorage and are applied without rebuilding assets or reloading the page.
## Theme manifest compatibility
Stylist accepts versioned manifests while remaining compatible with older themes. New manifests should declare:
```json
{
"manifest_version": 1,
"key": "design-gallery",
"name": "Design Gallery"
}
```
`manifest_version` defaults to `1` when omitted. Unknown manifest fields are preserved and ignored by Stylist unless the current version explicitly uses them, allowing Theme Builder to add future metadata without preventing theme discovery.
Appearance and accent features are optional. Stylist derives the internal capability flags only when the corresponding definitions exist:
```json
{
"appearances": ["light", "dark", "system"],
"accents": ["blue", "neutral"],
"default_appearance": "system",
"default_accent": "neutral"
}
```
Legacy themes with none of these fields continue to load unchanged and do not receive appearance or accent controls.
Additional boolean capabilities may be declared explicitly:
```json
{
"capabilities": {
"marketplace": true
}
}
```
## Validate a theme
Validate an installed theme key, unpacked theme directory, or ZIP package:
```bash
php artisan stylist:validate design-gallery
php artisan stylist:validate resources/themes/design-gallery
php artisan stylist:validate ~/Downloads/design-gallery.zip
```
The command checks the manifest, required entry view, stylesheet, script, declared assets, preview and accessibility issues. It exits with a failure status when errors are found.
## Theme inheritance and diagnostics
Shared application views belong to the `common` theme. Child themes declare inheritance without copying those views:
```json
{
"name": "Dashboard",
"slug": "admin",
"extends": "common"
}
```
Resolution order is the active theme, each declared parent, the configured fallback, the common theme, module defaults, then Laravel's normal views.
Use these maintenance commands:
```bash
php artisan stylist:inspect
php artisan stylist:duplicates
php artisan stylist:doctor
php artisan stylist:create-theme customer --parent=common --name="Customer Portal"
```
`stylist:duplicates` fails when the same relative Blade task path exists in more than one theme. Add a child view only when it is a deliberate replacement; this application enforces one authoritative view per task.