Pencil Pro
Regra de Resolução Primária
Este skill deve ser configurado antes do primeiro uso.
Se o usuário disser "executar o assistente de configuração do PencilPlaybook" ou pedir para configurar o PencilPlaybook:
→ Leia .claude/skills/pencilplaybook/setup.md e siga as instruções exatamente.
Se o usuário disser "construir minha primeira tela com o PencilPlaybook" ou pedir para começar a projetar:
→ Leia .claude/skills/pencilplaybook/onboarding.md e siga as instruções exatamente.
Resolução configurada: (executar configuração para definir isso)
Se a raiz de uma tela em um arquivo .pen existente não corresponder à sua resolução configurada, anote isso antes de editar. Não construa sobre um canvas de tamanho errado sem sinalizar o desvio.
Exceção comum — páginas de marketing: Projete em 1440px independentemente da resolução do seu aplicativo. Páginas de marketing são consumidas em larguras de navegador variáveis — projete em 1440px, verifique em 390px.
Inicialização de Sessão (Toda Sessão Pencil)
1. get_editor_state() — verificar documento ativo e seleção
2. open_document("path/to/your-file.pen") — abrir arquivo de destino
3. get_guidelines(topic="web-app") — carregar diretrizes de design
4. set_variables(<mapa de tokens abaixo>) — injetar tokens de marca
5. get_variables() — confirmar tokens armazenados
6. snapshot_layout() — verificar dimensões do canvas
Seu mapa de tokens — execute set_variables com este objeto no início de cada sessão. As variáveis podem não persistir entre sessões do 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"
}
Após set_variables, chame get_variables() para confirmar que todos os tokens estão armazenados.
Scripts Scaffold
Nove scripts scaffold cobrindo os arquétipos de layout mais comuns. Execute o assistente de configuração para preencher os valores de dimensão e cor abaixo antes de usar.
Scaffold A — Dashboard do Aplicativo
Métricas, KPIs, feed de atividade, monitoramento
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})
Após scaffold: snapshot_layout() — verifique se pageArea.width e contentInner.width estão corretos.
Scaffold B — Lista / Fila do Aplicativo
Tabelas, bibliotecas de ativos, filas, gerenciamento de usuários
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"})
Scaffold C — Detalhe / Revisão do Aplicativo
Visualizações de detalhe em dois painéis, fluxos de revisão, layouts lado a lado
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})
Nota: A divisão esquerda/direita padrão é ~40/60. Ajuste por funcionalidade — divisões comuns: 40/60, 38/62, 50/50.
Scaffold D — Página de Marketing
Páginas de destino, páginas de produto — sempre com 1440px de largura, independentemente do canvas do aplicativo
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})
Páginas de marketing são mobile-first. Projete em 1440px e verifique o layout em largura de 390px antes da entrega.
Scaffold E — Modal / Diálogo
Confirmações, ações destrutivas, formulários de edição rápida, painéis laterais
Execute o Scaffold A, B ou C primeiro. Em seguida, adicione este modal sobreposto na páginaArea — não insira na raiz.
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"})
Após scaffold: snapshot_layout() — confirme que o modal está visível e centralizado. Ajuste a largura do modal por caso de uso: 380px (confirmação compacta), 480px (formulário padrão), 600px (formulário amplo), 720px (detalhe/pré-visualização).
Scaffold F — Assistente / Passo a Passo
Formulários de várias etapas, fluxos de integração, sequências de configuração, checkout
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})
Nota: ContentInner tem 640px de largura por padrão — formulário de coluna única focado. Botão Voltar à esquerda, Próximo/Enviar à direita em ActionFooter (justifyContent:"space-between").
Scaffold G — Tela Mobile
390×844px (padrão iPhone 14). Use para todas as telas mobile — codificado, nenhum valor de configuração necessário.
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"})
Nota: Remova statusBar e defina navBar.y=0 se não estiver exibindo a interface do sistema. Remova bottomNav para aplicativos sem navegação por abas. Os alvos de toque dentro deste scaffold devem ter ≥44×44px.
Scaffold H — Formulário / Entrada de Dados
Páginas de configurações, edição de perfil, entrada intensa de dados — coluna única, formulário centralizado
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"})
Nota: A largura padrão do FormInner é 600px. Use 480px para fluxos simples, 800px para layouts amplos de duas colunas. Adicione mais nós FormSection dentro de formInner para agrupar campos relacionados.
Scaffold I — Estado Vazio / Etapa de Integração
Visualizações sem dados, prompts de primeiro uso, descoberta de funcionalidades, telas em branco
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})
Nota: Substitua IllustrationArea por G("illustrationArea", "ai", "your prompt") para gerar uma ilustração. Mantenha o texto do estado vazio curto: um título (16–18px), uma linha de apoio (14px muted), um CTA primário.
Fluxos de Trabalho Principais
Fluxo 1: Arqueologia de Canvas
Use quando: "o que tem neste arquivo .pen?" ou "descreva o layout atual"
1. open_document("path/to/file.pen")
2. get_editor_state()
Descreva a estrutura retornada — número de elementos, hierarquia de aninhamento, sistema de grade usado, quaisquer anotações. Se o canvas estiver vazio: "Canvas vazio — dimensões {X}x{Y}, nenhum elemento renderizado." Se houver um scaffold reconhecível, nomeie-o ("Parece um scaffold da Dashboard do Aplicativo — sidebar de {N}px, header, barra de estatísticas, wrap de conteúdo").
Fluxo 2: Construção de Componente
Use ao construir qualquer componente de interface: botões, cartões, tabelas, menus dropdown, barras de progresso, etc.
- Análise de Contexto: Entenda como o componente se encaixa no layout. Verifique os elementos pais — não construa um botão primário que flutua isoladamente.
- Hierarquia Visual: Dê ao componente a profundidade correta usando sombras, elevação, cor de fundo. Botões têm
borderRadius:6por padrão; ajuste para 4 em componentes compactos. - Estado: construa variantes de estado onde for relevante: padrão, hover (se o editor suportar pseudo-estados), ativo, desabilitado.
- Escala: O componente preenche seu contêiner por padrão (
width:"100%"ou herança) a menos que seja um elemento flutuante (modais, dropdowns, dicas de ferramentas). - Toques Finais: tamanhos de fonte entre 12–16px, pesos de fonte conforme grade tipográfica, altura de linha de 1.4–1.6.
Diretrizes de Design
Estas regras substituem preferências subjetivas. Aplique-as sempre.
Hierarquia Visual
- Tamanho acima de cor — elementos maiores parecem mais importantes, mesmo sem cor. Ao sinalizar importância, aumente o tamanho primeiro, depois ajuste o peso/contraste. Botões primários são mais altos (40–48px) do que botões secundários (32–36px).
- Profundidade e Elevação — si. Use sombras para empurrar elementos para frente no espaço. Modais e dropdowns estão sempre acima de tudo.
- Tipografia Escalonada — títulos: 20–24px, subtítulos: 16–18px, corpo: 14px, suporte: 12px. Não use tamanhos arbitrários.
Espaçamento e Ritmo
- Use apenas valores da sua grade de espaçamento: 4, 8, 12, 16, 20, 24, 32, 40, 48, 64. Prefira 8 e 16 entre elementos. Use 24 e 32 para separar seções.
- Elementos de cartão: padding 24px. Espaçamento interno entre grupos: 16px.
- O espaçamento visual entre um título e seu conteúdo é 8px. Título para próxima seção: 24px.
Contraste e Acessibilidade
- Contraste de texto: texto principal ≥7:1 contra fundo, texto de suporte ≥4.5:1 contra fundo. Links: ≥3:1 contra texto ao redor, ≥4.5:1 contra fundo.
- Não coloque texto claro (por exemplo,
#FFFFFFou#F5F5F5) sobre imagens de fundo sem uma sobreposição escura (pelo menos 60% de opacidade). - Alvos de toque: mínimo 44×44px em telas mobile. Em telas desktop, 32×32px mínimo, prefira 40×40px.
Cor e Branding
- Use cores primárias para ações e navegação. Use cores de superfície para fundos de cartão, cabeçalhos de tabela, barras laterais.
- Nunca use a cor primária como cor de fundo a menos que seja para um herói ou banner promocional onde o contraste é controlado.
- As cores de estado (sucesso, aviso, erro) devem ser usadas apenas para seus significados pretendidos. Não use cor de erro para decoração.
Organização de Layout
- As telas de aplicativo sempre têm uma barra lateral à esquerda (largura do scaffold) e uma área de página.
- As barras laterais contêm navegação. As áreas de página contêm cabeçalho, conteúdo, rodapé de ação.
- Páginas de marketing não têm barra lateral. Use largura total de 1440px com preenchimento de conteúdo.
- Telas mobile não têm barra lateral. Use scaffold 390×844. Cabeçalho no topo, navegação inferior na parte inferior.
O Que Não Fazer
- Não coloque modais na raiz do canvas. Insira-os na
pageAreapara que a sobreposição funcione corretamente comsnapshot_layout(). - Não crie elementos filho sem um pai — verifique a hierarquia. Botões não flutuam sozinhos; estão dentro de um contêiner.
- Não adivinhe tokens de marca — sempre execute
get_variables()primeiro para verificar valores armazenados. Se estiverem vazios, peça ao usuário para executar o assistente de configuração. - Não ultrapasse o canvas — verifique com
snapshot_layout()antes de terminar. - Não use fontes que não estejam no mapa de tokens. Se o aplicativo não especificar uma fonte, use o font-sans padrão.
- Não construa scaffolds parciais — se você iniciar um scaffold, renderize todos os elementos definidos nele. Scaffolds parciais produzem layouts quebrados.
- Não crie barras laterais em aplicativos sem barra lateral (Scaffold I — Estado Vazio) ou em telas mobile.