@fprad0/skill-master-mcp 0.0.12 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -88
- package/README.md +472 -472
- package/VERSION.md +9 -9
- package/bin/lib/bootstrap-global-core.mjs +34 -0
- package/bin/lib/client-config.mjs +287 -285
- package/bin/lib/doctor-core.mjs +202 -0
- package/bin/lib/menu-core.mjs +1792 -1514
- package/bin/lib/operation-result.mjs +59 -0
- package/bin/lib/register-clients-core.mjs +247 -0
- package/bin/lib/skill-installation.mjs +215 -215
- package/bin/lib/update-cli-core.mjs +117 -0
- package/bin/skill-master-activation.mjs +165 -163
- package/bin/skill-master-bootstrap-global.mjs +61 -49
- package/bin/skill-master-configure-private-registry.mjs +3 -3
- package/bin/skill-master-doctor.mjs +239 -228
- package/bin/skill-master-eval-activation.mjs +32 -32
- package/bin/skill-master-install-global-skills.mjs +59 -59
- package/bin/skill-master-install-project-skills.mjs +97 -97
- package/bin/skill-master-menu.mjs +489 -378
- package/bin/skill-master-register-clients.mjs +232 -153
- package/bin/skill-master-success-skills.mjs +357 -307
- package/bin/skill-master-update.mjs +121 -72
- package/bin/skill-master.mjs +3 -3
- package/dist/activation.d.ts.map +1 -1
- package/dist/activation.js +12 -0
- package/dist/activation.js.map +1 -1
- package/dist/prompt-router.d.ts.map +1 -1
- package/dist/prompt-router.js +19 -0
- package/dist/prompt-router.js.map +1 -1
- package/dist/recommender.d.ts.map +1 -1
- package/dist/recommender.js +4 -1
- package/dist/recommender.js.map +1 -1
- package/docs/architecture/APRENDIZADO_DE_IMPLEMENTACOES_BEM_SUCEDIDAS.md +125 -125
- package/docs/architecture/ARQUITETURA_AUTO_UPDATE.md +9 -9
- package/docs/architecture/PLANO_MASTER_ACIONAMENTO_AUTOMATICO_E_APRENDIZADO.md +341 -341
- package/docs/architecture/REDE_SEGURA_DE_SKILLS.md +148 -148
- package/docs/operations/GUIA_MULTI_COMPUTADOR.md +262 -262
- package/docs/operations/GUIA_NPM_PRIVADO.md +294 -294
- package/docs/operations/GUIA_NPM_PUBLICO.md +147 -147
- package/docs/operations/MENU_VISUAL_EVIDENCE_2026-06-28.md +66 -66
- package/docs/operations/assets/menu-frame-compact.html +36 -33
- package/docs/operations/assets/menu-frame-dna-hero.html +87 -0
- package/docs/operations/assets/menu-frame-fine-helix.html +89 -0
- package/docs/operations/assets/menu-frame-large.html +44 -41
- package/docs/operations/assets/menu-frame-running.html +41 -38
- package/docs/operations/assets/menu-frame-score-10-contact-sheet.html +184 -0
- package/docs/operations/cross-platform-auth-transfer/ANALISE_COMPATIBILIDADE_MCP_2026-06-28.md +140 -140
- package/docs/operations/cross-platform-auth-transfer/README_TRANSFERENCIA.md +85 -85
- package/docs/operations/reborn-menu-cyberpunk-transfer/ANALISE_MENU_REBORN_CYBERPUNK_2026-06-28.md +174 -174
- package/docs/operations/reborn-menu-cyberpunk-transfer/HANDOFF_IMPLEMENTACAO_REBORN_CYBERPUNK_2026-06-28.md +119 -119
- package/docs/operations/reborn-menu-cyberpunk-transfer/ORDEM_DE_EXECUCAO_MENU_REBORN_CYBERPUNK.md +134 -134
- package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA.md +84 -84
- package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA_REBORN_PACKAGE.md +56 -56
- package/docs/operations/token-economy-transfer/ANALISE_AVANCADA_ECONOMIA_TOKENS_2026-06-30.md +141 -0
- package/docs/operations/token-economy-transfer/PLANO_DEV_SENIOR_MASTER_TOKEN_ECONOMY_2026-06-30.md +171 -0
- package/docs/operations/token-economy-transfer/README_TRANSFERENCIA_TOKEN_ECONOMY.md +31 -0
- package/docs/planning/MENU_RUNTIME_CORRECTION_PLAN_2026-06-30.md +551 -0
- package/docs/planning/V0_0_9_APROVACAO_CRITICA_MENSAGENS_DE_VENDA.md +85 -85
- package/docs/planning/V0_0_9_FONTES_E_CRITERIOS_DE_AUTORIDADE.md +139 -139
- package/docs/planning/V0_0_9_MATRIZ_SKILLS_MULTIDISCIPLINARES.md +105 -105
- package/docs/planning/V0_0_9_POLITICA_MORAL_CATOLICA_PARA_IA.md +181 -181
- package/docs/planning/V0_0_9_PROMPTS_EXECUCAO.md +59 -59
- package/docs/planning/V0_0_9_ROADMAP_DISCERNIMENTO_E_CONHECIMENTO_AMPLO.md +181 -181
- package/docs/planning/mcp-1.0.0/00_RESUMO_EXECUTIVO_AUDITORIA_MENU.md +118 -0
- package/docs/planning/mcp-1.0.0/01_MATRIZ_TESTES_MENU_E_RESULTADOS.md +250 -0
- package/docs/planning/mcp-1.0.0/02_PLANO_CORRECAO_ATIVAR_SKILL_APRENDIDA.md +200 -0
- package/docs/planning/mcp-1.0.0/03_PLANO_COMPATIBILIDADE_WINDOWS_LINUX_MACOS.md +167 -0
- package/docs/planning/mcp-1.0.0/04_PLANO_UI_CYBERPUNK_PIXEL_ART_E_PERFORMANCE.md +165 -0
- package/docs/planning/mcp-1.0.0/05_PROMPT_TASK_EXECUCAO_CORRECOES.md +151 -0
- package/docs/planning/mcp-1.0.0/06_CHECKLIST_REGRESSAO_PRE_RELEASE.md +159 -0
- package/docs/planning/mcp-1.0.0/07_RELATORIO_APLICACAO_CORRECOES_MENU_SKILL_MASTER.md +136 -0
- package/docs/planning/mcp-1.0.0/08_AUDITORIA_CRITICA_MENU_NOTA_E_DNA_REFINADO.md +184 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/00_PROMPT_TASK_MASTER_NOTA_10_10.md +103 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/01_PROMPT_TASK_FINE_HELIX_DNA.md +116 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/02_PROMPT_TASK_DNA_HERO_BOOT_AND_MOTION.md +109 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/03_PROMPT_TASK_MENU_UX_HELP_ERROR_COPY.md +99 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/04_PROMPT_TASK_EVIDENCE_RENDERER_1_0_0.md +97 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/05_PROMPT_TASK_CROSS_PLATFORM_UTF8_MOJIBAKE.md +99 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/06_PROMPT_TASK_VISUAL_REGRESSION_QA.md +105 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/07_PROMPT_TASK_PRE_RELEASE_SCORE_GATE_10_10.md +104 -0
- package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/README_ORDEM_EXECUCAO_NOTA_10_10.md +77 -0
- package/docs/prompt-tasks/PROMPT_TASK_001_BOOTSTRAP_SKILL_MASTER_MCP.md +6 -6
- package/docs/prompt-tasks/PROMPT_TASK_002_AUTO_UPDATE_LAUNCHER.md +6 -6
- package/docs/prompt-tasks/PROMPT_TASK_003_REMOTE_MANIFEST_AND_RELEASES.md +6 -6
- package/docs/prompt-tasks/PROMPT_TASK_004_MULTI_USER_DISTRIBUTION.md +6 -6
- package/docs/prompt-tasks/PROMPT_TASK_005_SECURITY_AND_QUALITY_GATE.md +6 -6
- package/docs/prompt-tasks/PROMPT_TASK_006_MASTER_ACIONAMENTO_APRENDIZADO.md +83 -83
- package/docs/prompt-tasks/PROMPT_TASK_007_PERSONA_ORQUESTRADORA.md +88 -88
- package/docs/prompt-tasks/PROMPT_TASK_008_PROMPT_ROUTER_MODOS_ATIVACAO.md +156 -156
- package/docs/prompt-tasks/PROMPT_TASK_009_PIPELINE_APRENDIZADO_SUCESSO.md +105 -105
- package/docs/prompt-tasks/PROMPT_TASK_010_EVALS_GOVERNANCA_ATIVACAO.md +119 -119
- package/docs/prompt-tasks/PROMPT_TASK_011_MENU_NOTIFICACOES_NOTION.md +120 -120
- package/docs/prompt-tasks/PROMPT_TASK_012_MENU_CYBERPUNK_PIXEL_FRAME.md +123 -123
- package/docs/prompt-tasks/PROMPT_TASK_013_MENU_FLUID_DNA_ANIMATION.md +114 -114
- package/docs/prompt-tasks/PROMPT_TASK_014_MENU_FUNCTIONAL_PARITY_QA.md +157 -157
- package/docs/prompt-tasks/PROMPT_TASK_015_TRANSFER_RELEASE_HANDOFF.md +127 -127
- package/docs/prompt-tasks/PROMPT_TASK_016_CROSS_PLATFORM_MCP_AUTH_REGISTRATION.md +107 -107
- package/docs/prompt-tasks/PROMPT_TASK_018_NPM_PUBLISH_2FA_SETUP.md +80 -80
- package/docs/prompt-tasks/PROMPT_TASK_019_TOKEN_ECONOMY_GLOBAL_SKILLS.md +56 -0
- package/docs/prompt-tasks/PROMPT_TASK_MASTER_EXECUTOR.md +6 -6
- package/docs/skill-candidates/v0.0.10/cli-creator/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/cli-creator/SKILL.md +160 -160
- package/docs/skill-candidates/v0.0.10/cli-creator/agents/openai.yaml +4 -4
- package/docs/skill-candidates/v0.0.10/cli-creator/references/agent-cli-patterns.md +154 -154
- package/docs/skill-candidates/v0.0.10/developer-workstation-ops/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.10/figma/LICENSE.txt +1 -1
- package/docs/skill-candidates/v0.0.10/figma/SKILL.md +42 -42
- package/docs/skill-candidates/v0.0.10/figma/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma/references/figma-mcp-config.md +35 -35
- package/docs/skill-candidates/v0.0.10/figma/references/figma-tools-and-prompts.md +34 -34
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/LICENSE.TXT +1 -1
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/SKILL.md +349 -349
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/references/mapping-checklist.md +7 -7
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/scripts/normalize_node_id.py +25 -25
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/LICENSE.TXT +1 -1
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/SKILL.md +537 -537
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/references/rule-template.md +15 -15
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/scripts/check_agents_md.sh +9 -9
- package/docs/skill-candidates/v0.0.10/figma-generate-design/LICENSE.TXT +1 -1
- package/docs/skill-candidates/v0.0.10/figma-generate-design/SKILL.md +341 -341
- package/docs/skill-candidates/v0.0.10/figma-generate-design/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-generate-design/maintainers.yml +1 -1
- package/docs/skill-candidates/v0.0.10/figma-generate-library/LICENSE.TXT +1 -1
- package/docs/skill-candidates/v0.0.10/figma-generate-library/SKILL.md +314 -314
- package/docs/skill-candidates/v0.0.10/figma-generate-library/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-generate-library/maintainers.yml +3 -3
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/code-connect-setup.md +260 -260
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/component-creation.md +1014 -1014
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/discovery-phase.md +518 -518
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/documentation-creation.md +834 -834
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/error-recovery.md +540 -540
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/naming-conventions.md +527 -527
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/token-creation.md +962 -962
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/bindVariablesToComponent.js +110 -110
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/cleanupOrphans.js +127 -127
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createComponentWithVariants.js +148 -148
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createDocumentationPage.js +139 -139
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createSemanticTokens.js +108 -108
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createVariableCollection.js +49 -49
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/inspectFileStructure.js +121 -121
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/rehydrateState.js +92 -92
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/validateCreation.js +83 -83
- package/docs/skill-candidates/v0.0.10/figma-implement-design/LICENSE.txt +1 -1
- package/docs/skill-candidates/v0.0.10/figma-implement-design/SKILL.md +258 -258
- package/docs/skill-candidates/v0.0.10/figma-implement-design/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-use/LICENSE.TXT +1 -1
- package/docs/skill-candidates/v0.0.10/figma-use/SKILL.md +233 -233
- package/docs/skill-candidates/v0.0.10/figma-use/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/figma-use/assets/figma-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/figma-use/assets/icon.svg +28 -28
- package/docs/skill-candidates/v0.0.10/figma-use/maintainers.yml +1 -1
- package/docs/skill-candidates/v0.0.10/figma-use/references/api-reference.md +301 -301
- package/docs/skill-candidates/v0.0.10/figma-use/references/common-patterns.md +512 -512
- package/docs/skill-candidates/v0.0.10/figma-use/references/component-patterns.md +488 -488
- package/docs/skill-candidates/v0.0.10/figma-use/references/effect-style-patterns.md +123 -123
- package/docs/skill-candidates/v0.0.10/figma-use/references/gotchas.md +599 -599
- package/docs/skill-candidates/v0.0.10/figma-use/references/maintainers.yml +12 -12
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-patterns.md +513 -513
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.d.ts +11293 -11293
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.index.md +441 -441
- package/docs/skill-candidates/v0.0.10/figma-use/references/text-style-patterns.md +203 -203
- package/docs/skill-candidates/v0.0.10/figma-use/references/validation-and-recovery.md +109 -109
- package/docs/skill-candidates/v0.0.10/figma-use/references/variable-patterns.md +354 -354
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/maintainers.yml +9 -9
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--creating.md +17 -17
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--using.md +17 -17
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components.md +50 -50
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-effect-styles.md +52 -52
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-text-styles.md +90 -90
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--creating.md +13 -13
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--using.md +13 -13
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables.md +64 -64
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds.md +41 -41
- package/docs/skill-candidates/v0.0.10/frontend-design/LICENSE.txt +177 -177
- package/docs/skill-candidates/v0.0.10/frontend-design/SKILL.md +55 -55
- package/docs/skill-candidates/v0.0.10/frontend-ui-ux-systems/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.10/github/SKILL.md +74 -74
- package/docs/skill-candidates/v0.0.10/github/agents/openai.yaml +6 -6
- package/docs/skill-candidates/v0.0.10/github/assets/github-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/image-graphic-design-rendering/SKILL.md +28 -28
- package/docs/skill-candidates/v0.0.10/language-quality-pt-en-fr-it-ru/SKILL.md +28 -28
- package/docs/skill-candidates/v0.0.10/math-physics-reasoning/SKILL.md +28 -28
- package/docs/skill-candidates/v0.0.10/mcp-builder/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/mcp-builder/SKILL.md +236 -236
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/evaluation.md +601 -601
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/mcp_best_practices.md +249 -249
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/node_mcp_server.md +969 -969
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/python_mcp_server.md +718 -718
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/connections.py +151 -151
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/evaluation.py +373 -373
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/example_evaluation.xml +22 -22
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/requirements.txt +2 -2
- package/docs/skill-candidates/v0.0.10/mcp-client-readiness/SKILL.md +31 -31
- package/docs/skill-candidates/v0.0.10/openai-docs/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/openai-docs/SKILL.md +161 -161
- package/docs/skill-candidates/v0.0.10/openai-docs/agents/openai.yaml +14 -14
- package/docs/skill-candidates/v0.0.10/openai-docs/assets/openai-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/openai-docs/references/latest-model.md +37 -37
- package/docs/skill-candidates/v0.0.10/openai-docs/references/prompting-guide.md +244 -244
- package/docs/skill-candidates/v0.0.10/openai-docs/references/upgrade-guide.md +181 -181
- package/docs/skill-candidates/v0.0.10/openai-docs/scripts/fetch-codex-manual.mjs +598 -598
- package/docs/skill-candidates/v0.0.10/openai-docs/scripts/resolve-latest-model-info.js +147 -147
- package/docs/skill-candidates/v0.0.10/playwright/NOTICE.txt +14 -14
- package/docs/skill-candidates/v0.0.10/playwright/SKILL.md +147 -147
- package/docs/skill-candidates/v0.0.10/playwright/agents/openai.yaml +6 -6
- package/docs/skill-candidates/v0.0.10/playwright/assets/playwright-small.svg +3 -3
- package/docs/skill-candidates/v0.0.10/playwright/references/cli.md +116 -116
- package/docs/skill-candidates/v0.0.10/playwright/references/workflows.md +95 -95
- package/docs/skill-candidates/v0.0.10/playwright/scripts/playwright_cli.sh +25 -25
- package/docs/skill-candidates/v0.0.10/polyglot-backend-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.10/screenshot/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/screenshot/SKILL.md +267 -267
- package/docs/skill-candidates/v0.0.10/screenshot/agents/openai.yaml +6 -6
- package/docs/skill-candidates/v0.0.10/screenshot/assets/screenshot-small.svg +5 -5
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/ensure_macos_permissions.sh +54 -54
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_display_info.swift +22 -22
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_permissions.swift +40 -40
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_window_info.swift +126 -126
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.ps1 +163 -163
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.py +585 -585
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/SKILL.md +62 -62
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/agents/openai.yaml +4 -4
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/activation-policy.md +77 -77
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/human-approval-policy.md +83 -83
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/persona-dev-senior-master.md +46 -46
- package/docs/skill-candidates/v0.0.10/terminal-menu-operations/SKILL.md +30 -30
- package/docs/skill-candidates/v0.0.10/terminal-pixel-art-tui/SKILL.md +43 -43
- package/docs/skill-candidates/v0.0.10/webapp-testing/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/webapp-testing/SKILL.md +95 -95
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/console_logging.py +34 -34
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/element_discovery.py +39 -39
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/static_html_automation.py +32 -32
- package/docs/skill-candidates/v0.0.10/webapp-testing/scripts/with_server.py +105 -105
- package/docs/skill-candidates/v0.0.10/winui-app/LICENSE.txt +201 -201
- package/docs/skill-candidates/v0.0.10/winui-app/SKILL.md +94 -94
- package/docs/skill-candidates/v0.0.10/winui-app/agents/openai.yaml +5 -5
- package/docs/skill-candidates/v0.0.10/winui-app/config.yaml +50 -50
- package/docs/skill-candidates/v0.0.10/winui-app/references/_sections.md +96 -96
- package/docs/skill-candidates/v0.0.10/winui-app/references/accessibility-input-and-localization.md +51 -51
- package/docs/skill-candidates/v0.0.10/winui-app/references/build-run-and-launch-verification.md +72 -72
- package/docs/skill-candidates/v0.0.10/winui-app/references/community-toolkit-controls-and-helpers.md +57 -57
- package/docs/skill-candidates/v0.0.10/winui-app/references/controls-layout-and-adaptive-ui.md +84 -84
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-environment-audit-and-remediation.md +82 -82
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-setup-and-project-selection.md +67 -67
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-template-first-recovery.md +62 -62
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-winui-app-structure.md +62 -62
- package/docs/skill-candidates/v0.0.10/winui-app/references/motion-animations-and-polish.md +45 -45
- package/docs/skill-candidates/v0.0.10/winui-app/references/performance-diagnostics-and-responsiveness.md +46 -46
- package/docs/skill-candidates/v0.0.10/winui-app/references/sample-source-map.md +37 -37
- package/docs/skill-candidates/v0.0.10/winui-app/references/shell-navigation-and-windowing.md +67 -67
- package/docs/skill-candidates/v0.0.10/winui-app/references/styling-theming-materials-and-icons.md +71 -71
- package/docs/skill-candidates/v0.0.10/winui-app/references/testing-debugging-and-review-checklists.md +77 -77
- package/docs/skill-candidates/v0.0.10/winui-app/references/windows-app-sdk-lifecycle-notifications-and-deployment.md +52 -52
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +398 -398
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +330 -330
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +871 -871
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +501 -501
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +766 -766
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +501 -501
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +500 -500
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +405 -405
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +363 -363
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +427 -427
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +417 -417
- package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -36
- package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -745
- package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -3
- package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -94
- package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -209
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -103
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -103
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -103
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -114
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -114
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -114
- package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -573
- package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -3
- package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -429
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +91 -91
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -383
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -335
- package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -203
- package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -34
- package/docs/skill-candidates/v0.0.12/context-compression-handoff/SKILL.md +47 -0
- package/docs/skill-candidates/v0.0.12/csharp-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/css-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/go-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/html-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/javascript-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/json-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/prompt-budget-gate/SKILL.md +46 -0
- package/docs/skill-candidates/v0.0.12/python-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/react-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/ruby-senior-master-engineering/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.12/senior-master-code-optimizer/SKILL.md +48 -48
- package/docs/skill-candidates/v0.0.12/sql-senior-master-engineering/SKILL.md +31 -31
- package/docs/skill-candidates/v0.0.12/token-economy-orchestrator/SKILL.md +38 -0
- package/docs/skill-candidates/v0.0.12/typescript-senior-master-engineering/SKILL.md +35 -35
- package/docs/skill-candidates/v0.0.9/ai-ethics-human-dignity/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.9/broad-domain-router/SKILL.md +41 -41
- package/docs/skill-candidates/v0.0.9/catholic-moral-discernment/SKILL.md +31 -31
- package/docs/skill-candidates/v0.0.9/engineering-systems-master/SKILL.md +31 -31
- package/docs/skill-candidates/v0.0.9/language-quality-pt-en-fr/SKILL.md +28 -28
- package/docs/skill-candidates/v0.0.9/math-science-reasoning/SKILL.md +29 -29
- package/docs/skill-candidates/v0.0.9/philosophy-sociology-discernment/SKILL.md +28 -28
- package/docs/skill-candidates/v0.0.9/professional-boundary-triage/SKILL.md +40 -40
- package/docs/skill-candidates/v0.0.9/release-ethics-gate/SKILL.md +32 -32
- package/docs/skill-candidates/v0.0.9/source-authority-reviewer/SKILL.md +31 -31
- package/examples/client-configs/claude-code.commands.md +21 -21
- package/examples/client-configs/claude-code.project.mcp.json +18 -18
- package/examples/client-configs/claude-desktop.macos.json +18 -18
- package/examples/client-configs/claude-desktop.windows.json +20 -20
- package/examples/client-configs/codex.windows.toml +11 -11
- package/examples/client-configs/gemini-code-assist.intellij.mcp.json +18 -18
- package/examples/client-configs/gemini.linux.settings.json +21 -21
- package/examples/client-configs/gemini.windows.settings.json +23 -23
- package/examples/client-configs/generic-stdio.json +16 -16
- package/manifests/channels/beta.json +24 -24
- package/manifests/channels/stable.json +25 -25
- package/network/approved-skills.json +54 -54
- package/network/unapproved-skill-candidates.json +110 -110
- package/package.json +89 -86
- package/scripts/configure-private-registry.mjs +208 -208
- package/scripts/lib/private-registry.mjs +97 -97
- package/scripts/render-menu-evidence.mjs +196 -130
- package/scripts/verify-menu-actions.mjs +112 -107
- package/scripts/verify-menu-visual.mjs +90 -0
- package/sources.json +11 -11
package/docs/skill-candidates/v0.0.10/figma-generate-library/references/documentation-creation.md
CHANGED
|
@@ -1,834 +1,834 @@
|
|
|
1
|
-
> Part of the [figma-generate-library skill](../SKILL.md).
|
|
2
|
-
|
|
3
|
-
# Documentation Creation Reference
|
|
4
|
-
|
|
5
|
-
This reference covers Phase 2 of the design system build: the cover page, foundations documentation page (color swatches, type specimens, spacing bars, shadow cards, radius demo), page layout dimensions, and inline component documentation. Every code block is complete `use_figma`-ready JavaScript (helper-function form — no IIFE wrapper, no `closePlugin` — meant to be embedded in a larger script).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 1. Cover Page
|
|
10
|
-
|
|
11
|
-
The cover page is always the first page in the file. It is a branded title card that sets context for anyone opening the file.
|
|
12
|
-
|
|
13
|
-
### What to include
|
|
14
|
-
|
|
15
|
-
- File/system name as a large heading (48–72px)
|
|
16
|
-
- Version string or date
|
|
17
|
-
- Brief tagline (1 sentence)
|
|
18
|
-
- Optional: color block background using the primary brand color variable
|
|
19
|
-
|
|
20
|
-
### Cover page dimensions
|
|
21
|
-
|
|
22
|
-
The cover frame should be **1440 × 900px** — this matches the default Figma canvas and looks correct in the page thumbnail.
|
|
23
|
-
|
|
24
|
-
### use_figma for cover page
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
async function createCoverPage(systemName, tagline, version, primaryColorVar) {
|
|
28
|
-
// primaryColorVar: a Figma Variable object for the brand primary fill
|
|
29
|
-
const page = figma.createPage();
|
|
30
|
-
page.name = 'Cover';
|
|
31
|
-
await figma.setCurrentPageAsync(page);
|
|
32
|
-
|
|
33
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
34
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
35
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
36
|
-
|
|
37
|
-
const frame = figma.createFrame();
|
|
38
|
-
frame.name = 'Cover';
|
|
39
|
-
frame.resize(1440, 900);
|
|
40
|
-
frame.x = 0;
|
|
41
|
-
frame.y = 0;
|
|
42
|
-
frame.layoutMode = 'VERTICAL';
|
|
43
|
-
frame.primaryAxisAlignItems = 'CENTER';
|
|
44
|
-
frame.counterAxisAlignItems = 'CENTER';
|
|
45
|
-
frame.itemSpacing = 16;
|
|
46
|
-
frame.paddingTop = 0;
|
|
47
|
-
frame.paddingBottom = 0;
|
|
48
|
-
frame.paddingLeft = 0;
|
|
49
|
-
frame.paddingRight = 0;
|
|
50
|
-
|
|
51
|
-
// Background: bind to primary variable if provided, else solid dark
|
|
52
|
-
if (primaryColorVar) {
|
|
53
|
-
const bgPaint = figma.variables.setBoundVariableForPaint(
|
|
54
|
-
{ type: 'SOLID', color: { r: 0.05, g: 0.05, b: 0.05 } },
|
|
55
|
-
'color',
|
|
56
|
-
primaryColorVar
|
|
57
|
-
);
|
|
58
|
-
frame.fills = [bgPaint];
|
|
59
|
-
} else {
|
|
60
|
-
frame.fills = [{ type: 'SOLID', color: { r: 0.06, g: 0.06, b: 0.07 } }];
|
|
61
|
-
}
|
|
62
|
-
page.appendChild(frame);
|
|
63
|
-
|
|
64
|
-
// System name heading
|
|
65
|
-
const title = figma.createText();
|
|
66
|
-
title.fontName = { family: 'Inter', style: 'Bold' };
|
|
67
|
-
title.characters = systemName;
|
|
68
|
-
title.fontSize = 64;
|
|
69
|
-
title.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
70
|
-
title.textAlignHorizontal = 'CENTER';
|
|
71
|
-
frame.appendChild(title);
|
|
72
|
-
|
|
73
|
-
// Tagline
|
|
74
|
-
const tag = figma.createText();
|
|
75
|
-
tag.fontName = { family: 'Inter', style: 'Regular' };
|
|
76
|
-
tag.characters = tagline;
|
|
77
|
-
tag.fontSize = 20;
|
|
78
|
-
tag.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.7 } }];
|
|
79
|
-
tag.textAlignHorizontal = 'CENTER';
|
|
80
|
-
frame.appendChild(tag);
|
|
81
|
-
|
|
82
|
-
// Version
|
|
83
|
-
const ver = figma.createText();
|
|
84
|
-
ver.fontName = { family: 'Inter', style: 'Medium' };
|
|
85
|
-
ver.characters = version;
|
|
86
|
-
ver.fontSize = 13;
|
|
87
|
-
ver.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.45 } }];
|
|
88
|
-
ver.textAlignHorizontal = 'CENTER';
|
|
89
|
-
frame.appendChild(ver);
|
|
90
|
-
|
|
91
|
-
return { page, frameId: frame.id };
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## 2. Foundations Page
|
|
98
|
-
|
|
99
|
-
The Foundations page is always placed **before any component pages**. It visually documents the design tokens — colors, typography, spacing, shadows, and border radii — so designers and engineers can see available primitives at a glance.
|
|
100
|
-
|
|
101
|
-
### Page layout dimensions
|
|
102
|
-
|
|
103
|
-
The outer documentation frame should be **1440px wide**. Sections stack vertically with **64–100px gaps** between them. Each section frame fills the full 1440px width and hugs its content vertically.
|
|
104
|
-
|
|
105
|
-
### Full Foundations page skeleton
|
|
106
|
-
|
|
107
|
-
```javascript
|
|
108
|
-
async function createFoundationsPage() {
|
|
109
|
-
const page = figma.createPage();
|
|
110
|
-
page.name = 'Foundations';
|
|
111
|
-
await figma.setCurrentPageAsync(page);
|
|
112
|
-
|
|
113
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
114
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
115
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
116
|
-
|
|
117
|
-
// Root scroll frame
|
|
118
|
-
const root = figma.createFrame();
|
|
119
|
-
root.name = 'Foundations';
|
|
120
|
-
root.layoutMode = 'VERTICAL';
|
|
121
|
-
root.primaryAxisAlignItems = 'MIN';
|
|
122
|
-
root.counterAxisAlignItems = 'MIN';
|
|
123
|
-
root.itemSpacing = 80;
|
|
124
|
-
root.paddingTop = 80;
|
|
125
|
-
root.paddingBottom = 120;
|
|
126
|
-
root.paddingLeft = 80;
|
|
127
|
-
root.paddingRight = 80;
|
|
128
|
-
root.layoutSizingHorizontal = 'FIXED';
|
|
129
|
-
root.layoutSizingVertical = 'HUG';
|
|
130
|
-
root.resize(1440, 1);
|
|
131
|
-
root.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
132
|
-
page.appendChild(root);
|
|
133
|
-
|
|
134
|
-
return { page, root };
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## 3. Color Swatches (bound to variables)
|
|
141
|
-
|
|
142
|
-
Color swatches must be **bound to actual Figma variables** — never hardcode hex values in swatch fills. This keeps documentation in sync automatically when variable values change.
|
|
143
|
-
|
|
144
|
-
### Single color swatch
|
|
145
|
-
|
|
146
|
-
```javascript
|
|
147
|
-
/**
|
|
148
|
-
* Creates a single color swatch card (rectangle + variable name label).
|
|
149
|
-
* The swatch rectangle fill is bound to the provided variable.
|
|
150
|
-
*
|
|
151
|
-
* @param {FrameNode} parent - The auto-layout row to append to.
|
|
152
|
-
* @param {string} varName - Display name (e.g. "color/bg/primary").
|
|
153
|
-
* @param {Variable} variable - The Figma Variable object to bind to.
|
|
154
|
-
* @returns {FrameNode} The swatch frame.
|
|
155
|
-
*/
|
|
156
|
-
async function createColorSwatch(parent, varName, variable) {
|
|
157
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
158
|
-
|
|
159
|
-
const swatchFrame = figma.createFrame();
|
|
160
|
-
swatchFrame.name = `Swatch/${varName}`;
|
|
161
|
-
swatchFrame.layoutMode = 'VERTICAL';
|
|
162
|
-
swatchFrame.primaryAxisAlignItems = 'MIN';
|
|
163
|
-
swatchFrame.counterAxisAlignItems = 'MIN';
|
|
164
|
-
swatchFrame.itemSpacing = 6;
|
|
165
|
-
swatchFrame.layoutSizingHorizontal = 'FIXED';
|
|
166
|
-
swatchFrame.layoutSizingVertical = 'HUG';
|
|
167
|
-
swatchFrame.resize(88, 1);
|
|
168
|
-
swatchFrame.fills = [];
|
|
169
|
-
|
|
170
|
-
// Color rectangle — bound to variable
|
|
171
|
-
const rect = figma.createRectangle();
|
|
172
|
-
rect.resize(88, 88);
|
|
173
|
-
rect.cornerRadius = 8;
|
|
174
|
-
const paint = figma.variables.setBoundVariableForPaint(
|
|
175
|
-
{ type: 'SOLID', color: { r: 0.5, g: 0.5, b: 0.5 } },
|
|
176
|
-
'color',
|
|
177
|
-
variable
|
|
178
|
-
);
|
|
179
|
-
rect.fills = [paint];
|
|
180
|
-
swatchFrame.appendChild(rect);
|
|
181
|
-
|
|
182
|
-
// Name label
|
|
183
|
-
const label = figma.createText();
|
|
184
|
-
label.fontName = { family: 'Inter', style: 'Regular' };
|
|
185
|
-
label.characters = varName.split('/').pop(); // show leaf name only
|
|
186
|
-
label.fontSize = 10;
|
|
187
|
-
label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
188
|
-
label.layoutSizingHorizontal = 'FILL';
|
|
189
|
-
swatchFrame.appendChild(label);
|
|
190
|
-
|
|
191
|
-
// Full path tooltip label (smaller, lighter)
|
|
192
|
-
const pathLabel = figma.createText();
|
|
193
|
-
pathLabel.fontName = { family: 'Inter', style: 'Regular' };
|
|
194
|
-
pathLabel.characters = varName;
|
|
195
|
-
pathLabel.fontSize = 9;
|
|
196
|
-
pathLabel.fills = [{ type: 'SOLID', color: { r: 0.6, g: 0.6, b: 0.6 } }];
|
|
197
|
-
pathLabel.layoutSizingHorizontal = 'FILL';
|
|
198
|
-
swatchFrame.appendChild(pathLabel);
|
|
199
|
-
|
|
200
|
-
parent.appendChild(swatchFrame);
|
|
201
|
-
return swatchFrame;
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Color section builder (primitives row + semantic grid)
|
|
206
|
-
|
|
207
|
-
```javascript
|
|
208
|
-
/**
|
|
209
|
-
* Creates a complete color documentation section with a section heading,
|
|
210
|
-
* a row of primitive swatches, and a grid of semantic swatches.
|
|
211
|
-
*
|
|
212
|
-
* @param {FrameNode} root - The root vertical stack frame.
|
|
213
|
-
* @param {Variable[]} primitiveVars - Variables from the Primitives collection.
|
|
214
|
-
* @param {Variable[]} semanticVars - Variables from the semantic Color collection.
|
|
215
|
-
*/
|
|
216
|
-
async function createColorSection(root, primitiveVars, semanticVars) {
|
|
217
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
218
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
219
|
-
|
|
220
|
-
// Section container
|
|
221
|
-
const section = figma.createFrame();
|
|
222
|
-
section.name = 'Section/Colors';
|
|
223
|
-
section.layoutMode = 'VERTICAL';
|
|
224
|
-
section.itemSpacing = 24;
|
|
225
|
-
section.layoutSizingHorizontal = 'FILL';
|
|
226
|
-
section.layoutSizingVertical = 'HUG';
|
|
227
|
-
section.fills = [];
|
|
228
|
-
root.appendChild(section);
|
|
229
|
-
|
|
230
|
-
// Section heading
|
|
231
|
-
const heading = figma.createText();
|
|
232
|
-
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
233
|
-
heading.characters = 'Colors';
|
|
234
|
-
heading.fontSize = 32;
|
|
235
|
-
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
236
|
-
section.appendChild(heading);
|
|
237
|
-
|
|
238
|
-
// Description
|
|
239
|
-
const desc = figma.createText();
|
|
240
|
-
desc.fontName = { family: 'Inter', style: 'Regular' };
|
|
241
|
-
desc.characters = 'Primitive color palette and semantic color tokens. Semantic tokens reference primitives — always use semantic tokens in components.';
|
|
242
|
-
desc.fontSize = 14;
|
|
243
|
-
desc.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }];
|
|
244
|
-
desc.layoutSizingHorizontal = 'FILL';
|
|
245
|
-
section.appendChild(desc);
|
|
246
|
-
|
|
247
|
-
// Primitive swatches row
|
|
248
|
-
const primLabel = figma.createText();
|
|
249
|
-
primLabel.fontName = { family: 'Inter', style: 'Bold' };
|
|
250
|
-
primLabel.characters = 'Primitives';
|
|
251
|
-
primLabel.fontSize = 13;
|
|
252
|
-
primLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
253
|
-
section.appendChild(primLabel);
|
|
254
|
-
|
|
255
|
-
const primRow = figma.createFrame();
|
|
256
|
-
primRow.name = 'Primitives/Row';
|
|
257
|
-
primRow.layoutMode = 'HORIZONTAL';
|
|
258
|
-
primRow.itemSpacing = 12;
|
|
259
|
-
primRow.layoutSizingHorizontal = 'FILL';
|
|
260
|
-
primRow.layoutSizingVertical = 'HUG';
|
|
261
|
-
primRow.fills = [];
|
|
262
|
-
primRow.layoutWrap = 'WRAP';
|
|
263
|
-
section.appendChild(primRow);
|
|
264
|
-
|
|
265
|
-
for (const v of primitiveVars) {
|
|
266
|
-
await createColorSwatch(primRow, v.name, v);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Semantic swatches grid
|
|
270
|
-
if (semanticVars.length > 0) {
|
|
271
|
-
const semLabel = figma.createText();
|
|
272
|
-
semLabel.fontName = { family: 'Inter', style: 'Bold' };
|
|
273
|
-
semLabel.characters = 'Semantic';
|
|
274
|
-
semLabel.fontSize = 13;
|
|
275
|
-
semLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
276
|
-
section.appendChild(semLabel);
|
|
277
|
-
|
|
278
|
-
const semRow = figma.createFrame();
|
|
279
|
-
semRow.name = 'Semantic/Row';
|
|
280
|
-
semRow.layoutMode = 'HORIZONTAL';
|
|
281
|
-
semRow.itemSpacing = 12;
|
|
282
|
-
semRow.layoutSizingHorizontal = 'FILL';
|
|
283
|
-
semRow.layoutSizingVertical = 'HUG';
|
|
284
|
-
semRow.fills = [];
|
|
285
|
-
semRow.layoutWrap = 'WRAP';
|
|
286
|
-
section.appendChild(semRow);
|
|
287
|
-
|
|
288
|
-
for (const v of semanticVars) {
|
|
289
|
-
await createColorSwatch(semRow, v.name, v);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return section;
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## 4. Type Specimens
|
|
300
|
-
|
|
301
|
-
Typography specimens show each text style rendered at its actual size with a sample string, the style name, and its specifications.
|
|
302
|
-
|
|
303
|
-
### Single type specimen row
|
|
304
|
-
|
|
305
|
-
```javascript
|
|
306
|
-
/**
|
|
307
|
-
* Creates a single type specimen row: style name (small label) + sample text +
|
|
308
|
-
* specification line (family · style · size · line-height).
|
|
309
|
-
*
|
|
310
|
-
* @param {FrameNode} parent - The parent vertical stack.
|
|
311
|
-
* @param {string} styleName - The text style name (e.g. "Display Large").
|
|
312
|
-
* @param {string} fontFamily - Font family (e.g. "Inter").
|
|
313
|
-
* @param {string} fontStyle - Font style (e.g. "Bold").
|
|
314
|
-
* @param {number} fontSize - Font size in pixels.
|
|
315
|
-
* @param {number} lineHeight - Line height in pixels.
|
|
316
|
-
* @returns {FrameNode} The specimen row frame.
|
|
317
|
-
*/
|
|
318
|
-
async function createTypeSpecimen(parent, styleName, fontFamily, fontStyle, fontSize, lineHeight) {
|
|
319
|
-
await figma.loadFontAsync({ family: fontFamily, style: fontStyle });
|
|
320
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
321
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
322
|
-
|
|
323
|
-
const row = figma.createFrame();
|
|
324
|
-
row.name = `Type/${styleName}`;
|
|
325
|
-
row.layoutMode = 'VERTICAL';
|
|
326
|
-
row.itemSpacing = 6;
|
|
327
|
-
row.paddingTop = 16;
|
|
328
|
-
row.paddingBottom = 16;
|
|
329
|
-
row.layoutSizingHorizontal = 'FILL';
|
|
330
|
-
row.layoutSizingVertical = 'HUG';
|
|
331
|
-
row.fills = [];
|
|
332
|
-
parent.appendChild(row);
|
|
333
|
-
|
|
334
|
-
// Style name label (small, muted)
|
|
335
|
-
const nameText = figma.createText();
|
|
336
|
-
nameText.fontName = { family: 'Inter', style: 'Medium' };
|
|
337
|
-
nameText.characters = styleName;
|
|
338
|
-
nameText.fontSize = 11;
|
|
339
|
-
nameText.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
340
|
-
nameText.layoutSizingHorizontal = 'FILL';
|
|
341
|
-
row.appendChild(nameText);
|
|
342
|
-
|
|
343
|
-
// Sample text rendered in the actual style
|
|
344
|
-
const specimen = figma.createText();
|
|
345
|
-
specimen.fontName = { family: fontFamily, style: fontStyle };
|
|
346
|
-
specimen.characters = 'The quick brown fox jumps over the lazy dog';
|
|
347
|
-
specimen.fontSize = fontSize;
|
|
348
|
-
specimen.lineHeight = { value: lineHeight, unit: 'PIXELS' };
|
|
349
|
-
specimen.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
350
|
-
specimen.layoutSizingHorizontal = 'FILL';
|
|
351
|
-
row.appendChild(specimen);
|
|
352
|
-
|
|
353
|
-
// Specification line
|
|
354
|
-
const specs = figma.createText();
|
|
355
|
-
specs.fontName = { family: 'Inter', style: 'Regular' };
|
|
356
|
-
specs.characters = `${fontFamily} ${fontStyle} · ${fontSize}px · ${lineHeight}px line height`;
|
|
357
|
-
specs.fontSize = 11;
|
|
358
|
-
specs.fills = [{ type: 'SOLID', color: { r: 0.65, g: 0.65, b: 0.65 } }];
|
|
359
|
-
specs.layoutSizingHorizontal = 'FILL';
|
|
360
|
-
row.appendChild(specs);
|
|
361
|
-
|
|
362
|
-
// Divider line
|
|
363
|
-
const divider = figma.createRectangle();
|
|
364
|
-
divider.resize(1280, 1);
|
|
365
|
-
divider.fills = [{ type: 'SOLID', color: { r: 0.9, g: 0.9, b: 0.9 } }];
|
|
366
|
-
divider.layoutSizingHorizontal = 'FILL';
|
|
367
|
-
row.appendChild(divider);
|
|
368
|
-
|
|
369
|
-
return row;
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Typography section builder
|
|
374
|
-
|
|
375
|
-
```javascript
|
|
376
|
-
/**
|
|
377
|
-
* Creates a complete typography documentation section.
|
|
378
|
-
* Pass an array of style definitions; the function renders one specimen per entry.
|
|
379
|
-
*
|
|
380
|
-
* @param {FrameNode} root - Root vertical stack.
|
|
381
|
-
* @param {Array<{name, family, style, size, lineHeight}>} typeStyles - Style definitions.
|
|
382
|
-
*/
|
|
383
|
-
async function createTypographySection(root, typeStyles) {
|
|
384
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
385
|
-
|
|
386
|
-
const section = figma.createFrame();
|
|
387
|
-
section.name = 'Section/Typography';
|
|
388
|
-
section.layoutMode = 'VERTICAL';
|
|
389
|
-
section.itemSpacing = 0;
|
|
390
|
-
section.layoutSizingHorizontal = 'FILL';
|
|
391
|
-
section.layoutSizingVertical = 'HUG';
|
|
392
|
-
section.fills = [];
|
|
393
|
-
root.appendChild(section);
|
|
394
|
-
|
|
395
|
-
const heading = figma.createText();
|
|
396
|
-
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
397
|
-
heading.characters = 'Typography';
|
|
398
|
-
heading.fontSize = 32;
|
|
399
|
-
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
400
|
-
section.appendChild(heading);
|
|
401
|
-
|
|
402
|
-
for (const ts of typeStyles) {
|
|
403
|
-
await createTypeSpecimen(section, ts.name, ts.family, ts.style, ts.size, ts.lineHeight);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
return section;
|
|
407
|
-
}
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
---
|
|
411
|
-
|
|
412
|
-
## 5. Spacing Bars
|
|
413
|
-
|
|
414
|
-
Spacing bars show each spacing token as a filled rectangle whose width equals the spacing value. Shorter bars for small values, longer bars for large values — the visual encoding is immediate.
|
|
415
|
-
|
|
416
|
-
### Spacing bar row
|
|
417
|
-
|
|
418
|
-
```javascript
|
|
419
|
-
/**
|
|
420
|
-
* Creates a single spacing bar: a colored rectangle sized to the spacing value,
|
|
421
|
-
* with a label showing name + pixel value + code syntax.
|
|
422
|
-
*
|
|
423
|
-
* @param {FrameNode} parent - Parent vertical stack.
|
|
424
|
-
* @param {string} name - Token name (e.g. "spacing/sm").
|
|
425
|
-
* @param {number} value - Spacing value in pixels.
|
|
426
|
-
* @param {Variable} variable - Figma Variable to bind the width to.
|
|
427
|
-
* @param {string} codeSyntax - CSS variable string (e.g. "var(--spacing-sm)").
|
|
428
|
-
*/
|
|
429
|
-
async function createSpacingBar(parent, name, value, variable, codeSyntax) {
|
|
430
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
431
|
-
|
|
432
|
-
const row = figma.createFrame();
|
|
433
|
-
row.name = `Spacing/${name}`;
|
|
434
|
-
row.layoutMode = 'HORIZONTAL';
|
|
435
|
-
row.counterAxisAlignItems = 'CENTER';
|
|
436
|
-
row.itemSpacing = 16;
|
|
437
|
-
row.layoutSizingHorizontal = 'FILL';
|
|
438
|
-
row.layoutSizingVertical = 'HUG';
|
|
439
|
-
row.fills = [];
|
|
440
|
-
parent.appendChild(row);
|
|
441
|
-
|
|
442
|
-
// The bar rectangle — width bound to spacing variable
|
|
443
|
-
const bar = figma.createRectangle();
|
|
444
|
-
bar.resize(value, 16);
|
|
445
|
-
bar.cornerRadius = 3;
|
|
446
|
-
bar.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }];
|
|
447
|
-
// Bind width to the spacing variable so it reflects the actual token value
|
|
448
|
-
if (variable) {
|
|
449
|
-
bar.setBoundVariable('width', variable);
|
|
450
|
-
}
|
|
451
|
-
row.appendChild(bar);
|
|
452
|
-
|
|
453
|
-
// Label: "spacing/sm 8px var(--spacing-sm)"
|
|
454
|
-
const label = figma.createText();
|
|
455
|
-
label.fontName = { family: 'Inter', style: 'Regular' };
|
|
456
|
-
label.characters = `${name} ${value}px ${codeSyntax}`;
|
|
457
|
-
label.fontSize = 12;
|
|
458
|
-
label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
459
|
-
row.appendChild(label);
|
|
460
|
-
|
|
461
|
-
return row;
|
|
462
|
-
}
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Spacing section builder
|
|
466
|
-
|
|
467
|
-
```javascript
|
|
468
|
-
/**
|
|
469
|
-
* Creates the full spacing documentation section.
|
|
470
|
-
*
|
|
471
|
-
* @param {FrameNode} root - Root vertical stack.
|
|
472
|
-
* @param {Array<{name, value, variable, codeSyntax}>} spacingTokens - Token definitions.
|
|
473
|
-
*/
|
|
474
|
-
async function createSpacingSection(root, spacingTokens) {
|
|
475
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
476
|
-
|
|
477
|
-
const section = figma.createFrame();
|
|
478
|
-
section.name = 'Section/Spacing';
|
|
479
|
-
section.layoutMode = 'VERTICAL';
|
|
480
|
-
section.itemSpacing = 12;
|
|
481
|
-
section.layoutSizingHorizontal = 'FILL';
|
|
482
|
-
section.layoutSizingVertical = 'HUG';
|
|
483
|
-
section.fills = [];
|
|
484
|
-
root.appendChild(section);
|
|
485
|
-
|
|
486
|
-
const heading = figma.createText();
|
|
487
|
-
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
488
|
-
heading.characters = 'Spacing';
|
|
489
|
-
heading.fontSize = 32;
|
|
490
|
-
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
491
|
-
section.appendChild(heading);
|
|
492
|
-
|
|
493
|
-
for (const tok of spacingTokens) {
|
|
494
|
-
await createSpacingBar(section, tok.name, tok.value, tok.variable, tok.codeSyntax);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return section;
|
|
498
|
-
}
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
---
|
|
502
|
-
|
|
503
|
-
## 6. Shadow Cards (Elevation)
|
|
504
|
-
|
|
505
|
-
Elevation documentation shows cards with progressively stronger drop shadows, labeled with name and effect parameters.
|
|
506
|
-
|
|
507
|
-
### Single shadow card
|
|
508
|
-
|
|
509
|
-
```javascript
|
|
510
|
-
/**
|
|
511
|
-
* Creates a shadow card: a white rectangle with a drop shadow effect,
|
|
512
|
-
* labeled with the elevation name and shadow parameters.
|
|
513
|
-
*
|
|
514
|
-
* @param {FrameNode} parent - The horizontal row to append to.
|
|
515
|
-
* @param {string} name - Elevation name (e.g. "Shadow/Medium").
|
|
516
|
-
* @param {DropShadowEffect[]} effects - Array of Figma effect objects.
|
|
517
|
-
*/
|
|
518
|
-
async function createShadowCard(parent, name, effects) {
|
|
519
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
520
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
521
|
-
|
|
522
|
-
const card = figma.createFrame();
|
|
523
|
-
card.name = `ShadowCard/${name}`;
|
|
524
|
-
card.layoutMode = 'VERTICAL';
|
|
525
|
-
card.primaryAxisAlignItems = 'CENTER';
|
|
526
|
-
card.counterAxisAlignItems = 'CENTER';
|
|
527
|
-
card.itemSpacing = 8;
|
|
528
|
-
card.paddingTop = 16;
|
|
529
|
-
card.paddingBottom = 16;
|
|
530
|
-
card.resize(120, 120);
|
|
531
|
-
card.cornerRadius = 8;
|
|
532
|
-
card.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
533
|
-
card.effects = effects;
|
|
534
|
-
parent.appendChild(card);
|
|
535
|
-
|
|
536
|
-
// Elevation name
|
|
537
|
-
const nameLabel = figma.createText();
|
|
538
|
-
nameLabel.fontName = { family: 'Inter', style: 'Medium' };
|
|
539
|
-
nameLabel.characters = name.split('/').pop();
|
|
540
|
-
nameLabel.fontSize = 12;
|
|
541
|
-
nameLabel.textAlignHorizontal = 'CENTER';
|
|
542
|
-
nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }];
|
|
543
|
-
card.appendChild(nameLabel);
|
|
544
|
-
|
|
545
|
-
// Effect parameters as small text
|
|
546
|
-
if (effects.length > 0) {
|
|
547
|
-
const e = effects[0];
|
|
548
|
-
if (e.type === 'DROP_SHADOW') {
|
|
549
|
-
const params = figma.createText();
|
|
550
|
-
params.fontName = { family: 'Inter', style: 'Regular' };
|
|
551
|
-
params.characters = `x:${e.offset.x} y:${e.offset.y}\nblur:${e.radius}`;
|
|
552
|
-
params.fontSize = 10;
|
|
553
|
-
params.textAlignHorizontal = 'CENTER';
|
|
554
|
-
params.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
555
|
-
card.appendChild(params);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
return card;
|
|
560
|
-
}
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
### Shadow section builder
|
|
564
|
-
|
|
565
|
-
```javascript
|
|
566
|
-
/**
|
|
567
|
-
* Creates the full elevation/shadow documentation section.
|
|
568
|
-
*
|
|
569
|
-
* @param {FrameNode} root - Root vertical stack.
|
|
570
|
-
* @param {Array<{name, effects}>} shadowTokens - Shadow definitions.
|
|
571
|
-
*/
|
|
572
|
-
async function createShadowSection(root, shadowTokens) {
|
|
573
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
574
|
-
|
|
575
|
-
const section = figma.createFrame();
|
|
576
|
-
section.name = 'Section/Elevation';
|
|
577
|
-
section.layoutMode = 'VERTICAL';
|
|
578
|
-
section.itemSpacing = 24;
|
|
579
|
-
section.layoutSizingHorizontal = 'FILL';
|
|
580
|
-
section.layoutSizingVertical = 'HUG';
|
|
581
|
-
section.fills = [];
|
|
582
|
-
root.appendChild(section);
|
|
583
|
-
|
|
584
|
-
const heading = figma.createText();
|
|
585
|
-
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
586
|
-
heading.characters = 'Elevation';
|
|
587
|
-
heading.fontSize = 32;
|
|
588
|
-
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
589
|
-
section.appendChild(heading);
|
|
590
|
-
|
|
591
|
-
// Cards row — extra top padding so shadows are visible
|
|
592
|
-
const row = figma.createFrame();
|
|
593
|
-
row.name = 'Elevation/Row';
|
|
594
|
-
row.layoutMode = 'HORIZONTAL';
|
|
595
|
-
row.itemSpacing = 32;
|
|
596
|
-
row.paddingTop = 24;
|
|
597
|
-
row.paddingBottom = 40;
|
|
598
|
-
row.layoutSizingHorizontal = 'FILL';
|
|
599
|
-
row.layoutSizingVertical = 'HUG';
|
|
600
|
-
row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }];
|
|
601
|
-
row.cornerRadius = 8;
|
|
602
|
-
row.paddingLeft = 24;
|
|
603
|
-
row.paddingRight = 24;
|
|
604
|
-
section.appendChild(row);
|
|
605
|
-
|
|
606
|
-
for (const tok of shadowTokens) {
|
|
607
|
-
await createShadowCard(row, tok.name, tok.effects);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
return section;
|
|
611
|
-
}
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
---
|
|
615
|
-
|
|
616
|
-
## 7. Border Radius Demo
|
|
617
|
-
|
|
618
|
-
Border radius documentation shows rectangles at each corner radius value, labeled with the token name and pixel value.
|
|
619
|
-
|
|
620
|
-
### Single radius card
|
|
621
|
-
|
|
622
|
-
```javascript
|
|
623
|
-
/**
|
|
624
|
-
* Creates a single border radius card: a square with corner radius applied,
|
|
625
|
-
* labeled with the token name and pixel value.
|
|
626
|
-
*
|
|
627
|
-
* @param {FrameNode} parent - The horizontal row to append to.
|
|
628
|
-
* @param {string} name - Token name (e.g. "radius/md").
|
|
629
|
-
* @param {number} value - Corner radius in pixels (0 for none, 9999 for full).
|
|
630
|
-
* @param {Variable} [variable] - Optional Figma Variable to bind corner radius.
|
|
631
|
-
*/
|
|
632
|
-
async function createRadiusCard(parent, name, value, variable) {
|
|
633
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
634
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
635
|
-
|
|
636
|
-
const wrapper = figma.createFrame();
|
|
637
|
-
wrapper.name = `Radius/${name}`;
|
|
638
|
-
wrapper.layoutMode = 'VERTICAL';
|
|
639
|
-
wrapper.primaryAxisAlignItems = 'CENTER';
|
|
640
|
-
wrapper.counterAxisAlignItems = 'CENTER';
|
|
641
|
-
wrapper.itemSpacing = 8;
|
|
642
|
-
wrapper.fills = [];
|
|
643
|
-
wrapper.layoutSizingHorizontal = 'FIXED';
|
|
644
|
-
wrapper.layoutSizingVertical = 'HUG';
|
|
645
|
-
wrapper.resize(96, 1);
|
|
646
|
-
parent.appendChild(wrapper);
|
|
647
|
-
|
|
648
|
-
const rect = figma.createRectangle();
|
|
649
|
-
rect.resize(72, 72);
|
|
650
|
-
rect.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98, a: 0.15 } }];
|
|
651
|
-
rect.strokes = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }];
|
|
652
|
-
rect.strokeWeight = 1.5;
|
|
653
|
-
|
|
654
|
-
// Cap display value — 9999 is how Figma represents "full/pill"
|
|
655
|
-
const displayRadius = Math.min(value, 36);
|
|
656
|
-
rect.cornerRadius = displayRadius;
|
|
657
|
-
|
|
658
|
-
// Bind to variable if provided
|
|
659
|
-
if (variable) {
|
|
660
|
-
rect.setBoundVariable('cornerRadius', variable);
|
|
661
|
-
}
|
|
662
|
-
wrapper.appendChild(rect);
|
|
663
|
-
|
|
664
|
-
const nameLabel = figma.createText();
|
|
665
|
-
nameLabel.fontName = { family: 'Inter', style: 'Medium' };
|
|
666
|
-
nameLabel.characters = name.split('/').pop();
|
|
667
|
-
nameLabel.fontSize = 11;
|
|
668
|
-
nameLabel.textAlignHorizontal = 'CENTER';
|
|
669
|
-
nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }];
|
|
670
|
-
wrapper.appendChild(nameLabel);
|
|
671
|
-
|
|
672
|
-
const valueLabel = figma.createText();
|
|
673
|
-
valueLabel.fontName = { family: 'Inter', style: 'Regular' };
|
|
674
|
-
valueLabel.characters = value >= 9999 ? 'full' : `${value}px`;
|
|
675
|
-
valueLabel.fontSize = 10;
|
|
676
|
-
valueLabel.textAlignHorizontal = 'CENTER';
|
|
677
|
-
valueLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
678
|
-
wrapper.appendChild(valueLabel);
|
|
679
|
-
|
|
680
|
-
return wrapper;
|
|
681
|
-
}
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
### Radius section builder
|
|
685
|
-
|
|
686
|
-
```javascript
|
|
687
|
-
/**
|
|
688
|
-
* Creates the full border radius documentation section.
|
|
689
|
-
*
|
|
690
|
-
* @param {FrameNode} root - Root vertical stack.
|
|
691
|
-
* @param {Array<{name, value, variable}>} radiusTokens - Radius token definitions.
|
|
692
|
-
*/
|
|
693
|
-
async function createRadiusSection(root, radiusTokens) {
|
|
694
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
695
|
-
|
|
696
|
-
const section = figma.createFrame();
|
|
697
|
-
section.name = 'Section/Radius';
|
|
698
|
-
section.layoutMode = 'VERTICAL';
|
|
699
|
-
section.itemSpacing = 24;
|
|
700
|
-
section.layoutSizingHorizontal = 'FILL';
|
|
701
|
-
section.layoutSizingVertical = 'HUG';
|
|
702
|
-
section.fills = [];
|
|
703
|
-
root.appendChild(section);
|
|
704
|
-
|
|
705
|
-
const heading = figma.createText();
|
|
706
|
-
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
707
|
-
heading.characters = 'Border Radius';
|
|
708
|
-
heading.fontSize = 32;
|
|
709
|
-
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
710
|
-
section.appendChild(heading);
|
|
711
|
-
|
|
712
|
-
const row = figma.createFrame();
|
|
713
|
-
row.name = 'Radius/Row';
|
|
714
|
-
row.layoutMode = 'HORIZONTAL';
|
|
715
|
-
row.itemSpacing = 24;
|
|
716
|
-
row.paddingTop = 24;
|
|
717
|
-
row.paddingBottom = 24;
|
|
718
|
-
row.paddingLeft = 24;
|
|
719
|
-
row.paddingRight = 24;
|
|
720
|
-
row.layoutSizingHorizontal = 'FILL';
|
|
721
|
-
row.layoutSizingVertical = 'HUG';
|
|
722
|
-
row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }];
|
|
723
|
-
row.cornerRadius = 8;
|
|
724
|
-
section.appendChild(row);
|
|
725
|
-
|
|
726
|
-
for (const tok of radiusTokens) {
|
|
727
|
-
await createRadiusCard(row, tok.name, tok.value, tok.variable);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
return section;
|
|
731
|
-
}
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
---
|
|
735
|
-
|
|
736
|
-
## 8. Documentation Alongside Components
|
|
737
|
-
|
|
738
|
-
Each component page should include a documentation frame directly on the canvas, placed to the left of the component set. This keeps docs and the component in sync without requiring a separate file.
|
|
739
|
-
|
|
740
|
-
### Component page documentation frame
|
|
741
|
-
|
|
742
|
-
```javascript
|
|
743
|
-
/**
|
|
744
|
-
* Creates the documentation frame for a component page: title, description,
|
|
745
|
-
* and usage notes, positioned at x=0 with the component set to its right.
|
|
746
|
-
*
|
|
747
|
-
* @param {PageNode} page - The component page (must already be current).
|
|
748
|
-
* @param {string} componentName - The component name.
|
|
749
|
-
* @param {string} description - What the component does and when to use it.
|
|
750
|
-
* @param {string[]} usageNotes - Bullet points for usage guidance.
|
|
751
|
-
* @returns {FrameNode} The documentation frame.
|
|
752
|
-
*/
|
|
753
|
-
async function createComponentDocFrame(page, componentName, description, usageNotes) {
|
|
754
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
755
|
-
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
756
|
-
|
|
757
|
-
const doc = figma.createFrame();
|
|
758
|
-
doc.name = '_Doc';
|
|
759
|
-
doc.layoutMode = 'VERTICAL';
|
|
760
|
-
doc.itemSpacing = 16;
|
|
761
|
-
doc.paddingTop = 40;
|
|
762
|
-
doc.paddingBottom = 40;
|
|
763
|
-
doc.paddingLeft = 40;
|
|
764
|
-
doc.paddingRight = 40;
|
|
765
|
-
doc.layoutSizingHorizontal = 'FIXED';
|
|
766
|
-
doc.layoutSizingVertical = 'HUG';
|
|
767
|
-
doc.resize(360, 1);
|
|
768
|
-
doc.fills = [];
|
|
769
|
-
doc.x = 0;
|
|
770
|
-
doc.y = 0;
|
|
771
|
-
page.appendChild(doc);
|
|
772
|
-
|
|
773
|
-
// Component name — large heading
|
|
774
|
-
const title = figma.createText();
|
|
775
|
-
title.fontName = { family: 'Inter', style: 'Bold' };
|
|
776
|
-
title.characters = componentName;
|
|
777
|
-
title.fontSize = 28;
|
|
778
|
-
title.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
779
|
-
title.layoutSizingHorizontal = 'FILL';
|
|
780
|
-
doc.appendChild(title);
|
|
781
|
-
|
|
782
|
-
// Description
|
|
783
|
-
const descText = figma.createText();
|
|
784
|
-
descText.fontName = { family: 'Inter', style: 'Regular' };
|
|
785
|
-
descText.characters = description;
|
|
786
|
-
descText.fontSize = 13;
|
|
787
|
-
descText.lineHeight = { value: 20, unit: 'PIXELS' };
|
|
788
|
-
descText.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
789
|
-
descText.layoutSizingHorizontal = 'FILL';
|
|
790
|
-
doc.appendChild(descText);
|
|
791
|
-
|
|
792
|
-
// Divider
|
|
793
|
-
const divider = figma.createRectangle();
|
|
794
|
-
divider.resize(280, 1);
|
|
795
|
-
divider.fills = [{ type: 'SOLID', color: { r: 0.88, g: 0.88, b: 0.88 } }];
|
|
796
|
-
divider.layoutSizingHorizontal = 'FILL';
|
|
797
|
-
doc.appendChild(divider);
|
|
798
|
-
|
|
799
|
-
// Usage notes
|
|
800
|
-
if (usageNotes.length > 0) {
|
|
801
|
-
const usageHeading = figma.createText();
|
|
802
|
-
usageHeading.fontName = { family: 'Inter', style: 'Bold' };
|
|
803
|
-
usageHeading.characters = 'Usage';
|
|
804
|
-
usageHeading.fontSize = 13;
|
|
805
|
-
usageHeading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
806
|
-
doc.appendChild(usageHeading);
|
|
807
|
-
|
|
808
|
-
for (const note of usageNotes) {
|
|
809
|
-
const noteText = figma.createText();
|
|
810
|
-
noteText.fontName = { family: 'Inter', style: 'Regular' };
|
|
811
|
-
noteText.characters = `• ${note}`;
|
|
812
|
-
noteText.fontSize = 12;
|
|
813
|
-
noteText.lineHeight = { value: 18, unit: 'PIXELS' };
|
|
814
|
-
noteText.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }];
|
|
815
|
-
noteText.layoutSizingHorizontal = 'FILL';
|
|
816
|
-
doc.appendChild(noteText);
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
return doc;
|
|
821
|
-
}
|
|
822
|
-
```
|
|
823
|
-
|
|
824
|
-
---
|
|
825
|
-
|
|
826
|
-
## 9. Critical Rules
|
|
827
|
-
|
|
828
|
-
1. **Bind swatches to variables** — use `setBoundVariableForPaint` for color fills, `setBoundVariable('width', ...)` for spacing bars, and `setBoundVariable('cornerRadius', ...)` for radius cards. Never hardcode values that have corresponding variables.
|
|
829
|
-
2. **Foundations page comes before component pages** — always insert it between the file structure separators and the first component page.
|
|
830
|
-
3. **Show both primitive and semantic layers** — if the system has a Primitives collection and a semantic Color collection, document both on the Foundations page with clear section labels.
|
|
831
|
-
4. **Page frame width = 1440px** — this is the convention across Simple DS, Polaris, and Material 3. Use it unless you detect a different existing convention via `get_metadata`.
|
|
832
|
-
5. **Section spacing = 64–80px** — the gap between color / typography / spacing / shadow / radius sections should be at minimum 64px so the page is scannable.
|
|
833
|
-
6. **Match existing page style** — if the target file uses emoji page name prefixes or a decorative separator style, carry that through to the Foundations page name.
|
|
834
|
-
7. **Include code syntax in labels** — where variables have code syntax set, display the CSS variable name in the swatch/bar label so developers can copy it directly.
|
|
1
|
+
> Part of the [figma-generate-library skill](../SKILL.md).
|
|
2
|
+
|
|
3
|
+
# Documentation Creation Reference
|
|
4
|
+
|
|
5
|
+
This reference covers Phase 2 of the design system build: the cover page, foundations documentation page (color swatches, type specimens, spacing bars, shadow cards, radius demo), page layout dimensions, and inline component documentation. Every code block is complete `use_figma`-ready JavaScript (helper-function form — no IIFE wrapper, no `closePlugin` — meant to be embedded in a larger script).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Cover Page
|
|
10
|
+
|
|
11
|
+
The cover page is always the first page in the file. It is a branded title card that sets context for anyone opening the file.
|
|
12
|
+
|
|
13
|
+
### What to include
|
|
14
|
+
|
|
15
|
+
- File/system name as a large heading (48–72px)
|
|
16
|
+
- Version string or date
|
|
17
|
+
- Brief tagline (1 sentence)
|
|
18
|
+
- Optional: color block background using the primary brand color variable
|
|
19
|
+
|
|
20
|
+
### Cover page dimensions
|
|
21
|
+
|
|
22
|
+
The cover frame should be **1440 × 900px** — this matches the default Figma canvas and looks correct in the page thumbnail.
|
|
23
|
+
|
|
24
|
+
### use_figma for cover page
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
async function createCoverPage(systemName, tagline, version, primaryColorVar) {
|
|
28
|
+
// primaryColorVar: a Figma Variable object for the brand primary fill
|
|
29
|
+
const page = figma.createPage();
|
|
30
|
+
page.name = 'Cover';
|
|
31
|
+
await figma.setCurrentPageAsync(page);
|
|
32
|
+
|
|
33
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
34
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
35
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
36
|
+
|
|
37
|
+
const frame = figma.createFrame();
|
|
38
|
+
frame.name = 'Cover';
|
|
39
|
+
frame.resize(1440, 900);
|
|
40
|
+
frame.x = 0;
|
|
41
|
+
frame.y = 0;
|
|
42
|
+
frame.layoutMode = 'VERTICAL';
|
|
43
|
+
frame.primaryAxisAlignItems = 'CENTER';
|
|
44
|
+
frame.counterAxisAlignItems = 'CENTER';
|
|
45
|
+
frame.itemSpacing = 16;
|
|
46
|
+
frame.paddingTop = 0;
|
|
47
|
+
frame.paddingBottom = 0;
|
|
48
|
+
frame.paddingLeft = 0;
|
|
49
|
+
frame.paddingRight = 0;
|
|
50
|
+
|
|
51
|
+
// Background: bind to primary variable if provided, else solid dark
|
|
52
|
+
if (primaryColorVar) {
|
|
53
|
+
const bgPaint = figma.variables.setBoundVariableForPaint(
|
|
54
|
+
{ type: 'SOLID', color: { r: 0.05, g: 0.05, b: 0.05 } },
|
|
55
|
+
'color',
|
|
56
|
+
primaryColorVar
|
|
57
|
+
);
|
|
58
|
+
frame.fills = [bgPaint];
|
|
59
|
+
} else {
|
|
60
|
+
frame.fills = [{ type: 'SOLID', color: { r: 0.06, g: 0.06, b: 0.07 } }];
|
|
61
|
+
}
|
|
62
|
+
page.appendChild(frame);
|
|
63
|
+
|
|
64
|
+
// System name heading
|
|
65
|
+
const title = figma.createText();
|
|
66
|
+
title.fontName = { family: 'Inter', style: 'Bold' };
|
|
67
|
+
title.characters = systemName;
|
|
68
|
+
title.fontSize = 64;
|
|
69
|
+
title.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
70
|
+
title.textAlignHorizontal = 'CENTER';
|
|
71
|
+
frame.appendChild(title);
|
|
72
|
+
|
|
73
|
+
// Tagline
|
|
74
|
+
const tag = figma.createText();
|
|
75
|
+
tag.fontName = { family: 'Inter', style: 'Regular' };
|
|
76
|
+
tag.characters = tagline;
|
|
77
|
+
tag.fontSize = 20;
|
|
78
|
+
tag.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.7 } }];
|
|
79
|
+
tag.textAlignHorizontal = 'CENTER';
|
|
80
|
+
frame.appendChild(tag);
|
|
81
|
+
|
|
82
|
+
// Version
|
|
83
|
+
const ver = figma.createText();
|
|
84
|
+
ver.fontName = { family: 'Inter', style: 'Medium' };
|
|
85
|
+
ver.characters = version;
|
|
86
|
+
ver.fontSize = 13;
|
|
87
|
+
ver.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.45 } }];
|
|
88
|
+
ver.textAlignHorizontal = 'CENTER';
|
|
89
|
+
frame.appendChild(ver);
|
|
90
|
+
|
|
91
|
+
return { page, frameId: frame.id };
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 2. Foundations Page
|
|
98
|
+
|
|
99
|
+
The Foundations page is always placed **before any component pages**. It visually documents the design tokens — colors, typography, spacing, shadows, and border radii — so designers and engineers can see available primitives at a glance.
|
|
100
|
+
|
|
101
|
+
### Page layout dimensions
|
|
102
|
+
|
|
103
|
+
The outer documentation frame should be **1440px wide**. Sections stack vertically with **64–100px gaps** between them. Each section frame fills the full 1440px width and hugs its content vertically.
|
|
104
|
+
|
|
105
|
+
### Full Foundations page skeleton
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
async function createFoundationsPage() {
|
|
109
|
+
const page = figma.createPage();
|
|
110
|
+
page.name = 'Foundations';
|
|
111
|
+
await figma.setCurrentPageAsync(page);
|
|
112
|
+
|
|
113
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
114
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
115
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
116
|
+
|
|
117
|
+
// Root scroll frame
|
|
118
|
+
const root = figma.createFrame();
|
|
119
|
+
root.name = 'Foundations';
|
|
120
|
+
root.layoutMode = 'VERTICAL';
|
|
121
|
+
root.primaryAxisAlignItems = 'MIN';
|
|
122
|
+
root.counterAxisAlignItems = 'MIN';
|
|
123
|
+
root.itemSpacing = 80;
|
|
124
|
+
root.paddingTop = 80;
|
|
125
|
+
root.paddingBottom = 120;
|
|
126
|
+
root.paddingLeft = 80;
|
|
127
|
+
root.paddingRight = 80;
|
|
128
|
+
root.layoutSizingHorizontal = 'FIXED';
|
|
129
|
+
root.layoutSizingVertical = 'HUG';
|
|
130
|
+
root.resize(1440, 1);
|
|
131
|
+
root.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
132
|
+
page.appendChild(root);
|
|
133
|
+
|
|
134
|
+
return { page, root };
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 3. Color Swatches (bound to variables)
|
|
141
|
+
|
|
142
|
+
Color swatches must be **bound to actual Figma variables** — never hardcode hex values in swatch fills. This keeps documentation in sync automatically when variable values change.
|
|
143
|
+
|
|
144
|
+
### Single color swatch
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
/**
|
|
148
|
+
* Creates a single color swatch card (rectangle + variable name label).
|
|
149
|
+
* The swatch rectangle fill is bound to the provided variable.
|
|
150
|
+
*
|
|
151
|
+
* @param {FrameNode} parent - The auto-layout row to append to.
|
|
152
|
+
* @param {string} varName - Display name (e.g. "color/bg/primary").
|
|
153
|
+
* @param {Variable} variable - The Figma Variable object to bind to.
|
|
154
|
+
* @returns {FrameNode} The swatch frame.
|
|
155
|
+
*/
|
|
156
|
+
async function createColorSwatch(parent, varName, variable) {
|
|
157
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
158
|
+
|
|
159
|
+
const swatchFrame = figma.createFrame();
|
|
160
|
+
swatchFrame.name = `Swatch/${varName}`;
|
|
161
|
+
swatchFrame.layoutMode = 'VERTICAL';
|
|
162
|
+
swatchFrame.primaryAxisAlignItems = 'MIN';
|
|
163
|
+
swatchFrame.counterAxisAlignItems = 'MIN';
|
|
164
|
+
swatchFrame.itemSpacing = 6;
|
|
165
|
+
swatchFrame.layoutSizingHorizontal = 'FIXED';
|
|
166
|
+
swatchFrame.layoutSizingVertical = 'HUG';
|
|
167
|
+
swatchFrame.resize(88, 1);
|
|
168
|
+
swatchFrame.fills = [];
|
|
169
|
+
|
|
170
|
+
// Color rectangle — bound to variable
|
|
171
|
+
const rect = figma.createRectangle();
|
|
172
|
+
rect.resize(88, 88);
|
|
173
|
+
rect.cornerRadius = 8;
|
|
174
|
+
const paint = figma.variables.setBoundVariableForPaint(
|
|
175
|
+
{ type: 'SOLID', color: { r: 0.5, g: 0.5, b: 0.5 } },
|
|
176
|
+
'color',
|
|
177
|
+
variable
|
|
178
|
+
);
|
|
179
|
+
rect.fills = [paint];
|
|
180
|
+
swatchFrame.appendChild(rect);
|
|
181
|
+
|
|
182
|
+
// Name label
|
|
183
|
+
const label = figma.createText();
|
|
184
|
+
label.fontName = { family: 'Inter', style: 'Regular' };
|
|
185
|
+
label.characters = varName.split('/').pop(); // show leaf name only
|
|
186
|
+
label.fontSize = 10;
|
|
187
|
+
label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
188
|
+
label.layoutSizingHorizontal = 'FILL';
|
|
189
|
+
swatchFrame.appendChild(label);
|
|
190
|
+
|
|
191
|
+
// Full path tooltip label (smaller, lighter)
|
|
192
|
+
const pathLabel = figma.createText();
|
|
193
|
+
pathLabel.fontName = { family: 'Inter', style: 'Regular' };
|
|
194
|
+
pathLabel.characters = varName;
|
|
195
|
+
pathLabel.fontSize = 9;
|
|
196
|
+
pathLabel.fills = [{ type: 'SOLID', color: { r: 0.6, g: 0.6, b: 0.6 } }];
|
|
197
|
+
pathLabel.layoutSizingHorizontal = 'FILL';
|
|
198
|
+
swatchFrame.appendChild(pathLabel);
|
|
199
|
+
|
|
200
|
+
parent.appendChild(swatchFrame);
|
|
201
|
+
return swatchFrame;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Color section builder (primitives row + semantic grid)
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
/**
|
|
209
|
+
* Creates a complete color documentation section with a section heading,
|
|
210
|
+
* a row of primitive swatches, and a grid of semantic swatches.
|
|
211
|
+
*
|
|
212
|
+
* @param {FrameNode} root - The root vertical stack frame.
|
|
213
|
+
* @param {Variable[]} primitiveVars - Variables from the Primitives collection.
|
|
214
|
+
* @param {Variable[]} semanticVars - Variables from the semantic Color collection.
|
|
215
|
+
*/
|
|
216
|
+
async function createColorSection(root, primitiveVars, semanticVars) {
|
|
217
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
218
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
219
|
+
|
|
220
|
+
// Section container
|
|
221
|
+
const section = figma.createFrame();
|
|
222
|
+
section.name = 'Section/Colors';
|
|
223
|
+
section.layoutMode = 'VERTICAL';
|
|
224
|
+
section.itemSpacing = 24;
|
|
225
|
+
section.layoutSizingHorizontal = 'FILL';
|
|
226
|
+
section.layoutSizingVertical = 'HUG';
|
|
227
|
+
section.fills = [];
|
|
228
|
+
root.appendChild(section);
|
|
229
|
+
|
|
230
|
+
// Section heading
|
|
231
|
+
const heading = figma.createText();
|
|
232
|
+
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
233
|
+
heading.characters = 'Colors';
|
|
234
|
+
heading.fontSize = 32;
|
|
235
|
+
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
236
|
+
section.appendChild(heading);
|
|
237
|
+
|
|
238
|
+
// Description
|
|
239
|
+
const desc = figma.createText();
|
|
240
|
+
desc.fontName = { family: 'Inter', style: 'Regular' };
|
|
241
|
+
desc.characters = 'Primitive color palette and semantic color tokens. Semantic tokens reference primitives — always use semantic tokens in components.';
|
|
242
|
+
desc.fontSize = 14;
|
|
243
|
+
desc.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }];
|
|
244
|
+
desc.layoutSizingHorizontal = 'FILL';
|
|
245
|
+
section.appendChild(desc);
|
|
246
|
+
|
|
247
|
+
// Primitive swatches row
|
|
248
|
+
const primLabel = figma.createText();
|
|
249
|
+
primLabel.fontName = { family: 'Inter', style: 'Bold' };
|
|
250
|
+
primLabel.characters = 'Primitives';
|
|
251
|
+
primLabel.fontSize = 13;
|
|
252
|
+
primLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
253
|
+
section.appendChild(primLabel);
|
|
254
|
+
|
|
255
|
+
const primRow = figma.createFrame();
|
|
256
|
+
primRow.name = 'Primitives/Row';
|
|
257
|
+
primRow.layoutMode = 'HORIZONTAL';
|
|
258
|
+
primRow.itemSpacing = 12;
|
|
259
|
+
primRow.layoutSizingHorizontal = 'FILL';
|
|
260
|
+
primRow.layoutSizingVertical = 'HUG';
|
|
261
|
+
primRow.fills = [];
|
|
262
|
+
primRow.layoutWrap = 'WRAP';
|
|
263
|
+
section.appendChild(primRow);
|
|
264
|
+
|
|
265
|
+
for (const v of primitiveVars) {
|
|
266
|
+
await createColorSwatch(primRow, v.name, v);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Semantic swatches grid
|
|
270
|
+
if (semanticVars.length > 0) {
|
|
271
|
+
const semLabel = figma.createText();
|
|
272
|
+
semLabel.fontName = { family: 'Inter', style: 'Bold' };
|
|
273
|
+
semLabel.characters = 'Semantic';
|
|
274
|
+
semLabel.fontSize = 13;
|
|
275
|
+
semLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
276
|
+
section.appendChild(semLabel);
|
|
277
|
+
|
|
278
|
+
const semRow = figma.createFrame();
|
|
279
|
+
semRow.name = 'Semantic/Row';
|
|
280
|
+
semRow.layoutMode = 'HORIZONTAL';
|
|
281
|
+
semRow.itemSpacing = 12;
|
|
282
|
+
semRow.layoutSizingHorizontal = 'FILL';
|
|
283
|
+
semRow.layoutSizingVertical = 'HUG';
|
|
284
|
+
semRow.fills = [];
|
|
285
|
+
semRow.layoutWrap = 'WRAP';
|
|
286
|
+
section.appendChild(semRow);
|
|
287
|
+
|
|
288
|
+
for (const v of semanticVars) {
|
|
289
|
+
await createColorSwatch(semRow, v.name, v);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return section;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 4. Type Specimens
|
|
300
|
+
|
|
301
|
+
Typography specimens show each text style rendered at its actual size with a sample string, the style name, and its specifications.
|
|
302
|
+
|
|
303
|
+
### Single type specimen row
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
/**
|
|
307
|
+
* Creates a single type specimen row: style name (small label) + sample text +
|
|
308
|
+
* specification line (family · style · size · line-height).
|
|
309
|
+
*
|
|
310
|
+
* @param {FrameNode} parent - The parent vertical stack.
|
|
311
|
+
* @param {string} styleName - The text style name (e.g. "Display Large").
|
|
312
|
+
* @param {string} fontFamily - Font family (e.g. "Inter").
|
|
313
|
+
* @param {string} fontStyle - Font style (e.g. "Bold").
|
|
314
|
+
* @param {number} fontSize - Font size in pixels.
|
|
315
|
+
* @param {number} lineHeight - Line height in pixels.
|
|
316
|
+
* @returns {FrameNode} The specimen row frame.
|
|
317
|
+
*/
|
|
318
|
+
async function createTypeSpecimen(parent, styleName, fontFamily, fontStyle, fontSize, lineHeight) {
|
|
319
|
+
await figma.loadFontAsync({ family: fontFamily, style: fontStyle });
|
|
320
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
321
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
322
|
+
|
|
323
|
+
const row = figma.createFrame();
|
|
324
|
+
row.name = `Type/${styleName}`;
|
|
325
|
+
row.layoutMode = 'VERTICAL';
|
|
326
|
+
row.itemSpacing = 6;
|
|
327
|
+
row.paddingTop = 16;
|
|
328
|
+
row.paddingBottom = 16;
|
|
329
|
+
row.layoutSizingHorizontal = 'FILL';
|
|
330
|
+
row.layoutSizingVertical = 'HUG';
|
|
331
|
+
row.fills = [];
|
|
332
|
+
parent.appendChild(row);
|
|
333
|
+
|
|
334
|
+
// Style name label (small, muted)
|
|
335
|
+
const nameText = figma.createText();
|
|
336
|
+
nameText.fontName = { family: 'Inter', style: 'Medium' };
|
|
337
|
+
nameText.characters = styleName;
|
|
338
|
+
nameText.fontSize = 11;
|
|
339
|
+
nameText.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
340
|
+
nameText.layoutSizingHorizontal = 'FILL';
|
|
341
|
+
row.appendChild(nameText);
|
|
342
|
+
|
|
343
|
+
// Sample text rendered in the actual style
|
|
344
|
+
const specimen = figma.createText();
|
|
345
|
+
specimen.fontName = { family: fontFamily, style: fontStyle };
|
|
346
|
+
specimen.characters = 'The quick brown fox jumps over the lazy dog';
|
|
347
|
+
specimen.fontSize = fontSize;
|
|
348
|
+
specimen.lineHeight = { value: lineHeight, unit: 'PIXELS' };
|
|
349
|
+
specimen.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
350
|
+
specimen.layoutSizingHorizontal = 'FILL';
|
|
351
|
+
row.appendChild(specimen);
|
|
352
|
+
|
|
353
|
+
// Specification line
|
|
354
|
+
const specs = figma.createText();
|
|
355
|
+
specs.fontName = { family: 'Inter', style: 'Regular' };
|
|
356
|
+
specs.characters = `${fontFamily} ${fontStyle} · ${fontSize}px · ${lineHeight}px line height`;
|
|
357
|
+
specs.fontSize = 11;
|
|
358
|
+
specs.fills = [{ type: 'SOLID', color: { r: 0.65, g: 0.65, b: 0.65 } }];
|
|
359
|
+
specs.layoutSizingHorizontal = 'FILL';
|
|
360
|
+
row.appendChild(specs);
|
|
361
|
+
|
|
362
|
+
// Divider line
|
|
363
|
+
const divider = figma.createRectangle();
|
|
364
|
+
divider.resize(1280, 1);
|
|
365
|
+
divider.fills = [{ type: 'SOLID', color: { r: 0.9, g: 0.9, b: 0.9 } }];
|
|
366
|
+
divider.layoutSizingHorizontal = 'FILL';
|
|
367
|
+
row.appendChild(divider);
|
|
368
|
+
|
|
369
|
+
return row;
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Typography section builder
|
|
374
|
+
|
|
375
|
+
```javascript
|
|
376
|
+
/**
|
|
377
|
+
* Creates a complete typography documentation section.
|
|
378
|
+
* Pass an array of style definitions; the function renders one specimen per entry.
|
|
379
|
+
*
|
|
380
|
+
* @param {FrameNode} root - Root vertical stack.
|
|
381
|
+
* @param {Array<{name, family, style, size, lineHeight}>} typeStyles - Style definitions.
|
|
382
|
+
*/
|
|
383
|
+
async function createTypographySection(root, typeStyles) {
|
|
384
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
385
|
+
|
|
386
|
+
const section = figma.createFrame();
|
|
387
|
+
section.name = 'Section/Typography';
|
|
388
|
+
section.layoutMode = 'VERTICAL';
|
|
389
|
+
section.itemSpacing = 0;
|
|
390
|
+
section.layoutSizingHorizontal = 'FILL';
|
|
391
|
+
section.layoutSizingVertical = 'HUG';
|
|
392
|
+
section.fills = [];
|
|
393
|
+
root.appendChild(section);
|
|
394
|
+
|
|
395
|
+
const heading = figma.createText();
|
|
396
|
+
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
397
|
+
heading.characters = 'Typography';
|
|
398
|
+
heading.fontSize = 32;
|
|
399
|
+
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
400
|
+
section.appendChild(heading);
|
|
401
|
+
|
|
402
|
+
for (const ts of typeStyles) {
|
|
403
|
+
await createTypeSpecimen(section, ts.name, ts.family, ts.style, ts.size, ts.lineHeight);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return section;
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## 5. Spacing Bars
|
|
413
|
+
|
|
414
|
+
Spacing bars show each spacing token as a filled rectangle whose width equals the spacing value. Shorter bars for small values, longer bars for large values — the visual encoding is immediate.
|
|
415
|
+
|
|
416
|
+
### Spacing bar row
|
|
417
|
+
|
|
418
|
+
```javascript
|
|
419
|
+
/**
|
|
420
|
+
* Creates a single spacing bar: a colored rectangle sized to the spacing value,
|
|
421
|
+
* with a label showing name + pixel value + code syntax.
|
|
422
|
+
*
|
|
423
|
+
* @param {FrameNode} parent - Parent vertical stack.
|
|
424
|
+
* @param {string} name - Token name (e.g. "spacing/sm").
|
|
425
|
+
* @param {number} value - Spacing value in pixels.
|
|
426
|
+
* @param {Variable} variable - Figma Variable to bind the width to.
|
|
427
|
+
* @param {string} codeSyntax - CSS variable string (e.g. "var(--spacing-sm)").
|
|
428
|
+
*/
|
|
429
|
+
async function createSpacingBar(parent, name, value, variable, codeSyntax) {
|
|
430
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
431
|
+
|
|
432
|
+
const row = figma.createFrame();
|
|
433
|
+
row.name = `Spacing/${name}`;
|
|
434
|
+
row.layoutMode = 'HORIZONTAL';
|
|
435
|
+
row.counterAxisAlignItems = 'CENTER';
|
|
436
|
+
row.itemSpacing = 16;
|
|
437
|
+
row.layoutSizingHorizontal = 'FILL';
|
|
438
|
+
row.layoutSizingVertical = 'HUG';
|
|
439
|
+
row.fills = [];
|
|
440
|
+
parent.appendChild(row);
|
|
441
|
+
|
|
442
|
+
// The bar rectangle — width bound to spacing variable
|
|
443
|
+
const bar = figma.createRectangle();
|
|
444
|
+
bar.resize(value, 16);
|
|
445
|
+
bar.cornerRadius = 3;
|
|
446
|
+
bar.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }];
|
|
447
|
+
// Bind width to the spacing variable so it reflects the actual token value
|
|
448
|
+
if (variable) {
|
|
449
|
+
bar.setBoundVariable('width', variable);
|
|
450
|
+
}
|
|
451
|
+
row.appendChild(bar);
|
|
452
|
+
|
|
453
|
+
// Label: "spacing/sm 8px var(--spacing-sm)"
|
|
454
|
+
const label = figma.createText();
|
|
455
|
+
label.fontName = { family: 'Inter', style: 'Regular' };
|
|
456
|
+
label.characters = `${name} ${value}px ${codeSyntax}`;
|
|
457
|
+
label.fontSize = 12;
|
|
458
|
+
label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
459
|
+
row.appendChild(label);
|
|
460
|
+
|
|
461
|
+
return row;
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Spacing section builder
|
|
466
|
+
|
|
467
|
+
```javascript
|
|
468
|
+
/**
|
|
469
|
+
* Creates the full spacing documentation section.
|
|
470
|
+
*
|
|
471
|
+
* @param {FrameNode} root - Root vertical stack.
|
|
472
|
+
* @param {Array<{name, value, variable, codeSyntax}>} spacingTokens - Token definitions.
|
|
473
|
+
*/
|
|
474
|
+
async function createSpacingSection(root, spacingTokens) {
|
|
475
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
476
|
+
|
|
477
|
+
const section = figma.createFrame();
|
|
478
|
+
section.name = 'Section/Spacing';
|
|
479
|
+
section.layoutMode = 'VERTICAL';
|
|
480
|
+
section.itemSpacing = 12;
|
|
481
|
+
section.layoutSizingHorizontal = 'FILL';
|
|
482
|
+
section.layoutSizingVertical = 'HUG';
|
|
483
|
+
section.fills = [];
|
|
484
|
+
root.appendChild(section);
|
|
485
|
+
|
|
486
|
+
const heading = figma.createText();
|
|
487
|
+
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
488
|
+
heading.characters = 'Spacing';
|
|
489
|
+
heading.fontSize = 32;
|
|
490
|
+
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
491
|
+
section.appendChild(heading);
|
|
492
|
+
|
|
493
|
+
for (const tok of spacingTokens) {
|
|
494
|
+
await createSpacingBar(section, tok.name, tok.value, tok.variable, tok.codeSyntax);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return section;
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## 6. Shadow Cards (Elevation)
|
|
504
|
+
|
|
505
|
+
Elevation documentation shows cards with progressively stronger drop shadows, labeled with name and effect parameters.
|
|
506
|
+
|
|
507
|
+
### Single shadow card
|
|
508
|
+
|
|
509
|
+
```javascript
|
|
510
|
+
/**
|
|
511
|
+
* Creates a shadow card: a white rectangle with a drop shadow effect,
|
|
512
|
+
* labeled with the elevation name and shadow parameters.
|
|
513
|
+
*
|
|
514
|
+
* @param {FrameNode} parent - The horizontal row to append to.
|
|
515
|
+
* @param {string} name - Elevation name (e.g. "Shadow/Medium").
|
|
516
|
+
* @param {DropShadowEffect[]} effects - Array of Figma effect objects.
|
|
517
|
+
*/
|
|
518
|
+
async function createShadowCard(parent, name, effects) {
|
|
519
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
520
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
521
|
+
|
|
522
|
+
const card = figma.createFrame();
|
|
523
|
+
card.name = `ShadowCard/${name}`;
|
|
524
|
+
card.layoutMode = 'VERTICAL';
|
|
525
|
+
card.primaryAxisAlignItems = 'CENTER';
|
|
526
|
+
card.counterAxisAlignItems = 'CENTER';
|
|
527
|
+
card.itemSpacing = 8;
|
|
528
|
+
card.paddingTop = 16;
|
|
529
|
+
card.paddingBottom = 16;
|
|
530
|
+
card.resize(120, 120);
|
|
531
|
+
card.cornerRadius = 8;
|
|
532
|
+
card.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
|
|
533
|
+
card.effects = effects;
|
|
534
|
+
parent.appendChild(card);
|
|
535
|
+
|
|
536
|
+
// Elevation name
|
|
537
|
+
const nameLabel = figma.createText();
|
|
538
|
+
nameLabel.fontName = { family: 'Inter', style: 'Medium' };
|
|
539
|
+
nameLabel.characters = name.split('/').pop();
|
|
540
|
+
nameLabel.fontSize = 12;
|
|
541
|
+
nameLabel.textAlignHorizontal = 'CENTER';
|
|
542
|
+
nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }];
|
|
543
|
+
card.appendChild(nameLabel);
|
|
544
|
+
|
|
545
|
+
// Effect parameters as small text
|
|
546
|
+
if (effects.length > 0) {
|
|
547
|
+
const e = effects[0];
|
|
548
|
+
if (e.type === 'DROP_SHADOW') {
|
|
549
|
+
const params = figma.createText();
|
|
550
|
+
params.fontName = { family: 'Inter', style: 'Regular' };
|
|
551
|
+
params.characters = `x:${e.offset.x} y:${e.offset.y}\nblur:${e.radius}`;
|
|
552
|
+
params.fontSize = 10;
|
|
553
|
+
params.textAlignHorizontal = 'CENTER';
|
|
554
|
+
params.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
555
|
+
card.appendChild(params);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return card;
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Shadow section builder
|
|
564
|
+
|
|
565
|
+
```javascript
|
|
566
|
+
/**
|
|
567
|
+
* Creates the full elevation/shadow documentation section.
|
|
568
|
+
*
|
|
569
|
+
* @param {FrameNode} root - Root vertical stack.
|
|
570
|
+
* @param {Array<{name, effects}>} shadowTokens - Shadow definitions.
|
|
571
|
+
*/
|
|
572
|
+
async function createShadowSection(root, shadowTokens) {
|
|
573
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
574
|
+
|
|
575
|
+
const section = figma.createFrame();
|
|
576
|
+
section.name = 'Section/Elevation';
|
|
577
|
+
section.layoutMode = 'VERTICAL';
|
|
578
|
+
section.itemSpacing = 24;
|
|
579
|
+
section.layoutSizingHorizontal = 'FILL';
|
|
580
|
+
section.layoutSizingVertical = 'HUG';
|
|
581
|
+
section.fills = [];
|
|
582
|
+
root.appendChild(section);
|
|
583
|
+
|
|
584
|
+
const heading = figma.createText();
|
|
585
|
+
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
586
|
+
heading.characters = 'Elevation';
|
|
587
|
+
heading.fontSize = 32;
|
|
588
|
+
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
589
|
+
section.appendChild(heading);
|
|
590
|
+
|
|
591
|
+
// Cards row — extra top padding so shadows are visible
|
|
592
|
+
const row = figma.createFrame();
|
|
593
|
+
row.name = 'Elevation/Row';
|
|
594
|
+
row.layoutMode = 'HORIZONTAL';
|
|
595
|
+
row.itemSpacing = 32;
|
|
596
|
+
row.paddingTop = 24;
|
|
597
|
+
row.paddingBottom = 40;
|
|
598
|
+
row.layoutSizingHorizontal = 'FILL';
|
|
599
|
+
row.layoutSizingVertical = 'HUG';
|
|
600
|
+
row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }];
|
|
601
|
+
row.cornerRadius = 8;
|
|
602
|
+
row.paddingLeft = 24;
|
|
603
|
+
row.paddingRight = 24;
|
|
604
|
+
section.appendChild(row);
|
|
605
|
+
|
|
606
|
+
for (const tok of shadowTokens) {
|
|
607
|
+
await createShadowCard(row, tok.name, tok.effects);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return section;
|
|
611
|
+
}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## 7. Border Radius Demo
|
|
617
|
+
|
|
618
|
+
Border radius documentation shows rectangles at each corner radius value, labeled with the token name and pixel value.
|
|
619
|
+
|
|
620
|
+
### Single radius card
|
|
621
|
+
|
|
622
|
+
```javascript
|
|
623
|
+
/**
|
|
624
|
+
* Creates a single border radius card: a square with corner radius applied,
|
|
625
|
+
* labeled with the token name and pixel value.
|
|
626
|
+
*
|
|
627
|
+
* @param {FrameNode} parent - The horizontal row to append to.
|
|
628
|
+
* @param {string} name - Token name (e.g. "radius/md").
|
|
629
|
+
* @param {number} value - Corner radius in pixels (0 for none, 9999 for full).
|
|
630
|
+
* @param {Variable} [variable] - Optional Figma Variable to bind corner radius.
|
|
631
|
+
*/
|
|
632
|
+
async function createRadiusCard(parent, name, value, variable) {
|
|
633
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
634
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Medium' });
|
|
635
|
+
|
|
636
|
+
const wrapper = figma.createFrame();
|
|
637
|
+
wrapper.name = `Radius/${name}`;
|
|
638
|
+
wrapper.layoutMode = 'VERTICAL';
|
|
639
|
+
wrapper.primaryAxisAlignItems = 'CENTER';
|
|
640
|
+
wrapper.counterAxisAlignItems = 'CENTER';
|
|
641
|
+
wrapper.itemSpacing = 8;
|
|
642
|
+
wrapper.fills = [];
|
|
643
|
+
wrapper.layoutSizingHorizontal = 'FIXED';
|
|
644
|
+
wrapper.layoutSizingVertical = 'HUG';
|
|
645
|
+
wrapper.resize(96, 1);
|
|
646
|
+
parent.appendChild(wrapper);
|
|
647
|
+
|
|
648
|
+
const rect = figma.createRectangle();
|
|
649
|
+
rect.resize(72, 72);
|
|
650
|
+
rect.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98, a: 0.15 } }];
|
|
651
|
+
rect.strokes = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }];
|
|
652
|
+
rect.strokeWeight = 1.5;
|
|
653
|
+
|
|
654
|
+
// Cap display value — 9999 is how Figma represents "full/pill"
|
|
655
|
+
const displayRadius = Math.min(value, 36);
|
|
656
|
+
rect.cornerRadius = displayRadius;
|
|
657
|
+
|
|
658
|
+
// Bind to variable if provided
|
|
659
|
+
if (variable) {
|
|
660
|
+
rect.setBoundVariable('cornerRadius', variable);
|
|
661
|
+
}
|
|
662
|
+
wrapper.appendChild(rect);
|
|
663
|
+
|
|
664
|
+
const nameLabel = figma.createText();
|
|
665
|
+
nameLabel.fontName = { family: 'Inter', style: 'Medium' };
|
|
666
|
+
nameLabel.characters = name.split('/').pop();
|
|
667
|
+
nameLabel.fontSize = 11;
|
|
668
|
+
nameLabel.textAlignHorizontal = 'CENTER';
|
|
669
|
+
nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }];
|
|
670
|
+
wrapper.appendChild(nameLabel);
|
|
671
|
+
|
|
672
|
+
const valueLabel = figma.createText();
|
|
673
|
+
valueLabel.fontName = { family: 'Inter', style: 'Regular' };
|
|
674
|
+
valueLabel.characters = value >= 9999 ? 'full' : `${value}px`;
|
|
675
|
+
valueLabel.fontSize = 10;
|
|
676
|
+
valueLabel.textAlignHorizontal = 'CENTER';
|
|
677
|
+
valueLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }];
|
|
678
|
+
wrapper.appendChild(valueLabel);
|
|
679
|
+
|
|
680
|
+
return wrapper;
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### Radius section builder
|
|
685
|
+
|
|
686
|
+
```javascript
|
|
687
|
+
/**
|
|
688
|
+
* Creates the full border radius documentation section.
|
|
689
|
+
*
|
|
690
|
+
* @param {FrameNode} root - Root vertical stack.
|
|
691
|
+
* @param {Array<{name, value, variable}>} radiusTokens - Radius token definitions.
|
|
692
|
+
*/
|
|
693
|
+
async function createRadiusSection(root, radiusTokens) {
|
|
694
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
695
|
+
|
|
696
|
+
const section = figma.createFrame();
|
|
697
|
+
section.name = 'Section/Radius';
|
|
698
|
+
section.layoutMode = 'VERTICAL';
|
|
699
|
+
section.itemSpacing = 24;
|
|
700
|
+
section.layoutSizingHorizontal = 'FILL';
|
|
701
|
+
section.layoutSizingVertical = 'HUG';
|
|
702
|
+
section.fills = [];
|
|
703
|
+
root.appendChild(section);
|
|
704
|
+
|
|
705
|
+
const heading = figma.createText();
|
|
706
|
+
heading.fontName = { family: 'Inter', style: 'Bold' };
|
|
707
|
+
heading.characters = 'Border Radius';
|
|
708
|
+
heading.fontSize = 32;
|
|
709
|
+
heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
710
|
+
section.appendChild(heading);
|
|
711
|
+
|
|
712
|
+
const row = figma.createFrame();
|
|
713
|
+
row.name = 'Radius/Row';
|
|
714
|
+
row.layoutMode = 'HORIZONTAL';
|
|
715
|
+
row.itemSpacing = 24;
|
|
716
|
+
row.paddingTop = 24;
|
|
717
|
+
row.paddingBottom = 24;
|
|
718
|
+
row.paddingLeft = 24;
|
|
719
|
+
row.paddingRight = 24;
|
|
720
|
+
row.layoutSizingHorizontal = 'FILL';
|
|
721
|
+
row.layoutSizingVertical = 'HUG';
|
|
722
|
+
row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }];
|
|
723
|
+
row.cornerRadius = 8;
|
|
724
|
+
section.appendChild(row);
|
|
725
|
+
|
|
726
|
+
for (const tok of radiusTokens) {
|
|
727
|
+
await createRadiusCard(row, tok.name, tok.value, tok.variable);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
return section;
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## 8. Documentation Alongside Components
|
|
737
|
+
|
|
738
|
+
Each component page should include a documentation frame directly on the canvas, placed to the left of the component set. This keeps docs and the component in sync without requiring a separate file.
|
|
739
|
+
|
|
740
|
+
### Component page documentation frame
|
|
741
|
+
|
|
742
|
+
```javascript
|
|
743
|
+
/**
|
|
744
|
+
* Creates the documentation frame for a component page: title, description,
|
|
745
|
+
* and usage notes, positioned at x=0 with the component set to its right.
|
|
746
|
+
*
|
|
747
|
+
* @param {PageNode} page - The component page (must already be current).
|
|
748
|
+
* @param {string} componentName - The component name.
|
|
749
|
+
* @param {string} description - What the component does and when to use it.
|
|
750
|
+
* @param {string[]} usageNotes - Bullet points for usage guidance.
|
|
751
|
+
* @returns {FrameNode} The documentation frame.
|
|
752
|
+
*/
|
|
753
|
+
async function createComponentDocFrame(page, componentName, description, usageNotes) {
|
|
754
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' });
|
|
755
|
+
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
|
|
756
|
+
|
|
757
|
+
const doc = figma.createFrame();
|
|
758
|
+
doc.name = '_Doc';
|
|
759
|
+
doc.layoutMode = 'VERTICAL';
|
|
760
|
+
doc.itemSpacing = 16;
|
|
761
|
+
doc.paddingTop = 40;
|
|
762
|
+
doc.paddingBottom = 40;
|
|
763
|
+
doc.paddingLeft = 40;
|
|
764
|
+
doc.paddingRight = 40;
|
|
765
|
+
doc.layoutSizingHorizontal = 'FIXED';
|
|
766
|
+
doc.layoutSizingVertical = 'HUG';
|
|
767
|
+
doc.resize(360, 1);
|
|
768
|
+
doc.fills = [];
|
|
769
|
+
doc.x = 0;
|
|
770
|
+
doc.y = 0;
|
|
771
|
+
page.appendChild(doc);
|
|
772
|
+
|
|
773
|
+
// Component name — large heading
|
|
774
|
+
const title = figma.createText();
|
|
775
|
+
title.fontName = { family: 'Inter', style: 'Bold' };
|
|
776
|
+
title.characters = componentName;
|
|
777
|
+
title.fontSize = 28;
|
|
778
|
+
title.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
779
|
+
title.layoutSizingHorizontal = 'FILL';
|
|
780
|
+
doc.appendChild(title);
|
|
781
|
+
|
|
782
|
+
// Description
|
|
783
|
+
const descText = figma.createText();
|
|
784
|
+
descText.fontName = { family: 'Inter', style: 'Regular' };
|
|
785
|
+
descText.characters = description;
|
|
786
|
+
descText.fontSize = 13;
|
|
787
|
+
descText.lineHeight = { value: 20, unit: 'PIXELS' };
|
|
788
|
+
descText.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }];
|
|
789
|
+
descText.layoutSizingHorizontal = 'FILL';
|
|
790
|
+
doc.appendChild(descText);
|
|
791
|
+
|
|
792
|
+
// Divider
|
|
793
|
+
const divider = figma.createRectangle();
|
|
794
|
+
divider.resize(280, 1);
|
|
795
|
+
divider.fills = [{ type: 'SOLID', color: { r: 0.88, g: 0.88, b: 0.88 } }];
|
|
796
|
+
divider.layoutSizingHorizontal = 'FILL';
|
|
797
|
+
doc.appendChild(divider);
|
|
798
|
+
|
|
799
|
+
// Usage notes
|
|
800
|
+
if (usageNotes.length > 0) {
|
|
801
|
+
const usageHeading = figma.createText();
|
|
802
|
+
usageHeading.fontName = { family: 'Inter', style: 'Bold' };
|
|
803
|
+
usageHeading.characters = 'Usage';
|
|
804
|
+
usageHeading.fontSize = 13;
|
|
805
|
+
usageHeading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }];
|
|
806
|
+
doc.appendChild(usageHeading);
|
|
807
|
+
|
|
808
|
+
for (const note of usageNotes) {
|
|
809
|
+
const noteText = figma.createText();
|
|
810
|
+
noteText.fontName = { family: 'Inter', style: 'Regular' };
|
|
811
|
+
noteText.characters = `• ${note}`;
|
|
812
|
+
noteText.fontSize = 12;
|
|
813
|
+
noteText.lineHeight = { value: 18, unit: 'PIXELS' };
|
|
814
|
+
noteText.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }];
|
|
815
|
+
noteText.layoutSizingHorizontal = 'FILL';
|
|
816
|
+
doc.appendChild(noteText);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return doc;
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
## 9. Critical Rules
|
|
827
|
+
|
|
828
|
+
1. **Bind swatches to variables** — use `setBoundVariableForPaint` for color fills, `setBoundVariable('width', ...)` for spacing bars, and `setBoundVariable('cornerRadius', ...)` for radius cards. Never hardcode values that have corresponding variables.
|
|
829
|
+
2. **Foundations page comes before component pages** — always insert it between the file structure separators and the first component page.
|
|
830
|
+
3. **Show both primitive and semantic layers** — if the system has a Primitives collection and a semantic Color collection, document both on the Foundations page with clear section labels.
|
|
831
|
+
4. **Page frame width = 1440px** — this is the convention across Simple DS, Polaris, and Material 3. Use it unless you detect a different existing convention via `get_metadata`.
|
|
832
|
+
5. **Section spacing = 64–80px** — the gap between color / typography / spacing / shadow / radius sections should be at minimum 64px so the page is scannable.
|
|
833
|
+
6. **Match existing page style** — if the target file uses emoji page name prefixes or a decorative separator style, carry that through to the Foundations page name.
|
|
834
|
+
7. **Include code syntax in labels** — where variables have code syntax set, display the CSS variable name in the swatch/bar label so developers can copy it directly.
|