184 lines
4.9 KiB
Markdown
Executable File
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.
|