Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build or edit Figma designs and components using the <Your Org> (<ABBR>) **<Your DS>** design system. Load alongside `figma-use` whenever a task targets <Your DS> / <Your Org> / <ABBR> products — reusing the published <Your DS> Variables, UI Kit, and Icons libraries (semantic tokens, text styles, effect/elevation styles, components) instead of hardcoding colors, spacing, type, or shadows. Triggers: 'use <Your DS>', 'build with <Your DS>', '<Your Org> design system', '<ABBR> tokens/components', '
.claude/skills/planetabhi-figma-use-design-system/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 574% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 439% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 339% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 353% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 457% | 0% |
Context for using the use_figma MCP tool with <Your Org>'s <Your DS> 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 (<Your DS> 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 <Your DS> 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.
<Your DS> 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 / importStyleByKeyAsync are resolved at runtime from these files — see Appendix A — Libraries & Discovery for the resolution recipe.
--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.--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.ds-heading-01..05, ds-body, ds-body-small, ds-caption, ds-code) via node.textStyleId — don't set font/size/line-height/letter-spacing by hand. Fonts: Inter (UI) and IBM Plex Mono (code).setExplicitVariableModeForCollection; never duplicate a screen to "make a dark version." See Appendix B — Tokens → Theming and Appendix C — Foundations.Follow in order. Load figma-use first.
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.
You need three categories of keys, resolved at runtime (don't guess):
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 <Your DS> screen in the target file is the most authoritative source.
Follow the figma-use incremental workflow (≤10 ops per call, validate after each). For each section:
Promise.all).setProperties.setBoundVariableForPaint, spacing/radius with setBoundVariable, apply text styles via textStyleId, elevation via effectStyleId.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.
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 <Your DS> 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 |
In addition to the figma-use pre-flight checklist, verify:
figma-use loaded; skillNames includes figma-use-design-system.--ds-spacing-* / --ds-size-* / --ds-border-radius-* — no raw px.--ds-shadow-* effect styles — no raw box-shadow.mainComponent, overridden via properties.> These appendices are the inlined references/*.md docs. They live here because Figma's skill upload accepts only this single SKILL.md. Links to figma-use / figma-generate-* point to those companion skills (uploaded separately), not to anything in this file.
The three <Your DS> 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.
| 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, and importStyleByKeyAsync are per-asset publish keys, resolved at runtime (below).
get_libraries({ fileKey: TARGET_FILE_KEY })
// → { libraries_added_to_file: [...], libraries_available_to_add: [...], libraries_available_to_add_next_offset }Confirm all three <Your DS> 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.
If the target file already has <Your DS> screens, walk one to get an exact component map — authoritative because it reflects what's actually published and linked.
js// 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()];
search_design_system, scoped to the <Your DS> librariessearch_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".
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:
jsconst 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 };
js// 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:
await figma.importComponentSetByKeyAsync(key) / importComponentByKeyAsync(key)await figma.variables.importVariableByKeyAsync(key)await figma.importStyleByKeyAsync(key) → apply via node.textStyleId / node.effectStyleId> ⚠️ getLocalVariableCollectionsAsync() returning empty does not mean <Your DS> has no variables — remote/published library variables are invisible to it. Use search_design_system (A.2.B) or inspect a screen (A.2.A).
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.
Semantic tokens standardize design decisions (color, spacing, sizing, radius) in a reusable, theme-aware way. Prefer these over global primitives (Appendix C — Foundations).
--[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| 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 |
| 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 |
| 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 |
| 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) | |
--ds-spacing-* aliases → primitive)zero→0 · xs→4 · s→8 · m→12 · l→16 · xl→24 · xxl→32 · xxxl→48 (px).
--ds-size-* → primitive)xs→spacing-16 (1rem) · s→spacing-24 (1.5rem) · default→spacing-32 (2rem) · l→spacing-40 (2.5rem).
--ds-border-radius-*)s→spacing-2 (.125rem) · default→spacing-4 (.25rem) · l→spacing-8 (.5rem) · max→50vh (pill).
| 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).
Light, dark, and high-contrast (light & dark) are modes on the <Your DS> Variables collections — not separate values you hand-pick.
js// 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);
js// 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.
Reference values for the <Your DS> primitives. Bind to the <Your DS> 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-.
> 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.
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.
--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 |
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) |
--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.
--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.
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 |
viewBox stays 24×24; size sets width/height attrs.strokeWidth is a separate prop, not scaled from size.size: 16 | 20 | 24, strokeWidth: number. See Appendix D — Components → Icon component props.| 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.
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.
Known components include:
> This list reflects the spec snapshot; the published library is the source of truth. Discover the live set with search_design_system or by inspecting the UI Kit file.
Patterns are composed from components + layout guides; assemble them from instances, don't flatten.
js// 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] };
componentProperties (and nested instances'), then remove the temp instance.<Button> with no variant may default to primary. Don't assume the library default variant matches the intended one.--ds-button-*) — see Appendix B — Tokens → Component tokens.Icons come from the Icons library.
INSTANCE_SWAP slot, not a variant-per-icon).figma.createNodeFromSvg(...) and size it to the slot (see the figma-generate-design companion skill → icons). Don't reconstruct icons from rotated primitives.viewBox stays 24×24.size: 16 | 20 | 24 sets the width/height attributes.strokeWidth: number is passed directly — not derived from size. Default 1.5; use 1 for the 16px size.Only build locally when the library genuinely doesn't cover the need. Then:
figma-generate-library companion skill for the component workflow (variant sets, properties, bindings).Accessibility is a foundational requirement and a validation gate — not a finishing touch.
| 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.
--ds-size-*) rather than shrinking below component defaults.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.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | fail→pass | 8,328 | 9,005 | +8% | 1 | 1 | 0% | 1,383 | 9,318 | +574% | 0 | 0 | — |
case-08 | fail→fail | 8,477 | 5,919 | -30% | 1 | 1 | 0% | 1,353 | 8,874 | +556% | 0 | 0 | — |
case-09 | fail→pass | 9,880 | 3,923 | -60% | 1 | 1 | 0% | 1,599 | 8,612 | +439% | 0 | 0 | — |
case-01 | fail→fail | 19,655 | 11,204 | -43% | 1 | 1 | 0% | 3,636 | 8,507 | +134% | 0 | 0 | — |
case-02 | fail→fail | 13,142 | 17,169 | +31% | 1 | 1 | 0% | 2,809 | 8,943 | +218% | 0 | 0 | — |
case-03 | fail→fail | 26,822 | 33,757 | +26% | 1 | 1 | 0% | 6,201 | 14,495 | +134% | 0 | 0 | — |
case-04 | pass→pass | 9,698 | 9,587 | -1% | 1 | 1 | 0% | 2,258 | 9,851 | +336% | 0 | 0 | — |
case-05 | pass→pass | 10,834 | 9,045 | -17% | 1 | 1 | 0% | 2,708 | 10,061 | +272% | 0 | 0 | — |
case-06 | pass→pass | 11,318 | 17,530 | +55% | 1 | 1 | 0% | 2,540 | 11,319 | +346% | 0 | 0 | — |
case-10 | fail→pass | 8,837 | 4,019 | -55% | 1 | 1 | 0% | 1,939 | 8,514 | +339% | 0 | 0 | — |
case-11 | fail→pass | 10,819 | 4,939 | -54% | 1 | 1 | 0% | 1,962 | 8,887 | +353% | 0 | 0 | — |
case-12 | fail→fail | 10,210 | 2,277 | -78% | 1 | 1 | 0% | 1,726 | 8,288 | +380% | 0 | 0 | — |
case-13 | fail→pass | 9,330 | 2,487 | -73% | 1 | 1 | 0% | 1,476 | 8,227 | +457% | 0 | 0 | — |
case-14 | pass→pass | 8,460 | 3,609 | -57% | 1 | 1 | 0% | 1,312 | 8,487 | +547% | 0 | 0 | — |
case-15 | fail→pass | 9,802 | 2,510 | -74% | 1 | 1 | 0% | 1,701 | 8,311 | +389% | 0 | 0 | — |
case-16 | pass→pass | 9,030 | 4,667 | -48% | 1 | 1 | 0% | 1,845 | 8,712 | +372% | 0 | 0 | — |
case-17 | pass→pass | 7,544 | 4,648 | -38% | 1 | 1 | 0% | 1,510 | 8,837 | +485% | 0 | 0 | — |
case-18 | pass→pass | 5,294 | 2,940 | -44% | 1 | 1 | 0% | 894 | 8,406 | +840% | 0 | 0 | — |
case-19 | fail→pass | 8,327 | 4,944 | -41% | 1 | 1 | 0% | 1,522 | 8,877 | +483% | 0 | 0 | — |
case-20 | fail→fail | 9,816 | 3,416 | -65% | 1 | 1 | 0% | 1,639 | 8,432 | +414% | 0 | 0 | — |
case-21 | fail→pass | 8,094 | 2,779 | -66% | 1 | 1 | 0% | 1,431 | 8,380 | +486% | 0 | 0 | — |
case-22 | fail→pass | 14,223 | 4,740 | -67% | 1 | 1 | 0% | 2,756 | 8,619 | +213% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 20 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.