use_figma — Design System Skill
Context for using the use_figma MCP tool with 's design system. The figma-use skill provides the foundational Plugin API rules (return-as-output, 0–1 colors, font loading, page switching, incremental workflow, atomic errors). Load both together — this skill is the what ( libraries, tokens, components, conventions); figma-use is the how (the API surface).
MANDATORY: load figma-use before any use_figma call. If the task is a full screen/view, also load figma-generate-design; if it is new components or a design-system build, also load figma-generate-library. Those workflow skills tell you how to assemble screens / components; this skill tells you which assets to assemble them from.
Always include figma-use-design-system in the comma-separated skillNames parameter when calling use_figma as part of this skill. If this skill was loaded via an MCP resource, you MUST prefix the name with resource: (e.g. resource:figma-use-design-system). This is a logging parameter — it does not affect execution.
1. The Three Libraries
ships as three published Figma libraries. These are the authoritative source of truth — never recreate their tokens, styles, or components by hand.
| Library | What it provides | File key |
|---|---|---|
| Variables | Design tokens, primitives, semantic variables, theming (collections + modes) | <variables-file-key> |
| UI Kit | Foundations, components, patterns, text styles, effect/elevation styles, layout guides | <ui-kit-file-key> |
| Icons | Icon set + symbols (stroke default; fill only for critical/warning/success) | <icons-file-key> |
These are file keys, not per-asset publish keys. The keys you pass to
importComponentSetByKeyAsync/importVariableByKeyAsync/importStyleByKeyAsyncare resolved at runtime from these files — see Appendix A — Libraries & Discovery for the resolution recipe.
2. Core Rules
- Tokens over hardcoded values — always. Every color, spacing, sizing, radius, and shadow in has a variable or style. Bind to it. Hardcoded hex / px is a defect, not a shortcut. See Appendix B — Tokens.
- Prefer semantic tokens over global primitives. Use
--ds-background-color-*,--ds-content-color-*,--ds-border-color-*,--ds-base-color-*— not raw--ds-color-grey-900. The global palette is used sparingly, only when no correct semantic mapping exists. - Instance components from the UI Kit — never rebuild them. Buttons, tables, modals, inputs, etc. already exist as components. Import and instance them; override via component properties. See Appendix D — Components.
- Apply elevation as effect styles, not raw shadows. Use the
--ds-shadow-{none,low,mid,high}effect styles from the UI Kit. They carry the correct light and dark box-shadow values. See Appendix C — Foundations → Elevations. - Type through text styles. Apply text styles (
ds-heading-01..05,ds-body,ds-body-small,ds-caption,ds-code) vianode.textStyleId— don't set font/size/line-height/letter-spacing by hand. Fonts: Inter (UI) and IBM Plex Mono (code). - Theme via collection modes, not value swaps. Light, dark, and high-contrast are modes on the Variables collections. Switch modes with
setExplicitVariableModeForCollection; never duplicate a screen to "make a dark version." See Appendix B — Tokens → Theming and Appendix C — Foundations. - Accessibility is a gate, not a nicety. Default themes target WCAG 2.2 AA; high-contrast themes target all levels (2.0+2.1+2.2 A/AA/AAA). Validate contrast and focus visibility. See Appendix E — Accessibility.
- Discover before creating. Inspect the target file and existing screens first; match their naming and structure. Only create local assets when genuinely lacks them.
3. Required Workflow
Follow in order. Load figma-use first.
Step 1 — Confirm the libraries are available
Run get_libraries({ fileKey }) against the target file. Confirm Variables, UI Kit, and Icons are linked (or available to add). If a needed library is missing, add it or tell the user. See Appendix A — Libraries & Discovery.
Step 2 — Resolve the asset keys you need
You need three categories of keys, resolved at runtime (don't guess):
- Variables (semantic colors, spacing, sizing, radius) — from the Variables library.
- Styles (text styles, elevation/effect styles) — from the UI Kit.
- Components / component sets (Button, Table, Modal, …) — from the UI Kit.
Resolve via search_design_system (scoped with includeLibraryKeys) or by running a read-only use_figma against the library file and reading .key off the node. See Appendix A — Libraries & Discovery for both patterns. Inspecting an existing screen in the target file is the most authoritative source.
Step 3 — Build incrementally with assets
Follow the figma-use incremental workflow (≤10 ops per call, validate after each). For each section:
- Import the components / variables / styles you resolved (batch with
Promise.all). - Instance components; override text/variant props via
setProperties. - Bind colors with
setBoundVariableForPaint, spacing/radius withsetBoundVariable, apply text styles viatextStyleId, elevation viaeffectStyleId. - Set the correct theme mode on the relevant collection(s).
- Return all created/mutated node IDs.
Step 4 — Validate
get_screenshot per section. Check: tokens actually bound (not hardcoded), correct text styles, correct elevation, correct theme mode, AA contrast, and that components are real instances (have mainComponent). See Appendix E — Accessibility.
4. Reference Appendices
The full reference docs are embedded as appendices at the end of this file (Figma skill upload accepts a single file, so everything is inlined here). Jump to the relevant one on demand:
| Appendix | When to read | Covers |
|---|---|---|
| Appendix A — Libraries & Discovery | Start of any task | The 3 libraries, get_libraries, search_design_system, runtime key-resolution recipes, import-by-key patterns |
| Appendix B — Tokens | Binding any color/spacing/size/radius; theming | Semantic token map (light + dark sources), naming convention, binding patterns, theme modes |
| Appendix C — Foundations | Color/type/spacing/sizing/elevation/icon/breakpoint values | Primitive scales, type scale + styles, spacing/sizing scales, elevations, icon rules, breakpoints |
| Appendix D — Components | Instancing or building components | Component inventory, discover/instance/override patterns, icon component props |
| Appendix E — Accessibility | Any deliverable | WCAG 2.2 AA gate, theme conformance, contrast/focus checks |
5. Pre-Flight Checklist
In addition to the figma-use pre-flight checklist, verify:
-
figma-useloaded;skillNamesincludesfigma-use-design-system. - All three libraries confirmed linked (Step 1).
- Asset keys resolved at runtime — not guessed (Step 2).
- Colors bound to semantic tokens (global palette only where no semantic mapping exists).
- Spacing/sizing/radius bound to
--ds-spacing-*/--ds-size-*/--ds-border-radius-*— no raw px. - Text uses text styles (Inter / IBM Plex Mono); no hand-set font metrics.
- Elevation applied via
--ds-shadow-*effect styles — no rawbox-shadow. - Components are real UI Kit instances with
mainComponent, overridden via properties. - Correct theme mode set via collection modes — not value duplication.
- Contrast meets WCAG 2.2 AA (default) / all levels (high-contrast).
- All created/mutated node IDs returned.
Appendices (Embedded Reference Docs)
These appendices are the inlined
references/*.mddocs. They live here because Figma's skill upload accepts only this singleSKILL.md. Links tofigma-use/figma-generate-*point to those companion skills (uploaded separately), not to anything in this file.
Appendix A — Libraries & Discovery
The three libraries are the source of truth. This appendix covers confirming they're linked and resolving the runtime asset keys you pass to the importXByKeyAsync APIs.
The libraries
| Library | Role | File key |
|---|---|---|
| Variables | Tokens, primitives, semantic variables, theming (collections + modes) | <variables-file-key> |
| UI Kit | Foundations, components, patterns, text styles, effect/elevation styles, layout guides | <ui-kit-file-key> |
| Icons | Icons & symbols (stroke default; fill for critical/warning/success only) | <icons-file-key> |
File keys ≠ publish keys. The values above identify the library files. The keys consumed by
importComponentSetByKeyAsync,importVariableByKeyAsync, andimportStyleByKeyAsyncare per-asset publish keys, resolved at runtime (below).
A.1 — Confirm the libraries are linked
get_libraries({ fileKey: TARGET_FILE_KEY })
// → { libraries_added_to_file: [...], libraries_available_to_add: [...], libraries_available_to_add_next_offset }
Confirm all three libraries appear in libraries_added_to_file. If a needed one is only in libraries_available_to_add, add it (or ask the user). Capture each entry's libraryKey to scope searches in A.2.
A.2 — Resolve asset keys (pick the most authoritative source available)
A.2.A. Inspect an existing screen in the target file (best)
If the target file already has screens, walk one to get an exact component map — authoritative because it reflects what's actually published and linked.
// Read-only — skip invisible instance interiors for speed.
figma.skipInvisibleInstanceChildren = true;
const frame = figma.currentPage.findOne(n => n.name === "EXISTING_SCREEN");
const sets = new Map();
frame.findAllWithCriteria({ types: ["INSTANCE"] }).forEach(inst => {
const mc = inst.mainComponent;
const cs = mc?.parent?.type === "COMPONENT_SET" ? mc.parent : null;
const key = cs ? cs.key : mc?.key;
const name = cs ? cs.name : mc?.name;
if (key && !sets.has(key)) sets.set(key, { name, key, isSet: !!cs, sampleVariant: mc.name });
});
return [...sets.values()];
A.2.B. search_design_system, scoped to the libraries
search_design_system({
query: "button",
fileKey: TARGET_FILE_KEY,
includeLibraryKeys: [UI_KIT_LIBRARY_KEY], // from get_libraries
includeComponents: true, includeVariables: true, includeStyles: true
})
Search broadly with synonyms (button, table, modal, input, badge, banner, checkbox, radio, link, dropdown, popover, textarea). For variables, query names: "background", "content", "border", "base", "spacing", "size", "radius", "shadow".
A.2.C. Resolve a key directly from a library file
When you know the node (e.g. from a library URL …/your-ui-kit?node-id=609-35535), run a read-only use_figma against the library file and read .key:
const node = await figma.getNodeByIdAsync("609:35535"); // hyphens → colons
const set = node?.parent?.type === "COMPONENT_SET" ? node.parent : node;
return { name: set.name, componentKey: set.key };
A.2.D. Variables and styles
// Local-to-target variables only (won't see remote library vars):
const colls = await figma.variables.getLocalVariableCollectionsAsync();
// For library (remote) variables, prefer search_design_system (A.2.B) or read bound vars off an existing screen.
Import resolved assets:
- Components:
await figma.importComponentSetByKeyAsync(key)/importComponentByKeyAsync(key) - Variables:
await figma.variables.importVariableByKeyAsync(key) - Styles:
await figma.importStyleByKeyAsync(key)→ apply vianode.textStyleId/node.effectStyleId
⚠️
getLocalVariableCollectionsAsync()returning empty does not mean has no variables — remote/published library variables are invisible to it. Usesearch_design_system(A.2.B) or inspect a screen (A.2.A).
A.3 — Cache what you resolve
Resolution costs round-trips. Within a task, resolve the keys you need once (batch the lookups), then reuse them across section-build calls. Return them from the discovery call so subsequent calls can pass them as string literals.
Appendix B — Tokens
Semantic tokens standardize design decisions (color, spacing, sizing, radius) in a reusable, theme-aware way. Prefer these over global primitives (Appendix C — Foundations).
Naming convention
--[namespace]-[context/category]-[role/object]-[modifier/attribute/state]
Namespace: --ds-. Examples:
--ds-background-color-primary— default background color--ds-content-color-primary— primary content & icon color--ds-content-color-disabled— disabled content--ds-button-background-primary-hover— component token, hover state
Semantic color tokens (Light → Dark source)
Background colors
| Token | Light | Dark |
|---|---|---|
--ds-background-color-primary |
white | grey-950 |
--ds-background-color-secondary |
grey-100 | grey-900 |
--ds-background-color-tertiary |
grey-200 | grey-800 |
--ds-background-color-brand |
blue-50 | blue-950 |
--ds-background-color-info |
blue-50 | blue-950 |
--ds-background-color-success |
green-50 | green-950 |
--ds-background-color-warning |
yellow-50 | yellow-950 |
--ds-background-color-error |
red-50 | red-950 |
Base colors (brand/status fills)
| Token | Light | Dark |
|---|---|---|
--ds-base-color-brand |
blue-500 | blue-500 |
--ds-base-color-info |
blue-500 | blue-500 |
--ds-base-color-success |
green-500 | green-500 |
--ds-base-color-warning |
yellow-500 | yellow-500 |
--ds-base-color-error |
red-500 | red-500 |
Border colors
| Token | Light | Dark |
|---|---|---|
--ds-border-color-strong |
grey-400 | grey-600 |
--ds-border-color-default |
grey-300 | grey-700 |
--ds-border-color-muted |
grey-200 | grey-800 |
Content colors (text & icons)
| Token | Light | Dark |
|---|---|---|
--ds-content-color-primary |
grey-900 | grey-100 |
--ds-content-color-secondary |
grey-700 | grey-300 |
--ds-content-color-tertiary |
grey-500 | grey-400 |
--ds-content-color-brand |
blue-600 | blue-500 |
--ds-content-color-constant |
white | white |
--ds-content-color-info |
blue-600 | blue-400 |
--ds-content-color-success |
green-600 | green-400 |
--ds-content-color-warning |
yellow-600 | yellow-400 |
--ds-content-color-error |
red-600 | red-400 |
--ds-content-color-link |
blue-600 | blue-400 |
--ds-content-color-link-hover |
blue-700 | blue-300 |
--ds-content-color-link-visited |
purple-600 | purple-400 |
--ds-content-color-inked |
black | white |
--ds-content-color-placeholder |
green-400 | green-600 |
--ds-content-color-disabled |
(see Variables library) |
Semantic spacing / sizing / radius
Spacing (--ds-spacing-* aliases → primitive)
zero→0 · xs→4 · s→8 · m→12 · l→16 · xl→24 · xxl→32 · xxxl→48 (px).
Sizing (--ds-size-* → primitive)
xs→spacing-16 (1rem) · s→spacing-24 (1.5rem) · default→spacing-32 (2rem) · l→spacing-40 (2.5rem).
Border radius (--ds-border-radius-*)
s→spacing-2 (.125rem) · default→spacing-4 (.25rem) · l→spacing-8 (.5rem) · max→50vh (pill).
Component tokens (example: Button)
| Group | Tokens |
|---|---|
| Background | --ds-button-background-{primary,secondary,danger}, each with -hover / -active; --ds-button-background-disabled |
| Size (height) | --ds-button-size-height-s → size-s (1.5rem) · -default → size-default (2rem) · -l → size-l (2.5rem) |
| Gap | --ds-button-gap-s → spacing-6 · -default → spacing-s (8) · -l → spacing-m (12) |
Other components expose analogous component-level tokens — discover them per component (see Appendix D — Components).
Theming
Light, dark, and high-contrast (light & dark) are modes on the Variables collections — not separate values you hand-pick.
- Bind a node to the semantic variable; the mode determines the resolved primitive automatically.
- Switch a subtree's theme by setting the mode on the relevant collection:
// Resolve the collection + target mode id, then apply to the container node.
const collection = /* imported/looked-up color collection */;
const darkMode = collection.modes.find(m => /dark/i.test(m.name));
containerNode.setExplicitVariableModeForCollection(collection, darkMode.modeId);
- Never duplicate a screen to make a dark version. One screen + a mode switch.
- Default themes target WCAG 2.2 AA; high-contrast themes target all levels — see Appendix E — Accessibility.
Binding patterns (quick reference)
// Color → semantic token
const paint = figma.variables.setBoundVariableForPaint(
{ type: 'SOLID', color: { r: 0, g: 0, b: 0 } }, 'color', bgPrimaryVar
);
node.fills = [paint];
// Spacing / radius → token
frame.setBoundVariable('paddingLeft', spacingLVar);
frame.setBoundVariable('topLeftRadius', radiusDefaultVar);
// Text style / elevation → style
textNode.textStyleId = headingStyle.id;
cardNode.effectStyleId = shadowMidStyle.id;
See variable-patterns.md and effect-style-patterns.md in the figma-use companion skill for full details.
Appendix C — Foundations
Reference values for the primitives. Bind to the variables/styles rather than typing these numbers — they're listed so you can pick the right token and sanity-check that a binding resolved as expected. Namespace for all tokens: --ds-.
Colors (global primitives — Default theme)
Use the global palette sparingly — only when no semantic token maps to the use case. Prefer the semantic tokens in Appendix B — Tokens.
Hues: grey, blue, green, red, yellow, purple. Each has steps 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950. Token: --ds-color-{hue}-{step}. Bind the variable; the Variables library holds the resolved hex/OKLCH per theme.
Typography
Font stacks: Sans (UI) = "Inter", system-ui, sans-serif · Mono (code) = "IBM Plex Mono", monospace.
Scale: Major second (1.125), root/base 1rem = 16px. Weights: 400 body & code, 600 headings.
Type scale (--ds-font-size-*)
| Token | px / rem | Role |
|---|---|---|
--ds-font-size-5 |
32 / 2rem | Level 1 heading |
--ds-font-size-4 |
28 / 1.75rem | Level 2 heading |
--ds-font-size-3 |
24 / 1.5rem | Level 3 heading |
--ds-font-size-2 |
20 / 1.25rem | Level 4 heading |
--ds-font-size-1 |
16 / 1rem | Level 5 heading |
--ds-font-size-base |
16 / 1rem | Body copy |
--ds-font-size-neg-1 |
14 / 0.875rem | Body small, code |
--ds-font-size-neg-2 |
12 / 0.75rem | Helper & caption |
Text styles (apply via node.textStyleId)
| Style | font-size | line-height | weight | letter-spacing |
|---|---|---|---|---|
ds-heading-01 |
size-5 | lh-5 | 600 | ls-3 |
ds-heading-02 |
size-4 | lh-4 | 600 | ls-2 |
ds-heading-03 |
size-3 | lh-3 | 600 | ls-1 |
ds-heading-04 |
size-2 | lh-2 | 600 | — |
ds-heading-05 |
size-1 | lh-1 | 600 | — |
ds-body |
base | lh-base | 400 | — |
ds-body-small |
neg-1 | lh-neg-1 | 400 | — |
ds-caption |
neg-2 | lh-neg-2 | 400 | — |
ds-code |
neg-1 | lh-neg-1 | 400 | (IBM Plex Mono) |
Spacing (--ds-spacing-*, 4-pt grid)
0=0 · 2 · 4 · 6 · 8 · 12 · 16 · 20 · 24 · 32 · 40 · 48 · 64 · 80 · 96 · 112 · 128 (px). Bind padding/gap/margin to these; see semantic aliases (--ds-spacing-xs…xxxl) in Appendix B — Tokens.
Sizing (--ds-sizing-*)
2 · 4 · 8 · 12 · 16 · 20 · 24 · 28 · 32 · 48 · 64 (px). Component heights/dimensions. Semantic aliases (--ds-size-xs…l) in Appendix B — Tokens.
Elevations
Apply as effect styles (node.effectStyleId). Each token carries distinct light and dark box-shadows, resolved by theme mode — never hand-author shadows.
| Token | Role |
|---|---|
--ds-shadow-none |
Canvas / background / global areas |
--ds-shadow-low |
Main content area |
--ds-shadow-mid |
Dropdowns, menus, tooltips |
--ds-shadow-high |
Sidesheet, modals, popover, toasts |
Iconography
- Grids: 24×24 (base), 20×20, 16×16.
viewBoxstays 24×24;sizesets width/height attrs. - Stroke: 1.5px default; 1px for 16px size only.
strokeWidthis a separate prop, not scaled fromsize. - Rounded end caps; angles in 15° increments; corner radius 2.
- Default variant = stroke. Fill variant only for critical / warning / success states.
- Props:
size: 16 | 20 | 24,strokeWidth: number. See Appendix D — Components → Icon component props.
Layout breakpoints
| Name | Value | Range |
|---|---|---|
| xxlarge | 1920px | 1920+ |
| xlarge | 1440px | 1440–1919 |
| large | 1088px | 1088–1439 |
| medium | 768px | 768–1087 |
| small | 480px | 480–767 |
| xsmall | 320px | 320–479 |
Responsive padding: --ds-spacing-16 for xsmall/small/medium/large; --ds-spacing-24 for xlarge/xxlarge. Layout guides are provided in the UI Kit library.
Appendix D — Components
Instance components from the UI Kit library — never rebuild them. Resolve their keys at runtime (Appendix A — Libraries & Discovery), import, instance, and override via component properties.
Component inventory (UI Kit)
Known components include:
- Badge
- Banner
- Button
- Checkbox
- Dropdown menu
- Link
- Modal
- Popover
- Radio
- Table
- Text input
- Textarea
This list reflects the spec snapshot; the published library is the source of truth. Discover the live set with
search_design_systemor by inspecting the UI Kit file.
Patterns
- Global: App header, Sidebar(s), App layout
- Forms
Patterns are composed from components + layout guides; assemble them from instances, don't flatten.
Instancing & overriding
// 1. Import the component set, pick the right variant.
const buttonSet = await figma.importComponentSetByKeyAsync(BUTTON_SET_KEY);
const primary = buttonSet.children.find(c =>
c.type === "COMPONENT" && c.name.includes("variant=primary")
) || buttonSet.defaultVariant;
// 2. Instance it into your container.
const btn = primary.createInstance();
container.appendChild(btn);
// 3. Override text/variant/boolean props via discovered property keys.
btn.setProperties({ "Label#1:0": "Save changes" });
return { createdNodeIds: [btn.id] };
- Discover a component's property keys by creating a temp instance and reading
componentProperties(and nested instances'), then remove the temp instance. - Read source-code defaults when translating from code —
<Button>with novariantmay default toprimary. Don't assume the library default variant matches the intended one. - Bind any per-component color/spacing to the component tokens (e.g.
--ds-button-*) — see Appendix B — Tokens → Component tokens.
Icons
Icons come from the Icons library.
- If a needed icon exists as a component, instance it (use an
INSTANCE_SWAPslot, not a variant-per-icon). - Otherwise import the SVG source via
figma.createNodeFromSvg(...)and size it to the slot (see thefigma-generate-designcompanion skill → icons). Don't reconstruct icons from rotated primitives.
Icon component props
viewBoxstays 24×24.size: 16 | 20 | 24sets the width/height attributes.strokeWidth: numberis passed directly — not derived fromsize. Default 1.5; use 1 for the 16px size.- Default variant is stroke; fill variant only for critical / warning / success.
- Geometry: rounded end caps, 15° angle increments, corner radius 2.
Building a new component (when lacks one)
Only build locally when the library genuinely doesn't cover the need. Then:
- Follow the
figma-generate-librarycompanion skill for the component workflow (variant sets, properties, bindings). - Bind every visual property to variables/styles — no hardcoded values.
Appendix E — Accessibility
Accessibility is a foundational requirement and a validation gate — not a finishing touch.
Conformance targets
| Theme | Target | Scope |
|---|---|---|
| Default themes (light & dark) | WCAG 2.2 Level AA | Current standard only |
| High-contrast themes (light & dark) | WCAG 2.0 + 2.1 + 2.2 | All levels A, AA, and AAA |
High-contrast variants are purpose-built for accessibility and include both light and dark. During onboarding, users pick a theme preference; they can switch themes from the user-profile dropdown in the main header.
What to verify when building / validating
- Contrast — text and meaningful icons meet AA contrast against their background token in every theme mode you ship (light and dark at minimum). Because colors are token-bound, check the resolved values per mode, not just the light mode.
- Focus visibility — interactive elements (buttons, links, inputs, checkboxes, radios) have a visible focus treatment.
- Touch / target size — interactive targets are large enough; use the sizing tokens (
--ds-size-*) rather than shrinking below component defaults. - Semantic mapping — status meaning (info/success/warning/error) is carried by the correct semantic tokens, not color alone; pair with icon/text where the spec component does.
- Don't defeat the system — overriding a component's tokenized colors with raw values can silently break contrast guarantees. Keep bindings intact.
When you build in Figma, prefer the tokenized, component-driven path (which carries the system's accessibility decisions) and flag any place where a requested visual would violate AA.