Pencil Pro
Règle de Résolution Primaire
Cette compétence doit être configurée avant la première utilisation.
Si l'utilisateur dit « exécuter l'assistant de configuration PencilPlaybook » ou demande à configurer PencilPlaybook :
→ Lisez .claude/skills/pencilplaybook/setup.md et suivez les instructions qui s'y trouvent exactement.
Si l'utilisateur dit « créer mon premier écran avec PencilPlaybook » ou demande à commencer le design :
→ Lisez .claude/skills/pencilplaybook/onboarding.md et suivez les instructions qui s'y trouvent exactement.
Résolution configurée : (exécutez la configuration pour définir cela)
Si une racine d'écran dans un fichier .pen existant ne correspond pas à votre résolution configurée, notez-la avant de modifier. Ne construisez pas sur un canvas de taille incorrecte sans signaler la déviation.
Exception courante — pages marketing : Design à 1440px quelle que soit votre résolution d'application. Les pages marketing sont consommées à des largeurs de navigateur variables — design à 1440px, vérifiez à 390px.
Démarrage de Session (Chaque Session Pencil)
1. get_editor_state() — vérifier le document actif et la sélection
2. open_document("path/to/your-file.pen") — ouvrir le fichier cible
3. get_guidelines(topic="web-app") — charger les directives de design
4. set_variables(<token map ci-dessous>) — injecter les tokens de marque
5. get_variables() — confirmer que les tokens sont stockés
6. snapshot_layout() — vérifier les dimensions du canvas
Votre token map — exécutez set_variables avec cet objet au début de chaque session. Les variables peuvent ne pas persister entre les sessions Claude Code.
{
"color-primary": "YOUR_HEX",
"color-primary-dark": "YOUR_HEX",
"color-accent": "YOUR_HEX",
"color-background": "YOUR_HEX",
"color-surface": "YOUR_HEX",
"color-border": "YOUR_HEX",
"color-text": "YOUR_HEX",
"color-text-muted": "YOUR_HEX",
"color-success": "YOUR_HEX",
"color-warning": "YOUR_HEX",
"color-error": "YOUR_HEX",
"font-sans": "YOUR_FONT",
"font-mono": "YOUR_FONT",
"font-serif": "YOUR_FONT",
"spacing-card": "24",
"spacing-gap-sm": "8",
"spacing-gap-md": "16",
"spacing-gap-lg": "24",
"spacing-gap-xl": "32",
"content-max-width": "YOUR_VALUE",
"sidebar-width": "YOUR_VALUE"
}
Après set_variables, appelez get_variables() pour confirmer que tous les tokens sont stockés.
Scripts d'Échafaudage
Neuf scripts d'échafaudage couvrant les archétypes de mise en page les plus courants. Exécutez l'assistant de configuration pour remplir les valeurs de dimensions et de couleurs ci-dessous avant utilisation.
Échafaudage A — Tableau de Bord d'Application
Métriques, KPI, flux d'activité, surveillance
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG", display:"flex", flexDirection:"column"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
statsBar=I("pageArea", {name:"StatsBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:80, bg:"STATS_BG", display:"flex", alignItems:"center", gap:24, px:32})
contentWrap=I("pageArea", {name:"ContentWrap", y:144, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_A, display:"flex", justifyContent:"center", p:32})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:24})
Après échafaudage : snapshot_layout() — vérifiez que pageArea.width et contentInner.width sont corrects.
Échafaudage B — Liste / File d'Attente d'Application
Tableaux, bibliothèques d'actifs, files d'attente, gestion des utilisateurs
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
commandStrip=I("pageArea", {name:"CommandStrip", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:52, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", gap:16, px:32})
tableWrap=I("pageArea", {name:"TableWrap", y:116, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_B, display:"flex", justifyContent:"center", px:32, pt:24})
tableInner=I("tableWrap", {name:"TableInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:0})
tableHeader=I("tableInner", {name:"TableHeader", width:SCAFFOLD_CONTENT_MAX, height:40, bg:"TABLE_HEADER_BG", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center"})
Échafaudage C — Détail / Révision d'Application
Vues détaillées à deux panneaux, flux de révision, mises en page côte à côte
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
actionBar=I("pageArea", {name:"ActionBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
contentWrap=I("pageArea", {name:"ContentWrap", y:120, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", justifyContent:"center"})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", gap:0})
leftPanel=I("contentInner", {name:"LeftPanel", width:SCAFFOLD_LEFT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"SURFACE_COLOR", borderRight:"1px solid BORDER_COLOR"})
rightPanel=I("contentInner", {name:"RightPanel", width:SCAFFOLD_RIGHT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"PAGE_BG", p:24, display:"flex", flexDirection:"column", gap:20})
Remarque : La division gauche/droite par défaut est d'environ 40/60. Ajustez selon la fonctionnalité — divisions courantes : 40/60, 38/62, 50/50.
Échafaudage D — Page Marketing
Pages d'atterrissage, pages produit — toujours 1440px de large, quelle que soit le canvas de l'application
navbar=I("root", {name:"Navbar", width:1440, height:72, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:80})
heroSection=I("root", {name:"HeroSection", y:72, width:1440, height:600, bg:"HERO_BG", display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center"})
heroContent=I("heroSection", {name:"HeroContent", width:SCAFFOLD_MARKETING_CONTENT_MAX, display:"flex", flexDirection:"column", alignItems:"center", gap:24})
section1=I("root", {name:"Section1", y:672, width:1440, height:480, bg:"SURFACE_COLOR", display:"flex", flexDirection:"column", alignItems:"center", py:80})
section1Content=I("section1", {name:"Section1Content", width:SCAFFOLD_MARKETING_CONTENT_MAX})
Les pages marketing sont mobile-first. Design à 1440px et vérifiez la mise en page à 390px de large avant la remise.
Échafaudage E — Modal / Boîte de Dialogue
Confirmations, actions destructrices, formulaires de modification rapide, panneaux latéraux
Exécutez d'abord l'échafaudage A, B ou C. Ajoutez ensuite cette modale superposée sur pageArea — ne l'insérez pas dans la racine.
backdrop=I("pageArea", {name:"ModalBackdrop", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"rgba(0,0,0,0.48)", display:"flex", alignItems:"center", justifyContent:"center"})
modal=I("backdrop", {name:"Modal", width:480, bg:"SURFACE_COLOR", borderRadius:8, border:"1px solid BORDER_COLOR", display:"flex", flexDirection:"column", overflow:"hidden"})
modalHeader=I("modal", {name:"ModalHeader", height:56, px:24, display:"flex", alignItems:"center", justifyContent:"space-between", borderBottom:"1px solid BORDER_COLOR"})
modalBody=I("modal", {name:"ModalBody", px:24, py:20, display:"flex", flexDirection:"column", gap:16})
modalFooter=I("modal", {name:"ModalFooter", height:60, px:24, display:"flex", alignItems:"center", justifyContent:"flex-end", gap:12, borderTop:"1px solid BORDER_COLOR"})
Après échafaudage : snapshot_layout() — confirmez que la modale est visible et centrée. Ajustez la largeur de la modale selon le cas d'utilisation : 380px (confirmation compacte), 480px (formulaire standard), 600px (formulaire large), 720px (détail/aperçu).
Échafaudage F — Assistant / Étapes
Formulaires multi-étapes, flux d'intégration, séquences de configuration, paiement
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
stepperBar=I("pageArea", {name:"StepperBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:60, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
contentWrap=I("pageArea", {name:"ContentWrap", y:124, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_F, display:"flex", justifyContent:"center", px:32, pt:32})
contentInner=I("contentWrap", {name:"ContentInner", width:640, display:"flex", flexDirection:"column", gap:24})
actionFooter=I("pageArea", {name:"ActionFooter", y:SCAFFOLD_WIZARD_FOOTER_Y, width:SCAFFOLD_PAGE_AREA_WIDTH, height:72, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-between", px:32})
Remarque : ContentInner fait 640px de large par défaut — formulaire à une colonne ciblé. Bouton retour à gauche, Suivant/Valider à droite dans ActionFooter (justifyContent:"space-between").
Échafaudage G — Écran Mobile
390×844px (standard iPhone 14). Utilisez ceci pour tous les écrans mobiles — codé en dur, aucune valeur de configuration requise.
statusBar=I("root", {name:"StatusBar", width:390, height:44, bg:"PAGE_BG"})
navBar=I("root", {name:"NavBar", y:44, width:390, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:16})
scrollContent=I("root", {name:"ScrollContent", y:100, width:390, height:688, bg:"PAGE_BG", display:"flex", flexDirection:"column", overflow:"hidden"})
contentPad=I("scrollContent", {name:"ContentPad", width:390, display:"flex", flexDirection:"column", gap:16, px:16, pt:16})
bottomNav=I("root", {name:"BottomNav", y:788, width:390, height:56, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-around"})
Remarque : Supprimez statusBar et définissez navBar.y=0 si l'interface système n'est pas affichée. Supprimez bottomNav pour les applications sans navigation par onglets. Les cibles tactiles dans cet échafaudage doivent être ≥44×44px.
Échafaudage H — Formulaire / Saisie de Données
Pages de paramètres, édition de profil, saisie de données intensive — formulaire centré à une colonne
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-between", px:32})
formWrap=I("pageArea", {name:"FormWrap", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", justifyContent:"center", px:32, pt:32})
formInner=I("formWrap", {name:"FormInner", width:600, display:"flex", flexDirection:"column", gap:28})
formSection=I("formInner", {name:"FormSection1", display:"flex", flexDirection:"column", gap:16})
formActions=I("formInner", {name:"FormActions", display:"flex", gap:12, justifyContent:"flex-end"})
Remarque : La largeur de FormInner par défaut est de 600px. Utilisez 480px pour les flux simples, 800px pour les mises en page larges à deux colonnes. Ajoutez plus de nœuds FormSection dans formInner pour regrouper les champs connexes.
Échafaudage I — État Vide / Étape d'Intégration
Vues sans données, invites de première utilisation, découverte de fonctionnalités, écrans vierges
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
emptyCenter=I("pageArea", {name:"EmptyCenter", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", alignItems:"center", justifyContent:"center"})
emptyContent=I("emptyCenter", {name:"EmptyContent", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:20})
illustrationArea=I("emptyContent", {name:"IllustrationArea", width:200, height:160, borderRadius:12, bg:"SURFACE_COLOR", border:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
textStack=I("emptyContent", {name:"TextStack", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:8})
emptyActions=I("emptyContent", {name:"EmptyActions", display:"flex", gap:12})
Remarque : Remplacez IllustrationArea par G("illustrationArea", "ai", "your prompt") pour générer une illustration. Gardez le texte de l'état vide court : un titre (16–18px), une ligne de support (14px atténué), un bouton d'action principal.
Flux de Travail Principaux
Flux de Travail 1 : Archéologie du Canvas
Utilisez quand : « qu'est-ce qu'il y a dans ce fichier .pen ? » → vérifiez les dimensions et la structure d'un fichier .pen existant.
1. get_editor_state() → notez le document actif
2. snapshot_layout() → prenez un instantané du canvas pour inspection
3. Obtenez les dimensions du canvas : hauteur, largeur, éléments enfants
4. Notez les écarts de résolution
Flux de Travail 2 : Injection de Marque
1. set_variables(<token map>) → injectez les tokens de marque
2. get_variables() → confirmez que les tokens sont stockés
3. Vérifiez que les tokens correspondent au thème prévu
Flux de Travail 3 : Responsivité
Règle générale : les points de rupture sont à 640px, 1024px, 1440px. Utilisez les échafaudages G (mobile) pour mobile, les échafaudages standard pour desktop.
Pour les vérifications de responsivité :
1. Après le design à 1440px, dupliquez le canvas et redimensionnez à 390px
2. Vérifiez : les éléments ne doivent pas se chevaucher, le texte doit rester lisible, les cibles tactiles doivent être ≥44×44px
3. Ajustez les mises en page flexibles pour s'adapter à la largeur réduite
Conseils de Conception
- Utilisez les échafaudages systématiquement — ils encapsulent des années de décisions de conception. Ne les écartez pas sans justifier pourquoi.
- Préférez les tokens à la surcharge visuelle — utilisez
C("votre.text", tokens)plutôt que des valeurs codées en dur. - Conception mobile-first — si le design doit être responsive, commencez par l'échafaudage G, puis développez.
- Psychologie perceptuelle — regroupez les éléments connexes visuellement (Loi de Proximité), utilisez des en-têtes cohérents (Loi de Similarité), laissez de l'espace autour des éléments importants (Loi de l'Espace).
- Accessibilité — le contraste du texte doit être ≥4,5:1, les cibles tactiles ≥44×44px, n'utilisez pas la couleur seule pour véhiculer l'information.
- Consistance — utilisez les mêmes espacements, polices et couleurs dans tout le design. Les tokens de l'assistant de configuration aident à cela.
Journal des Modifications
- v1.0.0 — Version initiale avec 9 échafaudages, assistant de configuration, flux de travail d'archéologie du canvas.