Aller au contenu
Bondry

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.

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"]
}
  • presets alimente 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_classes entre dans la bibliothèque de classes globales sous la forme .bdg-<name>, et l'administrateur peut les modifier ensuite.
  • surfaces, site_parts et templates sont 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 :

Code
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 : hover devient :hover, focus devient :focus-visible, active devient :active ;
  • le mode sombre : l'état dark devient .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 descripteur designer. C'est ce que fait l'élément HTML du core.

La checklist avant de publier#

  1. 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.
  2. Aucun accès direct aux tables d'un autre module. Des gardes class_exists et Route::has sur chaque intégration entre modules.
  3. Les tables du module sont préfixées mod_<slug>_ et supprimées dans onUninstall.
  4. Chaque requête de collection applique la visibilité du module propriétaire.
  5. Chaque vue de widget échappe tout, émet un alt obligatoire sur les images (ou les marque comme décoratives) et définit width et height quand ils sont connus.
  6. Un widget renvoie une chaîne vide quand il n'a rien à montrer, plutôt qu'une boîte vide.
  7. Aucun script inline : la CSP du produit le bloque. Le JS va dans votre bundle.
  8. Avec le Designer désinstallé, votre module fonctionne à l'identique.
  9. Avec le Designer installé et aucune mise en page publiée, l'écran affiche exactement le Blade qu'il affichait avant.
  10. Zéro violation axe sur chaque nouvel écran, dans les deux rôles.