diff --git a/skills/igniteui-angular-figma-to-app/SKILL.md b/skills/igniteui-angular-figma-to-app/SKILL.md new file mode 100644 index 00000000000..ef5dfd6c44b --- /dev/null +++ b/skills/igniteui-angular-figma-to-app/SKILL.md @@ -0,0 +1,760 @@ +--- +name: igniteui-angular-figma-to-app +description: > + Translate Figma app screens designed using the Indigo.Design UI Kits into production + Angular applications with Ignite UI for Angular. The Indigo.Design UI Kits are Figma + component libraries available in four design-system variants — Material, Fluent, + Bootstrap, and Indigo — each with light and dark themes. Designers build their own + app frames in Figma using these kit libraries, and every kit component instance maps + 1:1 to an Ignite UI Angular control. The active kit variant also determines the + design system used in the Angular theme. Uses the Figma MCP for design data, the + Ignite UI CLI MCP for component docs, the Ignite UI Theming MCP for palette and + component-level styling, and the Playwright MCP for visual validation against the + original Figma design. Triggers on "implement this Figma design", "build from Figma", + "translate Figma to Angular", "implement this artboard", "generate app from Figma", + or when a Figma URL is shared with implementation intent in an Ignite UI Angular context. +user-invocable: true +--- + +# Ignite UI for Angular — Figma to App + +Translate Figma app screens built with the **Indigo.Design UI Kits** into production +Angular applications. Designers create their own frames in Figma using the Indigo.Design +component libraries as shared libraries — these kits come in four design-system variants +(**Material**, **Fluent**, **Bootstrap**, **Indigo**) with light and dark themes each. +Every component instance in the design maps 1:1 to an Ignite UI Angular control, and +the active kit variant directly determines which design system to use in the Angular +theme. + +This skill orchestrates four MCP servers: **Figma** (design data), **Ignite UI CLI** +(component docs), **Ignite UI Theming** (styles), and **Playwright** (visual validation). + +--- + +## MANDATORY AGENT PROTOCOL + +You **must** complete all phases in order. Do **not** skip phases or generate component +code from memory. Every component selector, input name, and import path must come from +`get_doc` results — never guessed. + +Read [references/figma-component-map.md](references/figma-component-map.md) before Phase 2. +Read [references/design-token-bridge.md](references/design-token-bridge.md) before Phase 3. +Read [references/asset-extraction.md](references/asset-extraction.md) before Phase 1h. +Read [references/validation-patterns.md](references/validation-patterns.md) before Phase 5. + +--- + +## Phase 0 — Prerequisites + +### 0a: Verify All Four MCP Servers + +Run these checks **silently** in parallel. Each verification call is a no-op if the +server is not connected; do not surface raw errors to the user at this point. + +| Server | Verification call | Success signal | +| --------------------- | ---------------------------------------------- | ----------------------------------- | +| **Figma** | `figma_get_metadata` with no `nodeId` | Returns page list or selection info | +| **Ignite UI CLI** | `igniteui_cli_list_components` with `framework: "angular"` | Returns component list | +| **Ignite UI Theming** | `theming_detect_platform` | Returns platform info | +| **Playwright** | `playwright_browser_navigate` to `about:blank` | Navigates without error | + +If **any server fails**, stop and guide the user through setup **for that server only** +before continuing. Full setup instructions for all servers are in +[references/mcp-setup.md](references/mcp-setup.md). + +### 0b: Detect or Scaffold Angular Project + +Check whether the current working directory contains a valid Angular + Ignite UI project: + +``` +1. Does package.json exist? +2. Does it list "igniteui-angular" OR "@infragistics/igniteui-angular" in dependencies? +3. Is there a src/app/ directory? +``` + +**If a valid project is found:** + +- Note the package layout: `igniteui-angular` (open-source) or `@infragistics/igniteui-angular` (licensed) +- Note the Angular version from `package.json` +- **Check `.vscode/mcp.json` for all four required MCP server entries** — `figma`, `igniteui-cli`, + `igniteui-theming`, and `playwright`. If any are missing, add them from + [references/mcp-setup.md](references/mcp-setup.md) before continuing. Projects scaffolded with + `npx igniteui-cli new` have `igniteui-cli` pre-wired but typically lack the other three. +- Check whether `.vscode/mcp.json` exists in the project root. If it does not, run + `npx -y igniteui-cli ai-config` from the project root to auto-generate the Ignite UI + CLI MCP server configuration and copy the Agent Skills — this ensures `list_components` + and `get_doc` are wired up before Phase 2. +- Inform the user: "Found existing Ignite UI Angular project. Proceeding with the Figma workflow." + +**If no valid project is found:** +Present this message and wait for the user’s choice: + +> “No Ignite UI Angular project found in the current directory. Would you like me to +> scaffold a new one using the Ignite UI CLI before implementing the Figma design? +> +> `npx -y igniteui-cli new` creates a project pre-configured with Ignite UI Angular, +> theming already applied in `styles.scss`, and the Ignite UI CLI MCP server auto-wired +> into `.vscode/mcp.json`. No global install required. +> +> Alternatively, point me at an existing project directory.” + +If the user confirms scaffolding: + +1. Ask for a project name. If the user has already shared a Figma URL, suggest a name + derived from the Figma file name; otherwise prompt. + +2. Choose the project template based on the artboard structure. Because Phase 1 has + not run yet, use the lightest signal available: + + | Signal | Template to use | + | -------------------------------------------------------------------- | ------------------------------------------------ | + | User mentions a sidebar, navigation drawer, or multiple routed views | `side-nav` | + | No strong signal — default | `empty` (routing + home page; easiest to extend) | + +3. Create the project: + + ```bash + npx -y igniteui-cli new --framework=angular --type=igx-ts --template= + ``` + + This produces a standard Angular workspace fully compatible with `ng` commands, + and additionally: + - Installs and configures `igniteui-angular` with a default theme in `styles.scss` + - Generates `.vscode/mcp.json` with the Ignite UI CLI MCP server entry already set + - Copies Ignite UI Agent Skills to `.claude/skills/` + +4. `cd ` + +5. Open the auto-generated `.vscode/mcp.json` and **append** the Figma, Ignite UI + Theming, and Playwright server entries from `references/mcp-setup.md`. The Ignite + UI CLI entry is already present — do not duplicate it. + +6. Confirm the project starts cleanly: + ```bash + npm start + ``` + Then continue to Phase 1. + +--- + +## Phase 1 — Figma Design Exploration + +**Goal:** understand the full design structure and capture all data needed for +implementation and validation before writing any code. + +> **Rate-limit awareness:** Figma MCP calls count against plan quotas. +> Starter plan: **6 calls/month**. Organization plan: 200/day. Enterprise: 600/day. +> +> Estimated call budget for a 5-artboard design: +> `figma_get_metadata` ×2 + `figma_get_screenshot` ×5 + `figma_get_design_context` ×5 + `figma_get_variable_defs` ×1 + `figma_get_code_connect_map` ×5 = **~18 calls**. +> **Starter plan users will exceed their monthly quota in a single session.** Strategies: +> 1. Call `figma_get_variable_defs` only **once** for the root page (variables are file-scoped, not artboard-scoped — calling it per artboard wastes quota on duplicate data). +> 2. Prioritize `figma_get_design_context` over additional screenshots if quota is tight. +> 3. For large files, consider implementing one artboard per monthly budget cycle. +> +> Use `figma_get_metadata` first to discover structure cheaply, then call +> `figma_get_design_context` only for the artboards you will implement. + +### 1a: Discover Pages and Artboards + +Call `figma_get_metadata` with no `nodeId`. This returns the top-level page list. +Then call `figma_get_metadata` again for each page that looks relevant to get its +artboard tree. + +> If the user already shared a Figma URL, extract the `nodeId` from it: +> URL format: `https://figma.com/design/:fileKey/:name?node-id=1-2` → nodeId = `1:2` +> (replace `-` with `:`) + +### 1b: Select Target Artboards + +If there are multiple pages or artboards, show the user a list: + +> "I found these artboards in your Figma file: +> +> - Page 1: [list artboard names + node IDs] +> - Page 2: [list artboard names + node IDs] +> +> Which artboards should I implement? (You can say 'all' or list specific names.)" + +Wait for confirmation before proceeding. + +### 1c: Capture Reference Screenshots + +> **IMPORTANT — Figma MCP is session-bound.** The `figma_get_screenshot` tool returns a +> screenshot of the **currently selected node in the Figma desktop app**, regardless of any +> `nodeId` parameter passed. To capture each artboard, you must ask the user to navigate +> to it in Figma first. + +For each target artboard: + +1. Ask the user: *"In Figma, please click the **[Artboard Name]** frame to select it, then confirm."* +2. Wait for confirmation, then call: + ``` + figma_get_screenshot({}) + // Store: { artboardName, screenshotFile, width: , height: } + ``` +3. Repeat for each artboard — do **not** batch these calls before the user navigates. + +After all artboards are captured, confirm the count: +> *"I have N reference screenshots: [list artboard names]. Proceeding to design context extraction." +> If any are missing, navigate to that artboard in Figma and recapture before continuing.* + +> Never skip this step. The screenshots are your ground truth for Phase 5 validation. + +### 1d: Extract Design Context + +> **IMPORTANT — Figma MCP is session-bound.** The `figma_get_design_context` tool returns +> context for the **currently selected node in the Figma desktop app**. You must ask the +> user to navigate to each artboard before calling this tool. +> +> **Output format:** `figma_get_design_context` returns **React + Tailwind CSS code**, not +> structured Angular metadata. The response is explicitly tagged *"SUPER CRITICAL: The +> generated React+Tailwind code MUST be converted to match the target project's technology +> stack."* Do **not** copy the React code into Angular files. Instead, read the JSX to extract +> the information below. Image localhost URLs in the output are session-scoped previews — +> do **not** use them as final assets (see Phase 1h and `references/asset-extraction.md`). + +For **each** target artboard: + +1. Ask the user: *"In Figma, please click the **[Artboard Name]** frame to select it, then confirm."* +2. Wait for confirmation, then call: + ``` + figma_get_design_context({ + clientLanguages: "typescript", + clientFrameworks: "angular", + artifactType: "WEB_PAGE_OR_APP_SCREEN", + taskType: "CREATE_ARTIFACT" + }) + ``` +3. From the React+Tailwind output, extract: + + - **Component layer names** (`data-name` attributes in the JSX) — match against `references/figma-component-map.md` + - **Layout structure** — `flex`, `grid`, `gap-*`, `p-*`, `w-*`, `h-*` Tailwind classes on container divs + - **Typography** — `font-['...']`, `text-[...]`, `font-weight` classes + - **Surface colors** — `bg-[#XXXXXX]` classes on container `
` elements that wrap major sections + (these become plain `
` wrappers in Angular with `background: #XXXXXX`) + - **Border/roundness** — `rounded-[...]`, `border`, `border-[...]` classes on containers and cards + - **Input type variants** — look for hidden zero-size nodes (`size-[0.5px]`) whose `data-name` + contains a component type (e.g. `"Date Picker Type"`, `"Combo Input"`). These are the + Indigo.Design kit's **variant indicator nodes** — their name encodes which input variant + (border/line/box) is active for that component. + - **Chart series colors** — for any chart layer, note the fill colors on its series paths + - **Action controls** — list every button, icon button, and toolbar action visible in the artboard; + this is your authoritative inventory — do not add actions not present in the design + - **Active kit variant** — look for library component references whose source file name + contains "Material", "Fluent", "Bootstrap", or "Indigo". If not found here, defer to + Phase 1e variable names and [references/design-token-bridge.md](references/design-token-bridge.md). + +4. Record all surface containers in the **Surfaces Spec** (added to Phase 1g). + +### 1e: Extract Design Tokens + +> Figma variables are **file-scoped**, not artboard-scoped. Call `figma_get_variable_defs` +> **once** for the root page node — not once per artboard. Calling it multiple times returns +> identical data and wastes plan quota. + +Call once: + +``` +figma_get_variable_defs({}) +``` + +The response contains a map of variable names to values, e.g.: + +``` +"color/primary/500": "#6200EE" +"color/surface": "#FFFFFF" +"typography/body/font-family": "Roboto" +``` + +Use `references/design-token-bridge.md` to map color and typography variables to Ignite +UI theming inputs in Phase 3. Do **not** attempt to map Figma spacing or sizing values +— see `references/design-token-bridge.md § Spacing, Sizing, and Roundness` for why. + +### 1f: Check for Existing Code Connect Mappings + +Call `figma_get_code_connect_map` for each artboard. If mappings exist, they confirm +which Ignite UI Angular components correspond to which Figma nodes — use these to +validate or augment your component mapping in Phase 2. + +``` +figma_get_code_connect_map({ nodeId: "" }) +``` + +### 1g: Build the Decomposition Table + +Before writing any code, produce **two tables** for **each artboard**. + +#### Table A — Ignite UI Components + +| Figma Layer Name | Visual Role | Ignite UI Component | Design Tokens Used | Data Type | +| -------------------------- | ------------------ | ----------------------- | ------------------- | --------------- | +| _e.g._ `_NavBar` | Top navigation bar | `IgxNavbarComponent` | `color/primary/500` | n/a | +| _e.g._ `_Grid/Default` | Data table | `IgxGridComponent` | `color/surface` | Tabular records | +| _e.g._ `_Button/Contained` | Primary CTA | `igxButton="contained"` | `color/primary/500` | n/a | + +Fallback to plain semantic HTML only when no Ignite UI component can match the layer +after consulting `references/figma-component-map.md`. Document the reason inline. + +#### Table B — Layout Surfaces + +Record every **non-IgxXxx container** that carries visual properties (background color, +border, padding, shadow). These are plain `
` wrappers in Angular — not Ignite UI +components — but they are critical to visual fidelity. Populate this table from the +`bg-[...]`, `rounded-[...]`, `border`, `p-[...]`, and `shadow-[...]` Tailwind classes +observed on container divs in the Phase 1d design context output. + +| Figma Frame / Container Name | Background | Border-Radius | Padding | Border | Shadow | Encloses (child sections) | +| ---------------------------- | ---------- | ------------- | ------- | ------ | ------ | ------------------------- | +| _e.g._ `Budget Categories` | `#222222` | `4px` | `24px` | none | none | Categories list, Add button | +| _e.g._ `Friend Card` | `#222222` | `8px` | `24px 16px` | `1px solid #333` | none | Avatar, name, phone, email, buttons | + +> **Rule:** if a section appears on a surface in Figma (i.e. its container has a +> non-transparent background), it **must** have that background in the Angular implementation. +> If a section floats on the page background (transparent), do **not** add a surface wrapper. +> Never infer surface structure from another page — always derive it from the design context +> for the specific artboard being implemented. + +Present both tables to the user for review before proceeding. + +### 1h: Extract Image Assets + +Read [references/asset-extraction.md](references/asset-extraction.md) in full before +running any extraction. + +**Zero-placeholder policy:** every image visible in the Figma design must be extracted +and committed to `src/assets/` before Phase 4. Gradient placeholders are not acceptable. + +**Step 0 — Get the file key first.** Ask the user to share the Figma file URL or key +before attempting any extraction. In Figma desktop: right-click the file tab → +**Copy link**. Without it you fall back to Tier 2 or Tier 3 (see below). + +From the decomposition tables, identify every layer that is a **static image asset** +(photo, background, logo, custom icon, illustration) rather than an Ignite UI component. +Do **not** extract Indigo.Design UI Kit component instances. + +**Use the four-tier decision tree from `asset-extraction.md`:** + +| Tier | Method | When to use | +| ---- | ------ | ----------- | +| **1** | REST API `/v1/files/:key/images` (Method A) or `/v1/images/:key` (Method B) | File key available — always the highest fidelity | +| **2** | Download localhost URLs from `figma_get_design_context` with `curl` | No file key; Figma session is active; design context was already called | +| **3** | `figma_get_screenshot` per node (ask user to select each node) | No file key; no localhost URLs | +| **4** | CSS gradient/color placeholder with `// TODO` comment | Only for confirmed pure-color fills — never as a shortcut | + +After extraction, save assets to: +- `src/assets/images/` — raster images (PNG, JPG) +- `src/assets/icons/` — SVG icons and logos + +Build a concise asset manifest (see `asset-extraction.md § Build an Asset Manifest`) +so the implementation phase uses consistent paths. + +If you used Tier 2 or Tier 3 for any asset, tell the user which ones need re-export +once the file key becomes available. + +--- + +## Phase 2 — Component Discovery (Ignite UI CLI MCP) + +**Goal:** look up exact Angular selectors, inputs, outputs, and usage patterns for every +component identified in Phase 1. Never generate component code from memory. + +### 2a: Read the Component Map + +Read [references/figma-component-map.md](references/figma-component-map.md) in full. +Find the row for each Figma layer name from your Phase 1 decomposition table. +Each row gives you: + +- The Ignite UI Angular selector +- The `get_doc` key to call +- Key inputs and variants to configure + +### 2b: Fetch Component Docs + +For every component family you will use, call `get_doc`: + +``` +list_components({ framework: "angular" }) // once, to discover doc names +get_doc({ framework: "angular", name: "" }) // per component family +``` + +Call all `get_doc` requests **in a single parallel batch** — never sequentially. +Do **not** write any component code until you have read its doc. + +### 2c: Search for Feature Docs + +Use `search_docs` for feature-level questions raised by the artboard, for example: + +``` +search_docs({ framework: "angular", query: "row editing" }) +search_docs({ framework: "angular", query: "virtual scrolling" }) +search_docs({ framework: "angular", query: "column pinning" }) +``` + +Feature docs are mandatory when the artboard shows grid editing, filtering, sorting, +pinning, or other advanced feature states. + +### 2d: Document the Final Component Plan + +After reading all docs, confirm or revise the decomposition table from Phase 1g with: + +- Exact selectors (e.g. ``, ``) +- Exact import paths (never imported from the root barrel) +- Required peer modules or provider functions + +Present this updated plan to the user and wait for confirmation before Phase 3. + +--- + +## Phase 3 — Theme Generation (Ignite UI Theming MCP) + +**Goal:** produce Sass theming code that matches the Figma design's visual language +using design tokens extracted in Phase 1e. + +Read [references/design-token-bridge.md](references/design-token-bridge.md) in full +before running any theming tool. + +### 3a: Inspect Existing Theme (Guard) + +Open `src/styles.scss` (or the project's global stylesheet). Look for an active +`@include theme(...)` or `@include palette(...)` call. + +- **Theme found, but variant mismatch** — if the existing theme is **light** and the + Figma design is **dark** (or vice versa), treat this as a theme change and proceed with + 3b–3c. A light theme applied to a dark design produces wrong background colors on every + component and will fail every Phase 5 check. +- **Theme found, variant matches** → do **not** call `theming_create_theme` or + `theming_create_palette` unless the user explicitly asks for a global theme change. + Reuse the existing palette. Skip to step 3d. +- **No theme found** → proceed with 3b. + +Detect the Figma design's variant from Phase 1e: if a `color/mode` variable exists, +use its value. Otherwise, use the artboard background color: near-black (`#121212`, +`#1a1a1a`, `#000`) → `"dark"`; near-white (`#fff`, `#f5f5f5`) → `"light"`. + +### 3b: Resolve Design System + +You don't need to call `theming_detect_platform` to confirm the Angular package layout. We already did that in Phase 0. + +To determine the design system, use this **strict precedence order**. Stop at the first +signal that gives a clear answer: + +1. **Explicit user request** — "make it Material", "use Fluent", etc. +2. **Library source name in design context** — the `figma_get_design_context` or + `figma_get_metadata` response may reference the Figma source library file name + (e.g. `"Indigo.Design UI Kit for Material"` → `material`). +3. **Variable collection names from Phase 1e** — collection names like + `Material/color/primary` identify the kit variant directly. +4. **Elevation variable structure** — inspect the `Elevations/*` variables in + `figma_get_variable_defs` output: + - **Three-layer DROP_SHADOW** (umbra + penumbra + ambient) → **Material Design** + - **Single-layer DROP_SHADOW** → Indigo, Fluent, or Bootstrap +5. **Palette shade naming** — variables named `primary/500`, `primary/100`–`primary/900` + follow the Material 100–900 palette convention → likely **Material**. +6. **Visual heuristics** (use only when all above are inconclusive): + prominent shadows + ripple effects → `"material"`; + flat surfaces + sharp corners + Segoe/Inter font → `"fluent"`; + component borders + Bootstrap grid → `"bootstrap"`; + rounded purple/indigo accents without Material shadows → `"indigo"`. + +> **Never use font name as a primary signal.** "Titillium Web" is the default body font +> in the Indigo.Design UI Kit for Material — it is not exclusive to the Indigo design system. + +Supported values: `material` (default), `bootstrap`, `fluent`, `indigo`. + +### 3c: Generate Global Theme + +Extract the following from Phase 1e variables using +[references/design-token-bridge.md](references/design-token-bridge.md): + +``` +primaryColor ← from "color/primary/500" or "primary/500" +secondaryColor ← from "color/secondary/500" or "secondary/500" +surfaceColor ← from "color/surface" or "surface/default" +fontFamily ← from "typography/font-family" or "typography/body/font-family" +``` + +Then call in order: + +> **Parameter names differ between tools** — `theming_create_palette` uses `primary`, +> `secondary`, `surface` (not `primaryColor` etc.). `theming_create_theme` uses +> `primaryColor`, `secondaryColor`, `surfaceColor`. Do not mix them up. + +> **fontFamily double-quote bug** — `theming_create_theme` may double-wrap the fontFamily +> string (e.g. `""'Titillium Web', sans-serif""`) in its Sass output, producing invalid Sass. +> If you see double-quoted strings in the generated output, strip the outer quotes before +> applying to `styles.scss`. + +``` +theming_create_palette({ + primary: primaryColor, + secondary: secondaryColor, + surface: surfaceColor, + platform: "angular", + licensed: +}) + +theming_create_elevations({ + preset: "material" // or "indigo" if design system is Indigo +}) + +theming_create_typography({ + fontFamily, + platform: "angular" +}) + +theming_create_theme({ + palette: , + elevations: , + typography: , + variant: "", + designSystem: "", + platform: "angular", + licensed: +}) +``` + +Apply the generated output to `src/styles.scss` as instructed in the tool's response. + +### 3d: Per-Component Token Mapping + +> **Scope:** applies only to core Ignite UI Angular components (grid, navbar, card, +> inputs, chips, list, etc.). Charts, maps, and gauges have no Sass tokens — configure +> those via component inputs only. + +For **every** Ignite UI core component in your plan, run this loop: + +1. `theming_get_component_design_tokens({ component: "" })` + — review all token names, types, and descriptions +2. Go back to the Phase 1e variable map and find Figma variables that correspond to + this component's surfaces (background, text, border, hover state) +3. `theming_create_component_theme({ component: "", platform: "angular", tokens: { } })` +4. Apply the generated `@include tokens()` block to the component's SCSS or to a + scoped block in `styles.scss` + +When a specific component needs a different density or spacing from the global default, +use `theming_set_size` or `theming_set_spacing` with the `component` parameter — this +scopes `--ig-size` or `--ig-spacing` to that component’s selector rather than applying +globally. For compound components, use `scope` with a sub-component selector. Only +apply these globally (`:root`) when the entire app has a clearly distinct density. +Leave `theming_set_roundness` at its default unless the user explicitly requests a +change. Never derive multiplier values from Figma pixel values. +See `references/design-token-bridge.md § Spacing, Sizing, and Roundness`. + +--- + +## Phase 4 — Implementation + +**Goal:** build the Angular view(s) that match the artboard decomposition from Phase 2. + +### Implementation Rules + +1. **Never generate component code without reading its `get_doc` result first** (Phase 2b) +2. **Section by section** — layout → navigation → primary content → secondary → data +3. Follow Angular standalone component conventions and AGENTS.md coding standards +4. Import components from their specific entry points, never from the root barrel +5. Use CSS Grid first to match Figma frame proportions; add Flexbox for sub-regions +6. Apply theming via the SCSS classes and tokens generated in Phase 3 +7. Use typed mock data that matches the design's density and domain +8. Keep layout, spacing, and typography in SCSS files — not inline styles +9. For DV components (charts, maps, gauges), set visual properties via component inputs + as described in [references/figma-component-map.md](references/figma-component-map.md) +10. After implementing each major section, save and check in the browser (if dev server is running) +11. **Global input type:** if the Figma design uses `border`-type inputs globally (detected + via variant indicator nodes in Phase 1d), set the `IGX_INPUT_GROUP_TYPE` injection token + once in `app.config.ts` rather than `type="border"` on every component. This covers all + compound components that wrap `IgxInputGroup` internally (`IgxSimpleCombo`, + `IgxDatePickerComponent`, `IgxDateRangePickerComponent`, `IgxTimePickerComponent`, + `IgxSelectComponent`): + ```typescript + // app.config.ts + import { IGX_INPUT_GROUP_TYPE } from 'igniteui-angular/input-group'; + // in providers array: + { provide: IGX_INPUT_GROUP_TYPE, useValue: 'border' } + ``` +12. **Layout surfaces:** for every entry in the Phase 1g Surfaces table, add a CSS class + with the recorded `background`, `border-radius`, `padding`, `border`, and `box-shadow`. + Never leave a section transparent if the Figma surface has a background. Never add a + background to a section that floats on the page background in the Figma design. +13. **Implement only controls that appear in the Figma artboard.** Do not add toolbar + buttons, actions, or UI elements that look useful but are not visible in the design + context output for that artboard. + +### Layout Strategy + +Translate Figma frame dimensions into CSS Grid first: + +```scss +// Artboard: 1440×900px, sidebar 280px, content 1160px +.app-layout { + display: grid; + grid-template-columns: 280px 1fr; + grid-template-rows: 64px 1fr; + min-height: 100vh; +} +``` + +Match desktop proportions before adding responsive breakpoints. + +### Angular Project Structure + +For a new view or page generated from a Figma artboard, create: + +``` +src/app/ + / + .component.ts ← standalone component + .component.html ← template + .component.scss ← styles + component theme overrides +``` + +Register the route in `app.routes.ts` when the project uses routing. + +--- + +## Phase 5 — Visual Validation (Playwright MCP) + +**Goal:** measure and compare the running app against the Figma reference screenshots +from Phase 1c. Use the measurement-driven loop — compare numbers, not impressions. + +Read [references/validation-patterns.md](references/validation-patterns.md) in full +before running any Playwright tool. + +### 5a: Ensure the Dev Server Is Running + +Ask the user for the local dev URL if not already known (default: `http://localhost:4200`). +Navigate to confirm the app is running: + +``` +playwright_browser_navigate({ url: "http://localhost:4200" }) +playwright_browser_console_messages() // check for startup errors +``` + +### 5b: Match Viewport to Artboard Dimensions + +Resize the browser to match the Figma artboard dimensions captured in Phase 1c: + +``` +playwright_browser_resize({ width: , height: }) +playwright_browser_navigate({ url: "" }) // re-navigate after resize +``` + +> **Always re-navigate after resize.** The browser may reset to `about:blank` on +> viewport change. This is a known Playwright MCP pitfall. + +### 5c: Capture and Compare Screenshots + +> **IMPORTANT — Figma MCP is session-bound.** To get a fresh Figma reference screenshot +> for comparison, ask the user to select the artboard in Figma, then call +> `figma_get_screenshot({})`. Alternatively, use the Phase 1c reference screenshots +> already saved to disk. + +For **each target artboard** (run the full 5c–5f loop once per page): + +1. Ask the user: *"In Figma, please click the **[Artboard Name]** frame to select it, then confirm."* +2. Navigate the browser to the corresponding route. +3. Take a browser screenshot: + ``` + playwright_browser_take_screenshot({ type: "png" }) + ``` +4. Do a **section-by-section** visual comparison against the Phase 1c reference: + - top bar → sidebar → **every section in the Phase 1g Surfaces table** → footer +5. Do **not** advance to the next artboard until no Critical/Major issues remain on the current one. + +### 5d: Measure Computed Styles + +For each section with visible differences — and **mandatorily for every entry in the +Phase 1g Surfaces table** — use `playwright_browser_evaluate` to extract exact values. +Pass code as a **plain JavaScript function string** using the `function` parameter +(see [references/validation-patterns.md](references/validation-patterns.md)): + +``` +playwright_browser_evaluate({ + function: "() => { var el = document.querySelector(''); if (!el) return { error: 'not found' }; var s = getComputedStyle(el); var r = el.getBoundingClientRect(); return { fontSize: s.fontSize, backgroundColor: s.backgroundColor, padding: s.padding, borderRadius: s.borderRadius, border: s.border, gap: s.gap, height: Math.round(r.height), width: Math.round(r.width) }; }" +}) +``` + +**Surfaces audit (mandatory for every page):** For every section in the Phase 1g Surfaces +table, assert: +- `backgroundColor` is **not** `rgba(0, 0, 0, 0)` when the surface has a background color +- `backgroundColor` **is** `rgba(0, 0, 0, 0)` when the design shows the section floating + on the page background (no card wrapper) +- All child elements shown inside the surface card in Figma are enclosed within the card's + bounding rect in the DOM + +**Action controls audit (mandatory for every page):** Count and name all visible action +buttons and toolbar controls. Compare against the Phase 1d inventory — any button not +recorded in the Figma design context is fabricated and must be removed. + +Compare all returned values against the Figma spec (from Phase 1d design context). + +### 5e: Classify and Report Mismatches + +| Severity | Category | Example | Action | +| ------------ | --------------- | ----------------------------------------- | --------------------------- | +| **Critical** | Missing element | Button in Figma, absent in code | Auto-fix | +| **Major** | Wrong component | Figma shows dropdown, code has text input | Auto-fix | +| **Minor** | Spacing off | 24px gap in Figma, 16px in code | Auto-fix if straightforward | +| **Cosmetic** | Color shade | `#333` vs `#2d2d2d` | Report only | + +For each mismatch, produce: + +``` +ISSUE: +LOCATION:
+FIGMA: +RENDERED: +SEVERITY: +FIX: +``` + +### 5f: Apply Corrections + +Fix Critical and Major issues immediately. After applying fixes, re-navigate and take a +fresh screenshot to confirm: + +``` +playwright_browser_navigate({ url: "" }) +playwright_browser_take_screenshot({ type: "png" }) +``` + +Repeat the measure → fix → re-verify loop until no Critical or Major issues remain. + +### 5g: Accessibility Snapshot + +Take an accessibility snapshot to verify the structural integrity of the view: + +``` +playwright_browser_snapshot() +``` + +Check that: + +- Interactive elements have accessible labels +- Headings follow a logical hierarchy +- Navigation landmarks are present + +--- + +## Critical Rules + +- **Phase 0 is not optional.** Never skip MCP verification. +- **Phase 2b before code.** Never write a selector you have not read from a doc. +- **Phase 1c screenshots are immutable ground truth.** Never overwrite them; always + compare against the original Figma state. +- **Re-navigate after resize** in Phase 5 to avoid Playwright's browser reset bug. +- **Rate-limit Figma MCP calls.** Use `figma_get_metadata` for discovery, then targeted + `figma_get_design_context` per artboard. Batch screenshot calls. +- **Fail fast on 3 retries.** If the same correction fails three times, stop, report + the issue to the user, and ask for guidance. +- **Never commit `package-lock.json`** or other lock files unintentionally. Ask before + changing any dependency manifest. + +--- + +## Related Skills + +- [`igniteui-angular-components`](../igniteui-angular-components/SKILL.md) — deep reference for non-grid components +- [`igniteui-angular-grids`](../igniteui-angular-grids/SKILL.md) — deep reference for grid, tree-grid, hierarchical-grid, pivot-grid +- [`igniteui-angular-theming`](../igniteui-angular-theming/SKILL.md) — theming system architecture and advanced palette patterns +- [`igniteui-angular-generate-from-image-design`](../igniteui-angular-generate-from-image-design/SKILL.md) — fallback when no Figma file is available (static image input) diff --git a/skills/igniteui-angular-figma-to-app/references/asset-extraction.md b/skills/igniteui-angular-figma-to-app/references/asset-extraction.md new file mode 100644 index 00000000000..346135cb326 --- /dev/null +++ b/skills/igniteui-angular-figma-to-app/references/asset-extraction.md @@ -0,0 +1,393 @@ +# Asset Extraction from Figma + +> **Part of the [`igniteui-angular-figma-to-app`](../SKILL.md) skill.** +> +> Use this file in Phase 1h to identify and extract image assets from Figma artboards +> before implementation. Read in full before calling any extraction tool. +> +> **Zero-placeholder policy:** every image asset visible in the Figma design must be +> extracted and committed to `src/assets/` before Phase 4 begins. Gradient placeholders +> and empty `
` boxes are not acceptable. If the highest-fidelity method is +> unavailable, use the next tier — but always extract something real. + +--- + +## Step 0 — Acquire the Figma File Key (Required for REST API) + +The Figma REST API requires a **file key** — the identifier embedded in every Figma +file URL. Without it, you can still extract assets using Tier 2 and Tier 3 methods +below, but the REST API (Tier 1) produces the highest quality output and should always +be the first attempt. + +**Ask the user for the file key at the start of Phase 1h:** + +> "To extract image assets at the highest quality, I need the Figma file key. +> In the Figma desktop app: +> +> 1. Right-click the file tab at the top → **Copy link** (or go to **File → Share** and copy the URL) +> 2. The URL looks like: `https://www.figma.com/design/ABCDEF1234567890/My-File-Name` +> 3. The file key is the segment after `/design/`: **`ABCDEF1234567890`** +> +> Please share that key (or the full URL). If you cannot access it right now, I will +> proceed with the desktop-app extraction methods and note which assets need to be +> re-exported at higher quality." + +**Extracting the key from a URL (if the user pastes it):** + +```bash +# URL format: https://www.figma.com/design//?... +# Extract key with sed: +echo "https://www.figma.com/design/ABCDEF1234567890/My-App" \ + | sed -E 's|.*/design/([^/]+)/.*|\1|' +# → ABCDEF1234567890 +export FILE_KEY="ABCDEF1234567890" +``` + +**Your Figma personal access token** (same one used for the MCP server) is needed for REST calls. Store it as an environment variable: + +```bash +export FIGMA_TOKEN="your-personal-access-token" +``` + +--- + +## Two Fundamentally Different Types of Image Assets + +Figma stores images in two distinct ways — understanding the difference is essential for choosing the right extraction method: + +| Type | What it is | Figma signal | Best extraction method | +| ---------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- | ---------------------------------------- | +| **Image fill** | A photo, texture, or raster image dragged/pasted into Figma. Stored as an IMAGE fill on a RECTANGLE or FRAME node. | Layer has fill of type `IMAGE`; `imageRef` in node data | REST API Method A → original source file | +| **Vector asset** | A logo, icon, or illustration drawn in Figma using vector tools. | Node type `VECTOR`, `BOOLEAN_OPERATION`, or `GROUP` | REST API Method B → clean SVG | + +Do **not** confuse these with Ignite UI component instances — those become Angular components, not extracted assets. + +--- + +## Step 1 — Identify Image Nodes + +### Naming patterns to look for in `figma_get_metadata` + +Scan the XML returned by `figma_get_metadata` for layer names matching: + +| Naming pattern | Likely asset type | Action | +| -------------------------------------------------- | ----------------- | ----------------------------------------- | +| `_Image`, `_Photo`, `_Picture`, `image`, `photo` | Raster image fill | Extract as PNG | +| `_Hero`, `_Banner`, `_Cover`, `hero`, `banner` | Large raster fill | Extract as PNG (2× scale) | +| `_Thumbnail`, `_Avatar`, `_Illustration` | Raster image fill | Extract as PNG | +| `_Logo`, `_Brand`, `logo`, `brand` | Vector or raster | If vector: extract as SVG; if raster: PNG | +| `_Icon/` prefix (custom icons not in igx-icon set) | Custom SVG icon | Extract as SVG | +| `_Background`, `_Bg`, `bg`, `background` | Large raster fill | Extract as PNG | +| `_Illustration`, `_Art`, `_Pattern` | Vector or raster | Classify before extracting | + +> **Ignore these** — do NOT extract them as image assets: +> +> - Any layer whose name starts with `_Button`, `_Input`, `_Grid`, `_Card`, etc. +> (Indigo.Design UI Kit component instances → implement as IgxXxx components) +> - `igx-icon` glyph nodes (use `` in Angular instead) +> - Artboard/frame boundaries themselves + +### Size heuristic + +Large rectangles (width > 200px or height > 200px) at key layout positions (hero area, +sidebar background, card thumbnail slot) are almost always image fills. + +Small nodes (< 48×48px) named with icon-like names are usually SVG icons. + +### Confirm with design context + +For ambiguous nodes, look at the `figma_get_design_context` output for the artboard. +Each image asset appears as either: + +- An `` — confirms it is a raster fill; note the node ID +- Inline SVG or an `` with `.svg` extension — confirms it is a vector; note the node ID + +Note all localhost image URLs from the design context — these are needed for Tier 2 +extraction if the REST API is unavailable. + +--- + +## Step 2 — Extract at the Highest Available Fidelity + +Use this **four-tier decision tree**. Start at Tier 1. Move to the next tier only if +the previous one is unavailable for this specific asset. + +``` +Do you have the FILE_KEY? +├─ YES → Use Tier 1 (REST API). Always the best. +└─ NO → Did figma_get_design_context include a localhost URL for this asset? + ├─ YES → Use Tier 2 (download localhost URL to disk). + └─ NO → Can you get a clean node screenshot? + ├─ YES → Use Tier 3 (figma_get_screenshot per node). + └─ NO → Use Tier 4 (CSS gradient/color placeholder as last resort, + with a TODO comment to replace later). +``` + +**After completing Phase 4, if you used Tier 2 or Tier 3 for any asset:** + +> Tell the user: "The following assets were extracted at reduced quality because the +> Figma file key was not available: [list]. To replace them with the original +> source files, run the Tier 1 REST API commands in Step 2a once you have the file key." + +--- + +### Tier 1 — REST API (Highest Fidelity) + +**Requires:** `FILE_KEY` and `FIGMA_TOKEN`. + +#### Method A — Original Image Fills + +Use this to download **photos, textures, and raster images** that were uploaded to +Figma (identified by `imageRef` in node fill data). Returns the original source file +at its native resolution — never a re-render. + +```bash +# Step A.1 — Get all image fill URLs in the file +curl -s \ + -H "X-Figma-Token: $FIGMA_TOKEN" \ + "https://api.figma.com/v1/files/$FILE_KEY/images" \ + -o /tmp/figma_image_fills.json + +# Response: { "images": { "": "", ... } } + +# Step A.2 — Get node fill data to match imageRef → node +curl -s \ + -H "X-Figma-Token: $FIGMA_TOKEN" \ + "https://api.figma.com/v1/files/$FILE_KEY/nodes?ids=$NODE_IDS" \ + -o /tmp/figma_nodes.json +# In the response, look for: "fills": [{ "type": "IMAGE", "imageRef": "abc123" }] +# Match "abc123" → URL from figma_image_fills.json + +# Step A.3 — Download to assets folder +mkdir -p src/assets/images src/assets/icons +IMAGE_URL=$(jq -r '.images[""]' /tmp/figma_image_fills.json) +curl -sL "$IMAGE_URL" -o src/assets/images/hero-background.jpg +``` + +> **URL expiry:** image fill URLs expire in **14 days**. Download during the session. + +#### Method B — Node Export (SVG, PNG, JPG) + +Use this to export **any node** as SVG, PNG, or JPG. Best for logos, custom icons, +vector illustrations, and raster compositions. + +```bash +mkdir -p src/assets/images src/assets/icons + +# SVG export (vectors — logos, icons, illustrations) +curl -s \ + -H "X-Figma-Token: $FIGMA_TOKEN" \ + "https://api.figma.com/v1/images/$FILE_KEY?ids=$NODE_IDS&format=svg&svg_outline_text=false&contents_only=true" \ + -o /tmp/figma_svg_export.json + +jq -r '.images | to_entries[] | "\(.key)\t\(.value)"' /tmp/figma_svg_export.json | \ +while IFS=$'\t' read -r nodeId url; do + filename="$(echo "$nodeId" | tr ':' '-').svg" + curl -sL "$url" -o "src/assets/icons/$filename" + echo "Downloaded $nodeId → src/assets/icons/$filename" +done + +# PNG export at 2× (raster compositions, hero banners) +curl -s \ + -H "X-Figma-Token: $FIGMA_TOKEN" \ + "https://api.figma.com/v1/images/$FILE_KEY?ids=$NODE_IDS&format=png&scale=2&contents_only=true" \ + -o /tmp/figma_png_export.json + +jq -r '.images | to_entries[] | "\(.key)\t\(.value)"' /tmp/figma_png_export.json | \ +while IFS=$'\t' read -r nodeId url; do + filename="$(echo "$nodeId" | tr ':' '-').png" + curl -sL "$url" -o "src/assets/images/$filename" +done +``` + +**Key export parameters:** + +| Parameter | Value | When to use | +| ------------------ | ------- | ---------------------------------------------------- | +| `format` | `svg` | Logos, icons, vector illustrations | +| `format` | `png` | Hero backgrounds, thumbnails — always pair `scale=2` | +| `format` | `jpg` | Photos without transparency — use `scale=2` | +| `scale` | `2` | **Always for PNG/JPG** — retina-quality output | +| `svg_outline_text` | `false` | Keep text as `` elements (smaller, accessible) | +| `contents_only` | `true` | Render the node in isolation (default) | + +> **Export URL expiry:** export URLs expire in **30 days**. Download immediately. + +--- + +### Tier 2 — Localhost URL Download (Desktop MCP Fallback) + +**Use when:** the file key is unavailable and `figma_get_design_context` returned +localhost URLs (e.g. `http://localhost:3845/assets/abc123.png`). + +These URLs are served by the Figma desktop app's in-memory renderer and are accessible +via `curl` during the active Figma session. They are **not** the original source file +(they are a renderer output), but they are substantially better than placeholders and +can be committed to the repository. + +```bash +mkdir -p src/assets/images src/assets/icons + +# Extract localhost URLs from a design context output and download them +# Replace with the actual URL found in figma_get_design_context output +curl -sL "http://localhost:3845/assets/.png" -o src/assets/images/hero-background.png +curl -sL "http://localhost:3845/assets/.svg" -o src/assets/icons/logo.svg +``` + +**Finding localhost URLs in design context output:** + +In the React+Tailwind code returned by `figma_get_design_context`, look for: + +- `const imgXxx = "http://localhost:3845/assets/.";` at the top of the output +- `` or `background-image` references inline + +Each `const` at the top is an image asset. Note its variable name, the URL, and which +Figma node it belongs to (from context around the `` tag). + +**Limitations of Tier 2 assets:** + +- Raster renders — vectors become PNGs, not SVGs +- Renderer resolution (typically 2×) — adequate for most uses +- Expire when the Figma desktop app closes — **must be downloaded before closing Figma** +- Must be renamed from `.png` to descriptive names before committing + +**Commit as-is** — they are real assets. Add a comment in the asset manifest: + +```typescript +// TODO: Replace with Tier 1 REST API export once FILE_KEY is available +heroBg: 'assets/images/hero-background.png', // extracted from Figma session +``` + +--- + +### Tier 3 — `figma_get_screenshot` per Node + +**Use when:** no file key AND no localhost URLs were produced for a specific node. + +`figma_get_screenshot` renders any currently-selected Figma node as a PNG screenshot. +Ask the user to select each image node in Figma, then call the tool. + +``` +// 1. Ask: "In Figma, please click the [Hero Background] layer to select it." +// 2. After confirmation: +figma_get_screenshot({}) +// 3. The returned image is a 1× screen-capture PNG. Save it to src/assets/images/. +``` + +**Limitations:** + +- 1× resolution — suitable as a placeholder but blurry on retina screens +- Rasterizes all vectors — logos become PNGs +- May include surrounding canvas elements + +Label these assets clearly in the manifest: + +```typescript +// TODO: Re-export at 2× via Tier 1 or Tier 2 — current version is 1× screen capture +heroBg: 'assets/images/hero-background.png', +``` + +--- + +### Tier 4 — CSS Fallback (Last Resort Only) + +**Use only when** an asset is confirmed to be a pure color fill or a gradient — not when +an image exists in Figma but extraction failed. Never use Tier 4 because extraction +feels difficult. + +```scss +// Only acceptable when the Figma layer is genuinely a gradient, not a photo +.hero-banner { + // TODO: Replace with real asset — extraction blocked (no file key, no session URL) + background: linear-gradient(135deg, #0d1b3e 0%, #1a0533 100%); +} +``` + +If you use Tier 4, add the `TODO` comment and include it in the post-session handoff +notes to the user. + +--- + +## Step 3 — Build an Asset Manifest + +After extraction, create a manifest so the implementation phase uses consistent paths: + +```typescript +// src/app//_assets.ts — generated during Phase 1h + +export const PAGE_ASSETS = { + // Figma node 123:456 — "Hero/Background" layer + // Tier 1: REST API PNG export at 2× + heroBg: 'assets/images/hero-background.jpg', + + // Figma node 789:012 — "_Logo/Main" layer + // Tier 1: REST API SVG export + logo: 'assets/icons/logo.svg', + + // Figma node 345:678 — "Card/Thumbnail" layer + // Tier 2: localhost URL download (TODO: re-export via REST API) + cardThumbnail: 'assets/images/card-thumbnail.png', +} as const; +``` + +Name files by layer purpose, not by node ID. + +--- + +## Step 4 — Angular Usage Patterns + +### Static images via `NgOptimizedImage` + +```html + +Dashboard hero background +``` + +Import `NgOptimizedImage` in the component's `imports` array. Note: `NgOptimizedImage` +does **not** work for inline base64 images. + +### Background images via SCSS + +```scss +.dashboard-hero { + background-image: url('/assets/images/hero-background.jpg'); + background-size: cover; + background-position: center; +} +``` + +### Inline SVG logos + +```html +Company logo +``` + +### Igx-icon for kit icons (do NOT extract as assets) + +Standard Material icons and `imx-icons` (Material Icons Extended) are registered at +runtime — never extract them as image files: + +```html +settings +``` + +See `figma-component-map.md § Material Icons Extended` for setup. + +--- + +## Pitfalls + +| Pitfall | Consequence | Fix | +| ------------------------------------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| Skipping asset extraction entirely (gradient placeholders) | Implementation looks nothing like the design; Phase 5 fails | Always use at least Tier 2 or Tier 3 — never skip | +| Not asking for the file key before starting extraction | Defaults to Tier 2/3 when Tier 1 was actually possible | Ask for the file key at the start of Phase 1h (see Step 0) | +| Using localhost URLs without downloading them in the session | URLs expire when Figma closes; assets become broken | Download with `curl` immediately; commit the files | +| Naming assets by node ID ("node-123-456.png") | Unmaintainable; breaks if Figma is reorganized | Name by layer purpose: `hero-background.jpg`, `company-logo.svg` | +| Using `figma_get_screenshot` for SVG logos | Logo is rasterized to PNG; loses vector scalability | Use Tier 1 Method B with `format=svg` instead; fall back to Tier 2 only if unavailable | +| Exporting PNG at `scale=1` | Blurry on HiDPI/retina screens | Always use `scale=2` | +| Storing Figma CDN export URLs in source code | URLs expire in 14–30 days; breaks production | Only store local `src/assets/...` paths in code | +| Downloading SVG with `svg_outline_text=true` (default) | All text converted to paths; larger file; no accessibility | Set `svg_outline_text=false` | +| Extracting Ignite UI component instances as images | Produces a static screenshot instead of an interactive component | Identify layer names from `figma-component-map.md`; those are components, not assets | +| Extracting background colors or gradients as images | Inflates bundle size, breaks theming | Colors → CSS custom properties or Ignite UI theming tokens | +| Not creating asset directories before running curl | Writes fail silently or to the wrong path | Always run `mkdir -p src/assets/images src/assets/icons` first | +| Large SVGs from complex illustrations | Slow render, large bundle | Consider PNG for illustrations > 50KB as SVG; SVG is best for logos and icons | diff --git a/skills/igniteui-angular-figma-to-app/references/design-token-bridge.md b/skills/igniteui-angular-figma-to-app/references/design-token-bridge.md new file mode 100644 index 00000000000..6ce6526becd --- /dev/null +++ b/skills/igniteui-angular-figma-to-app/references/design-token-bridge.md @@ -0,0 +1,324 @@ +# Figma Variables → Ignite UI Angular Theming Bridge + +> **Part of the [`igniteui-angular-figma-to-app`](../SKILL.md) skill.** +> +> Use this file in Phase 3 to translate Figma variable values (from `figma_get_variable_defs`) +> into Ignite UI Theming MCP inputs. Read this file in full before calling any theming tool. + +--- + +## How the Indigo.Design UI Kits Organize Variables + +The **Indigo.Design UI Kits** are Figma component libraries published by Infragistics. +Designers build their own app frames in Figma using these kits as shared libraries. +The kits come in four design-system variants, each with light and dark themes: + +| Kit variant | Figma library name pattern | Ignite UI `designSystem` | +| ---------------------- | ----------------------------------------------- | ------------------------ | +| Material (most common) | `Indigo.Design UI Kit for Material` | `"material"` | +| Fluent | `Indigo.Design UI Kit for Fluent` | `"fluent"` | +| Bootstrap | `Indigo.Design UI Kit for Bootstrap` | `"bootstrap"` | +| Indigo | `Indigo.Design UI Kit` / `Indigo.Design System` | `"indigo"` | + +**Identifying the active kit variant** is the first task in Phase 3 because it sets +the `designSystem` parameter for `theming_create_theme`. Use these signals in **strict +precedence order** — stop at the first clear match: + +1. **Library source name** — `figma_get_design_context` and `figma_get_metadata` responses + may reference the source library file name (e.g. `"Indigo.Design UI Kit for Material"`). +2. **Variable collection name** — `figma_get_variable_defs` may return collection names + that include the design system (e.g. `Material/color/primary`). +3. **Elevation variable structure** — inspect the `Elevations/*` variables from + `figma_get_variable_defs`: + - **Three-layer DROP_SHADOW** (umbra + penumbra + ambient, `Elevations/Shadow 01-03`) → **Material** + - **Single-layer DROP_SHADOW** → Indigo, Fluent, or Bootstrap +4. **Palette shade naming** — variables named `primary/500`, `primary/100`–`primary/900` + follow the Material 100–900 convention → likely **Material**. +5. **Visual heuristics** (use only when all above are inconclusive) — see the + [Design System Detection table](#design-system-detection-from-figma) below. + +> **Never use font name as a primary signal.** "Titillium Web" is the default body font +> in the Indigo.Design UI Kit for Material — it is not exclusive to any single kit variant. + +All four kit variants share the same variable naming conventions described below. The Ignite UI theming system uses Figma variable collections that mirror its own token structure: + +``` +Primitives collection → raw palette values (e.g. blue/500 = #6200EE) +Semantic collection → role-based aliases (e.g. color/primary = alias → blue/500) +Component collection → per-component overrides (e.g. button/background = alias → color/primary) +``` + +The `figma_get_variable_defs` response returns a flat map of resolved variable names to values. Use the sections below to identify which variables map to which theming inputs. + +--- + +## Global Palette Mapping + +### Primary Color + +| Figma Variable Pattern | Theming Input | Notes | +| ---------------------- | ------------------------------------- | --------------------------------------- | +| `color/primary` | `primary` in `theming_create_palette` | Use the resolved hex value | +| `primary/500` | `primary` | The 500 shade is the seed color | +| `Primary/Default` | `primary` | Alternative naming in some kit versions | +| `palette/primary/500` | `primary` | Prefixed naming pattern | + +> **Parameter names:** `theming_create_palette` uses `primary`, `secondary`, `surface` +> (short names). `theming_create_theme` uses `primaryColor`, `secondaryColor`, +> `surfaceColor` (long names). Do **not** mix them up. + +### Secondary / Accent Color + +| Figma Variable Pattern | Theming Input | Notes | +| ---------------------- | --------------------------------------- | ---------------------------------- | +| `color/secondary` | `secondary` in `theming_create_palette` | — | +| `secondary/500` | `secondary` | — | +| `Secondary/Default` | `secondary` | — | +| `color/accent` | `secondary` | Some kit variants call it "accent" | + +### Surface / Background Color + +| Figma Variable Pattern | Theming Input | Notes | +| ---------------------- | ------------------------------------- | ------------------- | +| `color/surface` | `surface` in `theming_create_palette` | The main background | +| `surface/default` | `surface` | — | +| `Surface` | `surface` | — | +| `color/background` | `surface` | Alternative naming | + +### Gray / Neutral Palette + +The Ignite UI theming system derives the gray scale automatically from the surface color. +You do **not** need to pass gray values to `theming_create_palette` explicitly unless you +need a custom gray family. If the Figma file has explicit gray variables, compare them +against the auto-generated palette after calling `theming_create_palette` and only add +a custom gray override if they differ significantly. + +### Semantic Status Colors + +| Figma Variable Pattern | Theming Input | Notes | +| -------------------------------- | ------------------------------------------ | -------- | +| `color/success` or `success/500` | `successColor` in `theming_create_palette` | Optional | +| `color/warning` or `warning/500` | `warningColor` in `theming_create_palette` | Optional | +| `color/error` or `error/500` | `errorColor` in `theming_create_palette` | Optional | +| `color/info` or `info/500` | `infoColor` in `theming_create_palette` | Optional | + +--- + +## Typography Mapping + +| Figma Variable Pattern | Theming Input | Notes | +| -------------------------------- | --------------------------------------------------- | ------------------------------------- | +| `typography/font-family` | `fontFamily` in `theming_create_typography` | Primary font | +| `typography/body/font-family` | `fontFamily` | Body font family | +| `typography/heading/font-family` | `fontFamily` | Use if heading font differs from body | +| `font/primary` | `fontFamily` | Alternative naming | +| `font/display` | Pass as `displayFontFamily` if the tool supports it | Display/headline font | + +> **fontFamily double-quote bug:** `theming_create_theme` may double-wrap the fontFamily +> string in its Sass output, producing invalid Sass such as `""'Titillium Web', sans-serif""`. +> If you see this pattern, strip the outer quotes before applying to `styles.scss`: +> +> ```scss +> // BAD (generated with bug) +> $font-family: +> '' 'Titillium Web', +> sans-serif ''; +> // GOOD (manually corrected) +> $font-family: 'Titillium Web', sans-serif; +> ``` + +> **Comma-separated font families** must be wrapped in parentheses when used in Sass +> typography mixins: +> +> ```scss +> // BAD — parsed as multiple Sass arguments +> @include typography($font-family: 'Roboto', 'Arial', sans-serif); +> // GOOD +> @include typography( +> $font-family: ( +> 'Roboto', +> 'Arial', +> sans-serif, +> ) +> ); +> ``` + +--- + +## Spacing, Sizing, and Roundness — Do Not Map Directly + +> **These Ignite UI theming tools are NOT equivalent to Figma spacing values.** +> Do not create a mapping between Figma pixel values and these tools. + +`theming_set_spacing` and `theming_set_roundness` accept **multipliers**, not pixel values. Passing a Figma `spacing/md = 16` as `theming_set_spacing({ spacing: 16 })` would produce a 1600% increase over the default — a catastrophic result. + +`theming_set_size` accepts a **density enum** (`small`, `medium`, `large`) — it controls how tightly packed components render, not a pixel measurement. + +### When to touch these tools (sparingly) + +| Tool | Use only when | Never use because | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `theming_set_size` | The Figma design clearly and consistently uses a noticeably tighter or looser component density than the design system default — e.g. a data-dense admin UI vs a spacious marketing page | A Figma spacing variable happens to match the name "compact" | +| `theming_set_spacing` | Explicitly requested by the user or required to match a very specific density contract; default (1.0) should be the starting point | A Figma `spacing/*` pixel value looks similar to the multiplier number | +| `theming_set_roundness` | The entire app has a clearly distinct border-radius language from the design system default (e.g. fully squared off vs fully rounded) | A Figma `border-radius/md = 8` maps numerically to the multiplier | + +### The correct adjustment path + +When a specific component needs tighter or looser density or spacing, scope `--ig-size` +and `--ig-spacing` to that component’s selector — not raw CSS overrides, not +`::ng-deep`. Both `theming_set_size` and `theming_set_spacing` accept a `component` +parameter that generates exactly this scoped output: + +``` +// Scoped size for one component type +theming_set_size({ component: "calendar", size: "small", platform: "angular" }) +// → igx-calendar { --ig-size: var(--ig-size-small); } + +// Scoped spacing: 0.75 = 75% of default +theming_set_spacing({ component: "calendar", spacing: 0.75, platform: "angular" }) +// → igx-calendar { --ig-spacing: 0.75; } +``` + +For compound components, scope to a sub-component selector via the `scope` parameter: + +``` +theming_set_size({ scope: "igx-grid-toolbar", size: "small", platform: "angular" }) +``` + +Or set the CSS custom properties directly in SCSS: + +```scss +igx-calendar { + --ig-size: var(--ig-size-small); + --ig-spacing: 0.75; +} +``` + +The Indigo.Design kit’s component proportions are already calibrated for each design +system; start from the defaults and only adjust when there is a clear visual reason. + +--- + +## Light vs Dark Mode Detection + +Detect from the Figma artboard: + +| Figma Signal | Action | +| -------------------------------------------------------- | ---------------------------------------------------------------------- | +| Dark artboard background (`#121212`, `#1a1a1a`, similar) | Use `variant: "dark"` in `theming_create_theme` | +| Light artboard background (`#fff`, `#f5f5f5`, similar) | Use `variant: "light"` in `theming_create_theme` | +| Multiple artboards — one light, one dark | Generate both theme variants with a `prefers-color-scheme` media query | +| `color/mode` variable present | Its value (`light` or `dark`) is the authoritative signal | + +--- + +## Design System Detection from Figma + +| Figma Visual Signal | Likely Design System | `designSystem` Value | +| ------------------------------------------------------------------ | -------------------------- | ----------------------- | +| Three-layer `DROP_SHADOW` on elevation variables (`Shadow 01-03`) | Material Design | `"material"` | +| Prominent single-layer shadows, rounded cards, ripple effects | Material Design | `"material"` | +| Flat surfaces, sharp corners, Segoe/Inter font | Microsoft Fluent | `"fluent"` | +| Component borders, Bootstrap-like grid | Bootstrap | `"bootstrap"` | +| Heavy use of purple/indigo accents, rounded corners, single shadow | Infragistics Indigo | `"indigo"` | +| `primary/500`, `primary/900` palette shade naming | Material (100–900 palette) | `"material"` | +| Explicit `$light-material-schema` or similar in Figma descriptions | Match the schema name | Use corresponding value | + +--- + +## Per-Component Token Resolution + +For each Ignite UI Angular component you use, follow this lookup order: + +### Step 1: Discover component tokens + +``` +theming_get_component_design_tokens({ component: "" }) +``` + +The result lists every available token with its name, type, and description. + +### Step 2: Match Figma variables to token names + +The **Indigo.Design UI Kits** use component-level variables that follow the pattern: + +``` +// +``` + +Examples: + +- `button/background` → token `background` in the button component +- `button/foreground` or `button/text-color` → token `foreground-color` +- `chip/background/selected` → token `selected-chip-color` +- `grid/header-background` → token `header-background` +- `navbar/background` → token `background` + +**Lookup process:** + +1. Take the Figma variable name (e.g. `button/background`) +2. Strip the component prefix (`background`) +3. Match it against the token list from `theming_get_component_design_tokens` +4. If no exact match, find the token whose description mentions the same visual role + +### Step 3: Common component token patterns + +| Component | Figma Variable | Likely Token Name | Notes | +| --------- | -------------------------- | ----------------------- | ----------------------- | +| Button | `button/background` | `background` | For `contained` variant | +| Button | `button/foreground` | `foreground-color` | Text color | +| Button | `button/border` | `border-color` | For `outlined` variant | +| Chip | `chip/background` | `background` | Default state | +| Chip | `chip/selected-background` | `selected-chip-color` | — | +| Grid | `grid/header/background` | `header-background` | — | +| Grid | `grid/row/background` | `content-background` | — | +| Grid | `grid/row/hover` | `row-hover-background` | — | +| Navbar | `navbar/background` | `background` | — | +| Input | `input/background` | `box-background` | Box/filled variant | +| Input | `input/border` | `border-color` | Line/border variant | +| Card | `card/background` | `background` | — | +| Card | `card/border` | `border-color` | — | +| List | `list/item/background` | `item-background` | — | +| List | `list/item/hover` | `item-hover-background` | — | +| Dialog | `dialog/background` | `background` | — | + +### Step 4: Generate component theme + +Pass **only tokens that differ from the global theme** to avoid over-specification: + +``` +theming_create_component_theme({ + component: "", + platform: "angular", + licensed: , + tokens: { + "background": "", + "foreground-color": "" + // only include tokens whose value differs from the generated global palette + } +}) +``` + +Apply the result using the `@include tokens()` call returned by the tool. + +--- + +## Variable Resolution Priority + +When multiple Figma variables could map to the same theming input, use this priority: + +1. **Component-scoped variable** (e.g. `button/background`) → per-component token +2. **Semantic role variable** (e.g. `color/primary`) → global palette input +3. **Primitive variable** (e.g. `primary/500`) → global palette seed color +4. **Raw hex/rgb value** (no variable) → extract directly from the design context + +--- + +## What to Skip + +Do **not** call theming tools for: + +- Chart, gauge, and map DV components → configure via component `[input]` bindings only +- Tile Manager and Dock Manager → these are web components with their own CSS custom properties +- Pure layout CSS (margins, grid columns, flex gaps) → write directly in SCSS +- Icon SVG fill colors → use `color` CSS property or the custom `--foreground` CSS property on the `igx-icon` host or its parent diff --git a/skills/igniteui-angular-figma-to-app/references/figma-component-map.md b/skills/igniteui-angular-figma-to-app/references/figma-component-map.md new file mode 100644 index 00000000000..49f5eeaee00 --- /dev/null +++ b/skills/igniteui-angular-figma-to-app/references/figma-component-map.md @@ -0,0 +1,306 @@ +# Indigo.Design UI Kit → Ignite UI Angular Component Map + +> **Part of the [`igniteui-angular-figma-to-app`](../SKILL.md) skill.** +> +> The **Indigo.Design UI Kits** are Figma component libraries (Material, Fluent, Bootstrap, +> Indigo variants) that designers use to build their app screens. Every component instance +> in a design file is drawn from one of these libraries and maps 1:1 to an Ignite UI +> Angular control. +> +> Use this file in Phase 2a to map Figma layer names — as they appear in the kit +> library — to Ignite UI Angular selectors, `get_doc` keys, and key inputs. When a +> layer name is not in this table, call `list_components` then `get_doc` on the closest +> match. + +--- + +## How to Use This File + +1. Find the kit component name (as it appears in the Figma layers panel or the + Indigo.Design kit library) in the **Kit Component Name** column. +2. Read the **Angular Selector** and **IgxXxx Class** for the template. +3. Use the **`get_doc` Key** to call `get_doc({ framework: "angular", name: "" })` + before writing any code. +4. Consult **Key Inputs / Variants** for the properties most commonly configured from + Figma variants. + +> The component names are identical across all four kit variants (Material, Fluent, +> Bootstrap, Indigo). The kit variant determines the theme style, not the component name. + +--- + +## Button Components + +| Kit Component Name | Angular Selector | IgxXxx Class | `get_doc` Key | Key Inputs / Variants | +| -------------------------------------- | ------------------------------------ | ------------------------- | -------------- | ---------------------------------------------------------- | +| `_Button/Flat` | `