> Part of the [figma-generate-library skill](../SKILL.md). # Documentation Creation Reference 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 — meant to be embedded in a larger script that uses `return` to send results back). --- ## 1. Cover Page 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. ### What to include - File/system name as a large heading (48–72px) - Version string or date - Brief tagline (1 sentence) - Optional: color block background using the primary brand color variable ### Cover page dimensions The cover frame should be **1440 × 900px** — this matches the default Figma canvas and looks correct in the page thumbnail. ### use_figma for cover page ```javascript async function createCoverPage(systemName, tagline, version, primaryColorVar) { // primaryColorVar: a Figma Variable object for the brand primary fill const page = figma.createPage(); page.name = 'Cover'; await figma.setCurrentPageAsync(page); await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); await figma.loadFontAsync({ family: 'Inter', style: 'Medium' }); const frame = figma.createFrame(); frame.name = 'Cover'; frame.resize(1440, 900); frame.x = 0; frame.y = 0; frame.layoutMode = 'VERTICAL'; frame.primaryAxisAlignItems = 'CENTER'; frame.counterAxisAlignItems = 'CENTER'; frame.itemSpacing = 16; frame.paddingTop = 0; frame.paddingBottom = 0; frame.paddingLeft = 0; frame.paddingRight = 0; // Background: bind to primary variable if provided, else solid dark if (primaryColorVar) { const bgPaint = figma.variables.setBoundVariableForPaint( { type: 'SOLID', color: { r: 0.05, g: 0.05, b: 0.05 } }, 'color', primaryColorVar ); frame.fills = [bgPaint]; } else { frame.fills = [{ type: 'SOLID', color: { r: 0.06, g: 0.06, b: 0.07 } }]; } page.appendChild(frame); // System name heading const title = figma.createText(); title.fontName = { family: 'Inter', style: 'Bold' }; title.characters = systemName; title.fontSize = 64; title.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }]; title.textAlignHorizontal = 'CENTER'; frame.appendChild(title); // Tagline const tag = figma.createText(); tag.fontName = { family: 'Inter', style: 'Regular' }; tag.characters = tagline; tag.fontSize = 20; tag.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.7 } }]; tag.textAlignHorizontal = 'CENTER'; frame.appendChild(tag); // Version const ver = figma.createText(); ver.fontName = { family: 'Inter', style: 'Medium' }; ver.characters = version; ver.fontSize = 13; ver.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.45 } }]; ver.textAlignHorizontal = 'CENTER'; frame.appendChild(ver); return { page, frameId: frame.id }; } ``` --- ## 2. Foundations Page 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. ### Page layout dimensions 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. ### Full Foundations page skeleton ```javascript async function createFoundationsPage() { const page = figma.createPage(); page.name = 'Foundations'; await figma.setCurrentPageAsync(page); await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); await figma.loadFontAsync({ family: 'Inter', style: 'Medium' }); await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); // Root scroll frame const root = figma.createFrame(); root.name = 'Foundations'; root.layoutMode = 'VERTICAL'; root.primaryAxisAlignItems = 'MIN'; root.counterAxisAlignItems = 'MIN'; root.itemSpacing = 80; root.paddingTop = 80; root.paddingBottom = 120; root.paddingLeft = 80; root.paddingRight = 80; root.layoutSizingHorizontal = 'FIXED'; root.layoutSizingVertical = 'HUG'; root.resize(1440, 1); root.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }]; page.appendChild(root); return { page, root }; } ``` --- ## 3. Color Swatches (bound to variables) 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. ### Single color swatch ```javascript /** * Creates a single color swatch card (rectangle + variable name label). * The swatch rectangle fill is bound to the provided variable. * * @param {FrameNode} parent - The auto-layout row to append to. * @param {string} varName - Display name (e.g. "color/bg/primary"). * @param {Variable} variable - The Figma Variable object to bind to. * @returns {FrameNode} The swatch frame. */ async function createColorSwatch(parent, varName, variable) { await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); const swatchFrame = figma.createFrame(); swatchFrame.name = `Swatch/${varName}`; swatchFrame.layoutMode = 'VERTICAL'; swatchFrame.primaryAxisAlignItems = 'MIN'; swatchFrame.counterAxisAlignItems = 'MIN'; swatchFrame.itemSpacing = 6; swatchFrame.layoutSizingHorizontal = 'FIXED'; swatchFrame.layoutSizingVertical = 'HUG'; swatchFrame.resize(88, 1); swatchFrame.fills = []; // Color rectangle — bound to variable const rect = figma.createRectangle(); rect.resize(88, 88); rect.cornerRadius = 8; const paint = figma.variables.setBoundVariableForPaint( { type: 'SOLID', color: { r: 0.5, g: 0.5, b: 0.5 } }, 'color', variable ); rect.fills = [paint]; swatchFrame.appendChild(rect); // Name label const label = figma.createText(); label.fontName = { family: 'Inter', style: 'Regular' }; label.characters = varName.split('/').pop(); // show leaf name only label.fontSize = 10; label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }]; label.layoutSizingHorizontal = 'FILL'; swatchFrame.appendChild(label); // Full path tooltip label (smaller, lighter) const pathLabel = figma.createText(); pathLabel.fontName = { family: 'Inter', style: 'Regular' }; pathLabel.characters = varName; pathLabel.fontSize = 9; pathLabel.fills = [{ type: 'SOLID', color: { r: 0.6, g: 0.6, b: 0.6 } }]; pathLabel.layoutSizingHorizontal = 'FILL'; swatchFrame.appendChild(pathLabel); parent.appendChild(swatchFrame); return swatchFrame; } ``` ### Color section builder (primitives row + semantic grid) ```javascript /** * Creates a complete color documentation section with a section heading, * a row of primitive swatches, and a grid of semantic swatches. * * @param {FrameNode} root - The root vertical stack frame. * @param {Variable[]} primitiveVars - Variables from the Primitives collection. * @param {Variable[]} semanticVars - Variables from the semantic Color collection. */ async function createColorSection(root, primitiveVars, semanticVars) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); // Section container const section = figma.createFrame(); section.name = 'Section/Colors'; section.layoutMode = 'VERTICAL'; section.itemSpacing = 24; section.layoutSizingHorizontal = 'FILL'; section.layoutSizingVertical = 'HUG'; section.fills = []; root.appendChild(section); // Section heading const heading = figma.createText(); heading.fontName = { family: 'Inter', style: 'Bold' }; heading.characters = 'Colors'; heading.fontSize = 32; heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; section.appendChild(heading); // Description const desc = figma.createText(); desc.fontName = { family: 'Inter', style: 'Regular' }; desc.characters = 'Primitive color palette and semantic color tokens. Semantic tokens reference primitives — always use semantic tokens in components.'; desc.fontSize = 14; desc.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }]; desc.layoutSizingHorizontal = 'FILL'; section.appendChild(desc); // Primitive swatches row const primLabel = figma.createText(); primLabel.fontName = { family: 'Inter', style: 'Bold' }; primLabel.characters = 'Primitives'; primLabel.fontSize = 13; primLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }]; section.appendChild(primLabel); const primRow = figma.createFrame(); primRow.name = 'Primitives/Row'; primRow.layoutMode = 'HORIZONTAL'; primRow.itemSpacing = 12; primRow.layoutSizingHorizontal = 'FILL'; primRow.layoutSizingVertical = 'HUG'; primRow.fills = []; primRow.layoutWrap = 'WRAP'; section.appendChild(primRow); for (const v of primitiveVars) { await createColorSwatch(primRow, v.name, v); } // Semantic swatches grid if (semanticVars.length > 0) { const semLabel = figma.createText(); semLabel.fontName = { family: 'Inter', style: 'Bold' }; semLabel.characters = 'Semantic'; semLabel.fontSize = 13; semLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }]; section.appendChild(semLabel); const semRow = figma.createFrame(); semRow.name = 'Semantic/Row'; semRow.layoutMode = 'HORIZONTAL'; semRow.itemSpacing = 12; semRow.layoutSizingHorizontal = 'FILL'; semRow.layoutSizingVertical = 'HUG'; semRow.fills = []; semRow.layoutWrap = 'WRAP'; section.appendChild(semRow); for (const v of semanticVars) { await createColorSwatch(semRow, v.name, v); } } return section; } ``` --- ## 4. Type Specimens Typography specimens show each text style rendered at its actual size with a sample string, the style name, and its specifications. ### Single type specimen row ```javascript /** * Creates a single type specimen row: style name (small label) + sample text + * specification line (family · style · size · line-height). * * @param {FrameNode} parent - The parent vertical stack. * @param {string} styleName - The text style name (e.g. "Display Large"). * @param {string} fontFamily - Font family (e.g. "Inter"). * @param {string} fontStyle - Font style (e.g. "Bold"). * @param {number} fontSize - Font size in pixels. * @param {number} lineHeight - Line height in pixels. * @returns {FrameNode} The specimen row frame. */ async function createTypeSpecimen(parent, styleName, fontFamily, fontStyle, fontSize, lineHeight) { await figma.loadFontAsync({ family: fontFamily, style: fontStyle }); await figma.loadFontAsync({ family: 'Inter', style: 'Medium' }); await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); const row = figma.createFrame(); row.name = `Type/${styleName}`; row.layoutMode = 'VERTICAL'; row.itemSpacing = 6; row.paddingTop = 16; row.paddingBottom = 16; row.layoutSizingHorizontal = 'FILL'; row.layoutSizingVertical = 'HUG'; row.fills = []; parent.appendChild(row); // Style name label (small, muted) const nameText = figma.createText(); nameText.fontName = { family: 'Inter', style: 'Medium' }; nameText.characters = styleName; nameText.fontSize = 11; nameText.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }]; nameText.layoutSizingHorizontal = 'FILL'; row.appendChild(nameText); // Sample text rendered in the actual style const specimen = figma.createText(); specimen.fontName = { family: fontFamily, style: fontStyle }; specimen.characters = 'The quick brown fox jumps over the lazy dog'; specimen.fontSize = fontSize; specimen.lineHeight = { value: lineHeight, unit: 'PIXELS' }; specimen.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; specimen.layoutSizingHorizontal = 'FILL'; row.appendChild(specimen); // Specification line const specs = figma.createText(); specs.fontName = { family: 'Inter', style: 'Regular' }; specs.characters = `${fontFamily} ${fontStyle} · ${fontSize}px · ${lineHeight}px line height`; specs.fontSize = 11; specs.fills = [{ type: 'SOLID', color: { r: 0.65, g: 0.65, b: 0.65 } }]; specs.layoutSizingHorizontal = 'FILL'; row.appendChild(specs); // Divider line const divider = figma.createRectangle(); divider.resize(1280, 1); divider.fills = [{ type: 'SOLID', color: { r: 0.9, g: 0.9, b: 0.9 } }]; divider.layoutSizingHorizontal = 'FILL'; row.appendChild(divider); return row; } ``` ### Typography section builder ```javascript /** * Creates a complete typography documentation section. * Pass an array of style definitions; the function renders one specimen per entry. * * @param {FrameNode} root - Root vertical stack. * @param {Array<{name, family, style, size, lineHeight}>} typeStyles - Style definitions. */ async function createTypographySection(root, typeStyles) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); const section = figma.createFrame(); section.name = 'Section/Typography'; section.layoutMode = 'VERTICAL'; section.itemSpacing = 0; section.layoutSizingHorizontal = 'FILL'; section.layoutSizingVertical = 'HUG'; section.fills = []; root.appendChild(section); const heading = figma.createText(); heading.fontName = { family: 'Inter', style: 'Bold' }; heading.characters = 'Typography'; heading.fontSize = 32; heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; section.appendChild(heading); for (const ts of typeStyles) { await createTypeSpecimen(section, ts.name, ts.family, ts.style, ts.size, ts.lineHeight); } return section; } ``` --- ## 5. Spacing Bars 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. ### Spacing bar row ```javascript /** * Creates a single spacing bar: a colored rectangle sized to the spacing value, * with a label showing name + pixel value + code syntax. * * @param {FrameNode} parent - Parent vertical stack. * @param {string} name - Token name (e.g. "spacing/sm"). * @param {number} value - Spacing value in pixels. * @param {Variable} variable - Figma Variable to bind the width to. * @param {string} codeSyntax - CSS variable string (e.g. "var(--spacing-sm)"). */ async function createSpacingBar(parent, name, value, variable, codeSyntax) { await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); const row = figma.createFrame(); row.name = `Spacing/${name}`; row.layoutMode = 'HORIZONTAL'; row.counterAxisAlignItems = 'CENTER'; row.itemSpacing = 16; row.layoutSizingHorizontal = 'FILL'; row.layoutSizingVertical = 'HUG'; row.fills = []; parent.appendChild(row); // The bar rectangle — width bound to spacing variable const bar = figma.createRectangle(); bar.resize(value, 16); bar.cornerRadius = 3; bar.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }]; // Bind width to the spacing variable so it reflects the actual token value if (variable) { bar.setBoundVariable('width', variable); } row.appendChild(bar); // Label: "spacing/sm 8px var(--spacing-sm)" const label = figma.createText(); label.fontName = { family: 'Inter', style: 'Regular' }; label.characters = `${name} ${value}px ${codeSyntax}`; label.fontSize = 12; label.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }]; row.appendChild(label); return row; } ``` ### Spacing section builder ```javascript /** * Creates the full spacing documentation section. * * @param {FrameNode} root - Root vertical stack. * @param {Array<{name, value, variable, codeSyntax}>} spacingTokens - Token definitions. */ async function createSpacingSection(root, spacingTokens) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); const section = figma.createFrame(); section.name = 'Section/Spacing'; section.layoutMode = 'VERTICAL'; section.itemSpacing = 12; section.layoutSizingHorizontal = 'FILL'; section.layoutSizingVertical = 'HUG'; section.fills = []; root.appendChild(section); const heading = figma.createText(); heading.fontName = { family: 'Inter', style: 'Bold' }; heading.characters = 'Spacing'; heading.fontSize = 32; heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; section.appendChild(heading); for (const tok of spacingTokens) { await createSpacingBar(section, tok.name, tok.value, tok.variable, tok.codeSyntax); } return section; } ``` --- ## 6. Shadow Cards (Elevation) Elevation documentation shows cards with progressively stronger drop shadows, labeled with name and effect parameters. ### Single shadow card ```javascript /** * Creates a shadow card: a white rectangle with a drop shadow effect, * labeled with the elevation name and shadow parameters. * * @param {FrameNode} parent - The horizontal row to append to. * @param {string} name - Elevation name (e.g. "Shadow/Medium"). * @param {DropShadowEffect[]} effects - Array of Figma effect objects. */ async function createShadowCard(parent, name, effects) { await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); await figma.loadFontAsync({ family: 'Inter', style: 'Medium' }); const card = figma.createFrame(); card.name = `ShadowCard/${name}`; card.layoutMode = 'VERTICAL'; card.primaryAxisAlignItems = 'CENTER'; card.counterAxisAlignItems = 'CENTER'; card.itemSpacing = 8; card.paddingTop = 16; card.paddingBottom = 16; card.resize(120, 120); card.cornerRadius = 8; card.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }]; card.effects = effects; parent.appendChild(card); // Elevation name const nameLabel = figma.createText(); nameLabel.fontName = { family: 'Inter', style: 'Medium' }; nameLabel.characters = name.split('/').pop(); nameLabel.fontSize = 12; nameLabel.textAlignHorizontal = 'CENTER'; nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }]; card.appendChild(nameLabel); // Effect parameters as small text if (effects.length > 0) { const e = effects[0]; if (e.type === 'DROP_SHADOW') { const params = figma.createText(); params.fontName = { family: 'Inter', style: 'Regular' }; params.characters = `x:${e.offset.x} y:${e.offset.y}\nblur:${e.radius}`; params.fontSize = 10; params.textAlignHorizontal = 'CENTER'; params.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }]; card.appendChild(params); } } return card; } ``` ### Shadow section builder ```javascript /** * Creates the full elevation/shadow documentation section. * * @param {FrameNode} root - Root vertical stack. * @param {Array<{name, effects}>} shadowTokens - Shadow definitions. */ async function createShadowSection(root, shadowTokens) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); const section = figma.createFrame(); section.name = 'Section/Elevation'; section.layoutMode = 'VERTICAL'; section.itemSpacing = 24; section.layoutSizingHorizontal = 'FILL'; section.layoutSizingVertical = 'HUG'; section.fills = []; root.appendChild(section); const heading = figma.createText(); heading.fontName = { family: 'Inter', style: 'Bold' }; heading.characters = 'Elevation'; heading.fontSize = 32; heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; section.appendChild(heading); // Cards row — extra top padding so shadows are visible const row = figma.createFrame(); row.name = 'Elevation/Row'; row.layoutMode = 'HORIZONTAL'; row.itemSpacing = 32; row.paddingTop = 24; row.paddingBottom = 40; row.layoutSizingHorizontal = 'FILL'; row.layoutSizingVertical = 'HUG'; row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }]; row.cornerRadius = 8; row.paddingLeft = 24; row.paddingRight = 24; section.appendChild(row); for (const tok of shadowTokens) { await createShadowCard(row, tok.name, tok.effects); } return section; } ``` --- ## 7. Border Radius Demo Border radius documentation shows rectangles at each corner radius value, labeled with the token name and pixel value. ### Single radius card ```javascript /** * Creates a single border radius card: a square with corner radius applied, * labeled with the token name and pixel value. * * @param {FrameNode} parent - The horizontal row to append to. * @param {string} name - Token name (e.g. "radius/md"). * @param {number} value - Corner radius in pixels (0 for none, 9999 for full). * @param {Variable} [variable] - Optional Figma Variable to bind corner radius. */ async function createRadiusCard(parent, name, value, variable) { await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); await figma.loadFontAsync({ family: 'Inter', style: 'Medium' }); const wrapper = figma.createFrame(); wrapper.name = `Radius/${name}`; wrapper.layoutMode = 'VERTICAL'; wrapper.primaryAxisAlignItems = 'CENTER'; wrapper.counterAxisAlignItems = 'CENTER'; wrapper.itemSpacing = 8; wrapper.fills = []; wrapper.layoutSizingHorizontal = 'FIXED'; wrapper.layoutSizingVertical = 'HUG'; wrapper.resize(96, 1); parent.appendChild(wrapper); const rect = figma.createRectangle(); rect.resize(72, 72); rect.fills = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98, a: 0.15 } }]; rect.strokes = [{ type: 'SOLID', color: { r: 0.22, g: 0.47, b: 0.98 } }]; rect.strokeWeight = 1.5; // Cap display value — 9999 is how Figma represents "full/pill" const displayRadius = Math.min(value, 36); rect.cornerRadius = displayRadius; // Bind to variable if provided if (variable) { rect.setBoundVariable('cornerRadius', variable); } wrapper.appendChild(rect); const nameLabel = figma.createText(); nameLabel.fontName = { family: 'Inter', style: 'Medium' }; nameLabel.characters = name.split('/').pop(); nameLabel.fontSize = 11; nameLabel.textAlignHorizontal = 'CENTER'; nameLabel.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.2 } }]; wrapper.appendChild(nameLabel); const valueLabel = figma.createText(); valueLabel.fontName = { family: 'Inter', style: 'Regular' }; valueLabel.characters = value >= 9999 ? 'full' : `${value}px`; valueLabel.fontSize = 10; valueLabel.textAlignHorizontal = 'CENTER'; valueLabel.fills = [{ type: 'SOLID', color: { r: 0.55, g: 0.55, b: 0.55 } }]; wrapper.appendChild(valueLabel); return wrapper; } ``` ### Radius section builder ```javascript /** * Creates the full border radius documentation section. * * @param {FrameNode} root - Root vertical stack. * @param {Array<{name, value, variable}>} radiusTokens - Radius token definitions. */ async function createRadiusSection(root, radiusTokens) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); const section = figma.createFrame(); section.name = 'Section/Radius'; section.layoutMode = 'VERTICAL'; section.itemSpacing = 24; section.layoutSizingHorizontal = 'FILL'; section.layoutSizingVertical = 'HUG'; section.fills = []; root.appendChild(section); const heading = figma.createText(); heading.fontName = { family: 'Inter', style: 'Bold' }; heading.characters = 'Border Radius'; heading.fontSize = 32; heading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; section.appendChild(heading); const row = figma.createFrame(); row.name = 'Radius/Row'; row.layoutMode = 'HORIZONTAL'; row.itemSpacing = 24; row.paddingTop = 24; row.paddingBottom = 24; row.paddingLeft = 24; row.paddingRight = 24; row.layoutSizingHorizontal = 'FILL'; row.layoutSizingVertical = 'HUG'; row.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.97 } }]; row.cornerRadius = 8; section.appendChild(row); for (const tok of radiusTokens) { await createRadiusCard(row, tok.name, tok.value, tok.variable); } return section; } ``` --- ## 8. Documentation Alongside Components 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. ### Component page documentation frame ```javascript /** * Creates the documentation frame for a component page: title, description, * and usage notes, positioned at x=0 with the component set to its right. * * @param {PageNode} page - The component page (must already be current). * @param {string} componentName - The component name. * @param {string} description - What the component does and when to use it. * @param {string[]} usageNotes - Bullet points for usage guidance. * @returns {FrameNode} The documentation frame. */ async function createComponentDocFrame(page, componentName, description, usageNotes) { await figma.loadFontAsync({ family: 'Inter', style: 'Bold' }); await figma.loadFontAsync({ family: 'Inter', style: 'Regular' }); const doc = figma.createFrame(); doc.name = '_Doc'; doc.layoutMode = 'VERTICAL'; doc.itemSpacing = 16; doc.paddingTop = 40; doc.paddingBottom = 40; doc.paddingLeft = 40; doc.paddingRight = 40; doc.layoutSizingHorizontal = 'FIXED'; doc.layoutSizingVertical = 'HUG'; doc.resize(360, 1); doc.fills = []; doc.x = 0; doc.y = 0; page.appendChild(doc); // Component name — large heading const title = figma.createText(); title.fontName = { family: 'Inter', style: 'Bold' }; title.characters = componentName; title.fontSize = 28; title.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; title.layoutSizingHorizontal = 'FILL'; doc.appendChild(title); // Description const descText = figma.createText(); descText.fontName = { family: 'Inter', style: 'Regular' }; descText.characters = description; descText.fontSize = 13; descText.lineHeight = { value: 20, unit: 'PIXELS' }; descText.fills = [{ type: 'SOLID', color: { r: 0.35, g: 0.35, b: 0.35 } }]; descText.layoutSizingHorizontal = 'FILL'; doc.appendChild(descText); // Divider const divider = figma.createRectangle(); divider.resize(280, 1); divider.fills = [{ type: 'SOLID', color: { r: 0.88, g: 0.88, b: 0.88 } }]; divider.layoutSizingHorizontal = 'FILL'; doc.appendChild(divider); // Usage notes if (usageNotes.length > 0) { const usageHeading = figma.createText(); usageHeading.fontName = { family: 'Inter', style: 'Bold' }; usageHeading.characters = 'Usage'; usageHeading.fontSize = 13; usageHeading.fills = [{ type: 'SOLID', color: { r: 0.07, g: 0.07, b: 0.07 } }]; doc.appendChild(usageHeading); for (const note of usageNotes) { const noteText = figma.createText(); noteText.fontName = { family: 'Inter', style: 'Regular' }; noteText.characters = `• ${note}`; noteText.fontSize = 12; noteText.lineHeight = { value: 18, unit: 'PIXELS' }; noteText.fills = [{ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.4 } }]; noteText.layoutSizingHorizontal = 'FILL'; doc.appendChild(noteText); } } return doc; } ``` --- ## 9. Critical Rules 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. 2. **Foundations page comes before component pages** — always insert it between the file structure separators and the first component page. 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. 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`. 5. **Section spacing = 64–80px** — the gap between color / typography / spacing / shadow / radius sections should be at minimum 64px so the page is scannable. 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. 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.