Le Designer pour les auteurs
Les contrats qu'un module ou un thème utilise pour étendre le constructeur de pages, avec la référence des contrôles de schéma.
Ceci est le guide pour étendre le Designer, pas pour l'implémenter. La règle
qui traverse toute la page : chaque enregistrement décrit ici est inerte
sans le Designer. Vous enregistrez dans votre propre boot(), et si le
module n'est pas installé, rien ne se passe. Un module ne dépend jamais du
constructeur de pages pour fonctionner.
Où vivent les contrats#
Ils sont dans le core, à côté des autres registres. Le module Designer les consomme.
| Contrat | Pour |
|---|---|
App\Support\Widgets |
Les éléments déplaçables dans l'éditeur |
App\Support\Designer\Surfaces |
Les écrans dont le Designer peut remplacer le milieu |
App\Support\Designer\Collections |
Les sources de données de l'élément boucle |
App\Support\Designer\DynamicTags |
Les valeurs dynamiques dans les contrôles |
App\Support\Designer\Conditions |
Les règles d'affichage par nœud et par document |
App\Support\Designer\FormActions |
Les actions après l'envoi d'un formulaire |
App\Support\Designer\Tokens |
La lecture des tokens du thème actif |
App\Support\Breadcrumbs |
Le fil que lit l'élément fil d'Ariane |
Tout est statique et enregistré dans boot(). Les libellés sont toujours des
callables : au moment du boot, votre fichier de langue peut ne pas être encore
chargé.
Les enregistrements côté module sont traités dans Widgets et surfaces. Ce qui suit est le côté thème et la matière de référence.
Les tokens du thème#
Le Designer ne crée pas de tokens : il lit ceux que le thème actif déclare.
Chaque contrôle de customizer.json qui porte un var devient un token
proposé dans les sélecteurs de couleur, de police, de rayon et d'espacement.
La chaîne du parent vers l'enfant est résolue avec eux, donc un thème enfant
qui surcharge --color-primary change toute mise en page qui pointe vers ce
token, sans que la mise en page soit touchée.
Quand le thème ne couvre pas quelque chose, l'administrateur crée une variable
Designer (--bd-*), stockée par le module dans sa propre feuille de style. En
changer une ne republie rien.
themes/<slug>/designer.json#
Optionnel, à côté de customizer.json.
{
"presets": {
"spacing": ["0", "0.25rem", "0.5rem", "1rem", "1.5rem", "2rem", "3rem"],
"shadows": { "soft": "0 1px 2px rgba(15, 23, 42, 0.06)" },
"type_scale": { "sm": "0.875rem", "base": "1rem", "lg": "1.125rem" }
},
"global_classes": [
{ "name": "card", "styles": { "desktop": { "normal": {
"background-color": { "token": "--color-background" },
"border-radius": { "token": "--radius" },
"padding": "1.5rem"
}}}}
],
"surfaces": { "blog.index": "designer/blog-index.json" },
"site_parts": { "header": "designer/header.json" },
"templates": ["designer/templates/hero-1.json"]
}
presetsalimente les curseurs et les sélecteurs de l'inspecteur. Un thème avec sa propre échelle typographique fait proposer cette échelle par l'éditeur, au lieu de valeurs brutes.global_classesentre dans la bibliothèque de classes globales sous la forme.bdg-<name>, et l'administrateur peut les modifier ensuite.surfaces,site_partsettemplatessont des mises en page que votre thème suggère. Activer le thème propose de les importer ; cela n'écrase jamais sans confirmation ce que l'utilisateur a déjà publié, et les mises en page vivent en base de données, donc changer de thème préserve le travail.
Une valeur de style peut être brute ("1.5rem") ou pointer vers un token
({ "token": "--radius" }). Préférez le token : c'est lui qui fait qu'une
mise en page suit un changement de thème.
La cascade#
De la plus faible à la plus forte :
CSS du thème -> CSS du module -> variables Designer ->
feuille de style du document -> CSS personnalisé du thème
Les règles de la feuille de style compilée du document :
- pas de
!important; - un sélecteur par nœud (
.bd-<id>) et un par classe globale (.bdg-<name>), les deux avec la même spécificité, donc l'ordre décide et le style local d'un nœud vient toujours après la classe globale ; - le desktop d'abord, les media queries de la plus large à la plus étroite, ce qui fait fonctionner l'héritage du desktop vers la tablette vers le mobile sans astuce de spécificité ;
- les états :
hoverdevient:hover,focusdevient:focus-visible,activedevient:active; - le mode sombre : l'état
darkdevient.dark .bd-<id>. Un thème qui déclare la prise en charge du mode sombre n'a rien d'autre à faire.
Référence des contrôles de schéma#
Voici les valeurs de type acceptées dans designer.schema sur un widget,
dans filters sur une collection et dans schema sur une action de
formulaire. label est toujours une clé de langue.
| Type | Valeur stockée | Options du descripteur |
|---|---|---|
text |
chaîne | maxlength, placeholder |
textarea |
chaîne | rows |
code |
chaîne | monospace, jamais exécutée |
richtext |
HTML assaini | l'éditeur du core, à la demande |
number |
int ou float | min, max, step |
slider |
chaîne avec une unité ("24px") |
min, max, unit, presets, token_group |
select |
chaîne | options |
select2 |
liste de chaînes | options, sélection multiple |
choose |
chaîne | options, radios dessinés en boutons |
switcher |
bool | |
color |
chaîne ou {token} |
la palette du thème dans le sélecteur |
media |
{path,width,height} |
accept, meta |
icon |
nom d'icône ou SVG téléversé | |
url |
chaîne | schémas sûrs uniquement |
gallery |
liste de {image,alt,caption} |
|
repeater |
liste de maps | fields, add |
dimensions |
{top,right,bottom,left} |
quatre côtés avec un bouton de liaison |
font |
chaîne | les familles du thème |
popup |
id de popup | sélecteur de popups publiées |
heading |
rien | un libellé de section |
divider |
rien | un filet |
Les contrôles qui portent une seule valeur (text, textarea, url,
media, number, slider, color) reçoivent automatiquement le bouton de
dynamic tag.
Les permissions#
Le Designer n'invente pas un système de permissions par module. Il utilise la matrice des groupes :
- une surface est restreinte via
designer.surfaces.<module>, construite automatiquement à partir des surfaces que vous avez enregistrées : rien à faire dans votre module ; - un élément individuel est restreint par l'administrateur, dans Designer > Element Manager ;
- pour exiger une permission avant qu'un nœud de votre élément puisse être
enregistré, déclarez
'requires' => 'unfiltered_html'dans le descripteurdesigner. C'est ce que fait l'élément HTML du core.
La checklist avant de publier#
- Chaque libellé est un callable qui retourne
__('...')depuis les fichiers de langue de votre module. Aucune chaîne codée en dur en PHP, Blade ou JS. - Aucun accès direct aux tables d'un autre module. Des gardes
class_existsetRoute::hassur chaque intégration entre modules. - Les tables du module sont préfixées
mod_<slug>_et supprimées dansonUninstall. - Chaque requête de collection applique la visibilité du module propriétaire.
- Chaque vue de widget échappe tout, émet un
altobligatoire sur les images (ou les marque comme décoratives) et définitwidthetheightquand ils sont connus. - Un widget renvoie une chaîne vide quand il n'a rien à montrer, plutôt qu'une boîte vide.
- Aucun script inline : la CSP du produit le bloque. Le JS va dans votre bundle.
- Avec le Designer désinstallé, votre module fonctionne à l'identique.
- Avec le Designer installé et aucune mise en page publiée, l'écran affiche exactement le Blade qu'il affichait avant.
- Zéro violation axe sur chaque nouvel écran, dans les deux rôles.