igniteui-webcomponents 7.4.0 → 7.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/components/checkbox/checkbox-base.d.ts +2 -0
  3. package/components/checkbox/checkbox-base.js +4 -0
  4. package/components/checkbox/checkbox-base.js.map +1 -1
  5. package/components/checkbox/checkbox.js +3 -11
  6. package/components/checkbox/checkbox.js.map +1 -1
  7. package/components/checkbox/switch.js +1 -8
  8. package/components/checkbox/switch.js.map +1 -1
  9. package/components/color-picker/color-picker.js +3 -3
  10. package/components/color-picker/color-picker.js.map +1 -1
  11. package/components/combo/combo.d.ts +6 -4
  12. package/components/combo/combo.js +13 -24
  13. package/components/combo/combo.js.map +1 -1
  14. package/components/date-picker/date-picker.base.d.ts +3 -3
  15. package/components/date-picker/date-picker.base.js +2 -2
  16. package/components/date-picker/date-picker.base.js.map +1 -1
  17. package/components/date-picker/date-picker.d.ts +1 -1
  18. package/components/date-range-picker/date-range-picker.d.ts +1 -1
  19. package/components/date-time-input/date-time-input.base.d.ts +4 -4
  20. package/components/date-time-input/date-time-input.base.js +3 -5
  21. package/components/date-time-input/date-time-input.base.js.map +1 -1
  22. package/components/file-input/file-input.d.ts +5 -0
  23. package/components/file-input/file-input.js +4 -0
  24. package/components/file-input/file-input.js.map +1 -1
  25. package/components/input/input-base.d.ts +2 -2
  26. package/components/input/input-base.js +3 -5
  27. package/components/input/input-base.js.map +1 -1
  28. package/components/input/input.d.ts +1 -1
  29. package/components/radio/radio.d.ts +2 -0
  30. package/components/radio/radio.js +7 -11
  31. package/components/radio/radio.js.map +1 -1
  32. package/components/rating/rating.d.ts +3 -0
  33. package/components/rating/rating.js +17 -18
  34. package/components/rating/rating.js.map +1 -1
  35. package/components/select/select.js +1 -1
  36. package/components/select/select.js.map +1 -1
  37. package/components/slider/range-slider.d.ts +0 -1
  38. package/components/slider/range-slider.js +6 -11
  39. package/components/slider/range-slider.js.map +1 -1
  40. package/components/slider/slider-base.d.ts +4 -1
  41. package/components/slider/slider-base.js +20 -18
  42. package/components/slider/slider-base.js.map +1 -1
  43. package/components/slider/slider.d.ts +2 -0
  44. package/components/slider/slider.js +5 -1
  45. package/components/slider/slider.js.map +1 -1
  46. package/components/textarea/textarea.d.ts +1 -4
  47. package/components/textarea/textarea.js +3 -5
  48. package/components/textarea/textarea.js.map +1 -1
  49. package/components/validation-container/validation-container.js +2 -1
  50. package/components/validation-container/validation-container.js.map +1 -1
  51. package/components/virtualization/engine.d.ts +35 -4
  52. package/components/virtualization/engine.js +126 -61
  53. package/components/virtualization/engine.js.map +1 -1
  54. package/components/virtualization/recycle.d.ts +13 -0
  55. package/components/virtualization/recycle.js +152 -0
  56. package/components/virtualization/recycle.js.map +1 -0
  57. package/components/virtualization/virtualization.d.ts +32 -11
  58. package/components/virtualization/virtualization.js +14 -11
  59. package/components/virtualization/virtualization.js.map +1 -1
  60. package/custom-elements.json +2382 -79
  61. package/igniteui-webcomponents.html-data.json +1 -1
  62. package/index.d.ts +1 -1
  63. package/index.js.map +1 -1
  64. package/internals/controllers/aria-projection.d.ts +61 -23
  65. package/internals/controllers/aria-projection.js +77 -26
  66. package/internals/controllers/aria-projection.js.map +1 -1
  67. package/internals/mixins/forms/associated.js +34 -0
  68. package/internals/mixins/forms/associated.js.map +1 -1
  69. package/internals/mixins/forms/types.d.ts +5 -0
  70. package/internals/mixins/forms/types.js.map +1 -1
  71. package/internals/templates/toggle-shell.d.ts +15 -14
  72. package/internals/templates/toggle-shell.js +12 -8
  73. package/internals/templates/toggle-shell.js.map +1 -1
  74. package/internals/utils/dom.d.ts +2 -2
  75. package/internals/utils/dom.js +2 -2
  76. package/internals/utils/dom.js.map +1 -1
  77. package/package.json +1 -1
  78. package/skills/README.md +2 -4
  79. package/skills/igniteui-wc-choose-components/SKILL.md +2 -1
  80. package/skills/igniteui-wc-customize-component-theme/SKILL.md +2 -1
  81. package/skills/igniteui-wc-figma-to-app/SKILL.md +133 -712
  82. package/skills/igniteui-wc-figma-to-app/references/asset-extraction.md +42 -62
  83. package/skills/igniteui-wc-figma-to-app/references/design-provenance.md +199 -0
  84. package/skills/igniteui-wc-figma-to-app/references/design-token-bridge.md +189 -107
  85. package/skills/igniteui-wc-figma-to-app/references/figma-component-map.md +129 -84
  86. package/skills/igniteui-wc-figma-to-app/references/figma-exploration.md +222 -0
  87. package/skills/igniteui-wc-figma-to-app/references/mcp-setup.md +81 -127
  88. package/skills/igniteui-wc-figma-to-app/references/project-setup.md +105 -0
  89. package/skills/igniteui-wc-figma-to-app/references/theme-generation.md +180 -0
  90. package/skills/igniteui-wc-figma-to-app/references/validation-patterns.md +74 -80
  91. package/skills/igniteui-wc-generate-from-image-design/SKILL.md +2 -1
  92. package/skills/igniteui-wc-generate-from-image-design/references/gotchas.md +3 -3
  93. package/skills/igniteui-wc-grids/SKILL.md +133 -0
  94. package/skills/igniteui-wc-integrate-with-framework/SKILL.md +2 -1
  95. package/skills/igniteui-wc-migrate-grid-lite-to-premium/SKILL.md +2 -1
  96. package/skills/igniteui-wc-optimize-bundle-size/SKILL.md +2 -1
  97. package/web-types.json +1 -1
@@ -2,21 +2,15 @@
2
2
 
3
3
  > **Part of the [`igniteui-wc-figma-to-app`](../SKILL.md) skill.**
4
4
  >
5
- > Use this file in Phase 5 for the measurement-driven validation loop. Read it in full
6
- > before calling any Playwright tool.
5
+ > Use this file in Phase 5 for the measurement-driven validation loop. Read it in full before calling any Playwright tool.
7
6
 
8
7
  ---
9
8
 
10
9
  ## Core Philosophy
11
10
 
12
- **Measure, don't eyeball.** The goal is not visual regression (did this change since last
13
- week?) but design fidelity (does this match the Figma spec?). Screenshots give you the
14
- gestalt; `playwright_browser_evaluate` gives you the numbers; numbers drive corrections.
11
+ **Measure, don't eyeball.** The goal is not visual regression (did this change since last week?) but design fidelity (does this match the Figma spec?). Screenshots give you the gestalt; `playwright_browser_evaluate` gives you the numbers; numbers drive corrections.
15
12
 
16
- **The Web Components twist:** almost everything you want to measure lives inside a shadow
17
- root. `document.querySelector('igc-card .title')` returns `null` — not because the element
18
- is missing, but because the selector cannot cross the boundary. Every snippet below is
19
- shadow-aware. Use them instead of writing ad-hoc selectors.
13
+ **The Web Components twist:** almost everything you want to measure lives inside a shadow root. `document.querySelector('igc-card .title')` returns `null` — not because the element is missing, but because the selector cannot cross the boundary. Every snippet below is shadow-aware and inlines the helpers it uses. Use them instead of writing ad-hoc selectors. A view built as a Lit component is itself a shadow root, so reach its content with a `host >>> selector` path (e.g. `app-dashboard >>> .kpi-card`).
20
14
 
21
15
  ---
22
16
 
@@ -30,16 +24,16 @@ shadow-aware. Use them instead of writing ad-hoc selectors.
30
24
  5. playwright_browser_evaluate → registration + theme audit (fail fast)
31
25
  6. playwright_browser_take_screenshot → capture the full viewport
32
26
  7. [Visual comparison] → against the Phase 1c reference, section by section
33
- 8. playwright_browser_evaluate → measure EVERY section in the Phase 1g Surfaces table
27
+ 8. playwright_browser_evaluate → measure EVERY section in the Phase 1g Table B (Layout Surfaces)
34
28
  9. [Surfaces audit] → assert background, radius, padding, border
35
29
  10. [Action controls audit] → count and name every control, shadow roots included
36
30
  11. [Input variant audit] → check `outlined` against the Phase 1d variant
37
31
  12. [Classify mismatches] → severity table
38
32
  13. [Apply fixes] → edit source files
39
33
  14. playwright_browser_navigate → reload after fixes
40
- 15. Repeat 6–14 until no Critical/Major issues remain
41
- 16. Do NOT advance to the next artboard until all checks pass on this one
42
- 17. playwright_browser_snapshot → final accessibility check
34
+ 15. Repeat 6–14 until the exit condition below is met (only Cosmetic and Accepted items left)
35
+ 16. Do NOT advance to the next artboard until then
36
+ 17. playwright_browser_snapshot → accessibility check for this view (once per artboard)
43
37
  ```
44
38
 
45
39
  ---
@@ -48,8 +42,7 @@ shadow-aware. Use them instead of writing ad-hoc selectors.
48
42
 
49
43
  ### 1. Viewport reset after resize
50
44
 
51
- After `playwright_browser_resize`, the browser may navigate itself to `about:blank`, and
52
- subsequent screenshots and measurements come back empty.
45
+ After `playwright_browser_resize`, the browser may navigate itself to `about:blank`, and subsequent screenshots and measurements come back empty.
53
46
 
54
47
  ```
55
48
  playwright_browser_resize({ width: 1440, height: 900 })
@@ -71,19 +64,17 @@ playwright_browser_evaluate({ function: "() => document.title" })
71
64
 
72
65
  ### 3. Measuring before the components have upgraded
73
66
 
74
- Custom elements upgrade asynchronously, and Lit renders on a microtask. Measuring too early
75
- returns pre-upgrade box metrics (often `height: 0`). Wait for definition and render:
67
+ Custom elements upgrade asynchronously, and Lit renders on a microtask. Measuring too early returns pre-upgrade box metrics (often `height: 0`). Wait for the registered elements to render. The snippet only waits on tags that are already defined, with a 3-second cap, so an unregistered tag cannot hang it; it is returned in `undefinedTags` instead:
76
68
 
77
69
  ```
78
70
  playwright_browser_evaluate({
79
- function: "async () => { const tags = [...new Set([...document.querySelectorAll('*')].map(e => e.tagName.toLowerCase()).filter(t => t.startsWith('igc-')))]; await Promise.all(tags.map(t => customElements.whenDefined(t))); const els = [...document.querySelectorAll('*')].filter(e => e.tagName.startsWith('IGC-')); await Promise.all(els.map(e => e.updateComplete).filter(Boolean)); await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); return { upgraded: tags.length }; }"
71
+ function: "async () => { const deepQueryAll = (sel, root = document) => { const out = []; const walk = (node) => { out.push(...node.querySelectorAll(sel)); node.querySelectorAll('*').forEach(el => el.shadowRoot && walk(el.shadowRoot)); }; walk(root); return out; }; const els = deepQueryAll('*').filter(e => e.tagName.startsWith('IGC-')); const tags = [...new Set(els.map(e => e.tagName.toLowerCase()))]; const undefinedTags = tags.filter(t => !customElements.get(t)); const timeout = new Promise(r => setTimeout(r, 3000)); await Promise.race([Promise.all(els.filter(e => customElements.get(e.tagName.toLowerCase())).map(e => e.updateComplete).filter(Boolean)), timeout]); await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); return { upgraded: tags.length - undefinedTags.length, undefinedTags }; }"
80
72
  })
81
73
  ```
82
74
 
83
75
  ### 4. An unregistered element fails silently
84
76
 
85
- A missing `defineComponents(...)` produces **no console error** — the tag renders as an
86
- empty inline box. Run the registration audit before blaming CSS.
77
+ A missing `defineComponents(...)` produces **no console error** — the tag renders as an empty inline box. Run the registration audit before blaming CSS.
87
78
 
88
79
  ### 5. Dev server must be running
89
80
 
@@ -92,18 +83,16 @@ playwright_browser_navigate({ url: "http://localhost:5173" })
92
83
  playwright_browser_console_messages()
93
84
  ```
94
85
 
95
- `ERR_CONNECTION_REFUSED` or a blank page means the Vite dev server is not running — ask the
96
- user to run `npm start`. Note the port: Vite defaults to **5173**.
86
+ `ERR_CONNECTION_REFUSED` or a blank page means the Vite dev server is not running — ask the user to run `npm start`. Note the port: Vite defaults to **5173**.
97
87
 
98
88
  ---
99
89
 
100
90
  ## The Deep-Query Helper
101
91
 
102
- Every measurement snippet below assumes this helper. It walks shadow roots, so a selector
103
- like `igc-card >>> [part="header"]` resolves.
92
+ Every measurement snippet below assumes this helper. It walks shadow roots, so a selector like `igc-card >>> [part="header"]` resolves.
104
93
 
105
94
  ```javascript
106
- // Paste as the first statements of any evaluate() function.
95
+ // Every snippet below already inlines the helpers it uses. Paste these into new snippets.
107
96
  const deepQuery = (path, root = document) =>
108
97
  path.split('>>>').map(s => s.trim()).reduce(
109
98
  (node, sel) => node && (node.shadowRoot || node).querySelector(sel),
@@ -122,10 +111,7 @@ const deepQueryAll = (sel, root = document) => {
122
111
  };
123
112
  ```
124
113
 
125
- Prefer measuring the **host element** (`igc-card`) for box metrics — width, height,
126
- position, margin — and pierce only for internals that the design calls out (header height,
127
- row padding). When you must pierce, target documented `::part(...)` names from `get_doc`,
128
- never internal class names.
114
+ Prefer measuring the **host element** (`igc-card`) for box metrics — width, height, position, margin — and pierce only for internals that the design calls out (header height, row padding). When you must pierce, target documented `::part(...)` names from `get_doc`, never internal class names.
129
115
 
130
116
  ---
131
117
 
@@ -137,13 +123,11 @@ All snippets use the `function` parameter.
137
123
 
138
124
  ```
139
125
  playwright_browser_evaluate({
140
- function: "() => { const tags = [...new Set(deepQueryAll('*').map(e => e.tagName.toLowerCase()).filter(t => t.startsWith('igc-')))]; const undefinedTags = tags.filter(t => !customElements.get(t)); const s = getComputedStyle(document.documentElement); return { tags, undefinedTags, theme: s.getPropertyValue('--ig-theme').trim(), variant: s.getPropertyValue('--ig-theme-variant').trim(), primary500: s.getPropertyValue('--ig-primary-500').trim(), surface500: s.getPropertyValue('--ig-surface-500').trim(), fontFamily: s.getPropertyValue('--ig-font-family').trim() }; }"
126
+ function: "() => { const deepQueryAll = (sel, root = document) => { const out = []; const walk = (node) => { out.push(...node.querySelectorAll(sel)); node.querySelectorAll('*').forEach(el => el.shadowRoot && walk(el.shadowRoot)); }; walk(root); return out; }; const tags = [...new Set(deepQueryAll('*').map(e => e.tagName.toLowerCase()).filter(t => t.startsWith('igc-')))]; const undefinedTags = tags.filter(t => !customElements.get(t)); const s = getComputedStyle(document.documentElement); return { tags, undefinedTags, theme: s.getPropertyValue('--ig-theme').trim(), variant: s.getPropertyValue('--ig-theme-variant').trim(), primary500: s.getPropertyValue('--ig-primary-500').trim(), surface500: s.getPropertyValue('--ig-surface-500').trim(), fontFamily: s.getPropertyValue('--ig-font-family').trim() }; }"
141
127
  })
142
128
  ```
143
129
 
144
- Assert: `undefinedTags` is empty; `theme` and `variant` match the design system and variant
145
- resolved in Phase 3. An empty `theme` means no theme CSS is loaded — components silently
146
- fall back to `bootstrap` / `light`.
130
+ Assert: `undefinedTags` is empty; `theme` and `variant` match the design system and variant resolved in Phase 3. An empty `theme` means no theme CSS is loaded — components silently fall back to `bootstrap` / `light`.
147
131
 
148
132
  ### Measure a single element (shadow-aware)
149
133
 
@@ -153,14 +137,13 @@ playwright_browser_evaluate({
153
137
  })
154
138
  ```
155
139
 
156
- > A host element with `display: inline` (the Lit default) reports a misleading box. If width
157
- > or height look wrong, check for a missing `:host { display: block }` before chasing padding.
140
+ > A host element with `display: inline` (the Lit default) reports a misleading box. If width or height look wrong, check for a missing `:host { display: block }` before chasing padding.
158
141
 
159
142
  ### Surfaces audit (mandatory — every page, every Phase 1g surface)
160
143
 
161
144
  ```
162
145
  playwright_browser_evaluate({
163
- function: "() => { const sections = { /* fill from the Phase 1g Surfaces table */ sectionA: '.section-a', sectionB: '.section-b' }; const deepQuery = (path, root = document) => path.split('>>>').map(s => s.trim()).reduce((n, sel) => n && (n.shadowRoot || n).querySelector(sel), root); const out = {}; for (const [key, sel] of Object.entries(sections)) { const el = deepQuery(sel); if (!el) { out[key] = 'NOT FOUND'; continue; } const s = getComputedStyle(el); const r = el.getBoundingClientRect(); out[key] = { bg: s.backgroundColor, radius: s.borderRadius, padding: s.padding, border: s.border, shadow: s.boxShadow, w: Math.round(r.width), h: Math.round(r.height) }; } return out; }"
146
+ function: "() => { const sections = { /* fill from the Phase 1g Table B */ sectionA: '.section-a', sectionB: '.section-b' }; const deepQuery = (path, root = document) => path.split('>>>').map(s => s.trim()).reduce((n, sel) => n && (n.shadowRoot || n).querySelector(sel), root); const out = {}; for (const [key, sel] of Object.entries(sections)) { const el = deepQuery(sel); if (!el) { out[key] = 'NOT FOUND'; continue; } const s = getComputedStyle(el); const r = el.getBoundingClientRect(); out[key] = { bg: s.backgroundColor, radius: s.borderRadius, padding: s.padding, border: s.border, shadow: s.boxShadow, w: Math.round(r.width), h: Math.round(r.height) }; } return out; }"
164
147
  })
165
148
  ```
166
149
 
@@ -179,41 +162,33 @@ playwright_browser_evaluate({
179
162
  })
180
163
  ```
181
164
 
182
- Compare against the Phase 1d inventory. Any control not in the design context output is
183
- fabricated and must be removed. `(unlabeled)` entries are also an accessibility failure —
184
- icon-only buttons need `aria-label`.
165
+ Compare against the Phase 1d inventory. Any control not in the design context output is fabricated and must be removed. `(unlabeled)` entries are also an accessibility failure — icon-only buttons need `aria-label`.
185
166
 
186
167
  ### Input variant audit (every page with form controls)
187
168
 
188
169
  ```
189
170
  playwright_browser_evaluate({
190
- function: "() => { const tags = ['igc-input','igc-textarea','igc-mask-input','igc-date-time-input','igc-file-input','igc-select','igc-combo','igc-date-picker','igc-date-range-picker']; const out = {}; tags.forEach(t => { const els = deepQueryAll(t); if (els.length) out[t] = { count: els.length, outlined: els.filter(e => e.hasAttribute('outlined')).length }; }); return out; }"
171
+ function: "() => { const deepQueryAll = (sel, root = document) => { const out = []; const walk = (node) => { out.push(...node.querySelectorAll(sel)); node.querySelectorAll('*').forEach(el => el.shadowRoot && walk(el.shadowRoot)); }; walk(root); return out; }; const tags = ['igc-input','igc-textarea','igc-mask-input','igc-date-time-input','igc-file-input','igc-select','igc-combo','igc-date-picker','igc-date-range-picker']; const out = {}; tags.forEach(t => { const els = deepQueryAll(t); if (els.length) out[t] = { count: els.length, outlined: els.filter(e => e.hasAttribute('outlined')).length }; }); return out; }"
191
172
  })
192
173
  ```
193
174
 
194
- Compare against the variant detected in Phase 1d. If the design uses border-style inputs
195
- everywhere, every control should report `outlined === count`.
175
+ Compare against the variant detected in Phase 1d. If the design uses border-style inputs everywhere, every control should report `outlined === count`.
196
176
 
197
177
  ### Property-binding audit (collection-bound charts, grids, combos)
198
178
 
199
179
  ```
200
180
  playwright_browser_evaluate({
201
- function: "() => { const defs = [ ['igc-category-chart', ['dataSource', 'data']], ['igc-data-chart', ['dataSource', 'data']], ['igc-pie-chart', ['dataSource', 'data']], ['igc-doughnut-chart', ['dataSource', 'data']], ['igc-financial-chart', ['dataSource', 'data']], ['igc-sparkline', ['dataSource', 'data']], ['igc-treemap', ['dataSource', 'data']], ['igc-funnel-chart', ['dataSource', 'data']], ['igc-grid', ['data']], ['igc-grid-lite', ['data']], ['igc-combo', ['data']] ]; const out = {}; defs.forEach(([tag, dataProps]) => { deepQueryAll(tag).forEach((el, i) => { const dataProp = dataProps.find(prop => Array.isArray(el[prop])); const brushProps = ['brushes', 'outlines'].filter(prop => Array.isArray(el[prop])); out[tag + '#' + i] = { dataLength: dataProp ? el[dataProp].length : null, brushCollections: brushProps.length ? Object.fromEntries(brushProps.map(prop => [prop, el[prop]])) : null, height: Math.round(el.getBoundingClientRect().height) }; }); }); return out; }"
181
+ function: "() => { const deepQueryAll = (sel, root = document) => { const out = []; const walk = (node) => { out.push(...node.querySelectorAll(sel)); node.querySelectorAll('*').forEach(el => el.shadowRoot && walk(el.shadowRoot)); }; walk(root); return out; }; const defs = [ ['igc-category-chart', 'dataSource', ['brushes', 'outlines']], ['igc-data-chart', 'dataSource', ['brushes', 'outlines']], ['igc-pie-chart', 'dataSource', ['brushes', 'outlines']], ['igc-financial-chart', 'dataSource', ['brushes', 'outlines']], ['igc-funnel-chart', 'dataSource', ['brushes', 'outlines']], ['igc-sparkline', 'dataSource', ['brush']], ['igc-treemap', 'dataSource', ['fillBrushes']], ['igc-grid', 'data', []], ['igc-grid-lite', 'data', []], ['igc-combo', 'data', []] ]; const out = {}; const assigned = (el, props) => props.filter(p => el[p] != null && el[p] !== ''); defs.forEach(([tag, dataProp, brushProps]) => { deepQueryAll(tag).forEach((el, i) => { const data = el[dataProp]; out[tag + '#' + i] = { dataLength: Array.isArray(data) ? data.length : null, brushes: brushProps.length ? assigned(el, brushProps) : 'n/a', height: Math.round(el.getBoundingClientRect().height) }; }); }); deepQueryAll('igc-doughnut-chart').forEach((el, i) => { const series = [...el.querySelectorAll('igc-ring-series')]; out['igc-doughnut-chart#' + i] = { series: series.map(s => ({ dataLength: Array.isArray(s.dataSource) ? s.dataSource.length : null, brushes: assigned(s, ['brushes', 'outlines']) })), height: Math.round(el.getBoundingClientRect().height) }; }); return out; }"
202
182
  })
203
183
  ```
204
184
 
205
- `dataLength: null` means the collection was set as an attribute (or not at all) instead of
206
- as a property. `brushCollections: null` on a chart means none of its documented
207
- `brushes` / `outlines` arrays were assigned, so it is still using the default palette instead
208
- of the Figma series colors. `height: 0` means the element or its grid track has no height.
209
- Use this audit for the collection-bound host tags in the selected plan; gauges and maps need
210
- their own host-specific validation once you know which properties the chosen component binds.
185
+ `dataLength: null` means the collection was set as an attribute (or not at all) instead of as a property. An empty `brushes` list on a chart means no series colors were assigned, so it is still using the default palette instead of the Figma series colors. The brush members differ per chart: `brushes` / `outlines` on most charts, `brush` on `igc-sparkline`, `fillBrushes` on `igc-treemap`, and `brushes` / `outlines` on each `igc-ring-series` child of `igc-doughnut-chart` (not on the host). `height: 0` means the element or its grid track has no height. Use this audit for the collection-bound host tags in the selected plan; gauges and maps need their own host-specific validation once you know which properties the chosen component binds.
211
186
 
212
187
  ### Measure the gap between two elements
213
188
 
214
189
  ```
215
190
  playwright_browser_evaluate({
216
- function: "() => { const a = document.querySelector('<SELECTOR_A>'); const b = document.querySelector('<SELECTOR_B>'); if (!a || !b) return { error: 'one or both elements not found' }; const ra = a.getBoundingClientRect(); const rb = b.getBoundingClientRect(); return { gapBetween: Math.round(rb.top - ra.bottom), aHeight: Math.round(ra.height), bTop: Math.round(rb.top) }; }"
191
+ function: "() => { const deepQuery = (path, root = document) => path.split('>>>').map(s => s.trim()).reduce((n, sel) => n && (n.shadowRoot || n).querySelector(sel), root); const a = deepQuery('<SELECTOR_A>'); const b = deepQuery('<SELECTOR_B>'); if (!a || !b) return { error: 'one or both elements not found' }; const ra = a.getBoundingClientRect(); const rb = b.getBoundingClientRect(); return { gapBetween: Math.round(rb.top - ra.bottom), aHeight: Math.round(ra.height), bTop: Math.round(rb.top) }; }"
217
192
  })
218
193
  ```
219
194
 
@@ -221,7 +196,7 @@ playwright_browser_evaluate({
221
196
 
222
197
  ```
223
198
  playwright_browser_evaluate({
224
- function: "() => { const sels = ['h1','h2','h3','p','.subtitle','.caption']; const out = {}; sels.forEach(sel => { const el = document.querySelector(sel); if (el) { const s = getComputedStyle(el); out[sel] = { fontSize: s.fontSize, fontWeight: s.fontWeight, lineHeight: s.lineHeight, fontFamily: s.fontFamily }; } }); return out; }"
199
+ function: "() => { const deepQueryAll = (sel, root = document) => { const out = []; const walk = (node) => { out.push(...node.querySelectorAll(sel)); node.querySelectorAll('*').forEach(el => el.shadowRoot && walk(el.shadowRoot)); }; walk(root); return out; }; const sels = ['h1','h2','h3','p','.subtitle','.caption']; const out = {}; sels.forEach(sel => { const el = deepQueryAll(sel)[0]; if (el) { const s = getComputedStyle(el); out[sel] = { fontSize: s.fontSize, fontWeight: s.fontWeight, lineHeight: s.lineHeight, fontFamily: s.fontFamily }; } }); return out; }"
225
200
  })
226
201
  ```
227
202
 
@@ -229,7 +204,7 @@ playwright_browser_evaluate({
229
204
 
230
205
  ```
231
206
  playwright_browser_evaluate({
232
- function: "() => { const el = document.querySelector('<LAYOUT_CONTAINER>'); if (!el) return { error: 'layout container not found' }; const s = getComputedStyle(el); return { display: s.display, gridTemplateColumns: s.gridTemplateColumns, gridTemplateRows: s.gridTemplateRows, gap: s.gap, width: Math.round(el.getBoundingClientRect().width) }; }"
207
+ function: "() => { const deepQuery = (path, root = document) => path.split('>>>').map(s => s.trim()).reduce((n, sel) => n && (n.shadowRoot || n).querySelector(sel), root); const el = deepQuery('<LAYOUT_CONTAINER>'); if (!el) return { error: 'layout container not found' }; const s = getComputedStyle(el); return { display: s.display, gridTemplateColumns: s.gridTemplateColumns, gridTemplateRows: s.gridTemplateRows, gap: s.gap, width: Math.round(el.getBoundingClientRect().width) }; }"
233
208
  })
234
209
  ```
235
210
 
@@ -237,12 +212,11 @@ playwright_browser_evaluate({
237
212
 
238
213
  ```
239
214
  playwright_browser_evaluate({
240
- function: "() => { const host = document.querySelector('<igc-tag>'); if (!host || !host.shadowRoot) return { error: 'host or shadow root not found' }; return [...host.shadowRoot.querySelectorAll('[part]')].map(el => ({ part: el.getAttribute('part'), bg: getComputedStyle(el).backgroundColor, color: getComputedStyle(el).color })); }"
215
+ function: "() => { const deepQuery = (path, root = document) => path.split('>>>').map(s => s.trim()).reduce((n, sel) => n && (n.shadowRoot || n).querySelector(sel), root); const host = deepQuery('<igc-tag>'); if (!host || !host.shadowRoot) return { error: 'host or shadow root not found' }; return [...host.shadowRoot.querySelectorAll('[part]')].map(el => ({ part: el.getAttribute('part'), bg: getComputedStyle(el).backgroundColor, color: getComputedStyle(el).color })); }"
241
216
  })
242
217
  ```
243
218
 
244
- Use the reported `part` names — they are the supported styling surface when a design token
245
- does not exist for a detail the design requires.
219
+ Use the reported `part` names — they are the supported styling surface when a design token does not exist for a detail the design requires.
246
220
 
247
221
  ---
248
222
 
@@ -250,17 +224,25 @@ does not exist for a detail the design requires.
250
224
 
251
225
  | Severity | Category | Decision rule | Action |
252
226
  | ------------ | -------------------------- | ----------------------------------------------------------- | --------------------------- |
253
- | **Critical** | Missing element | Present in Figma, absent from DOM | Auto-fix |
254
- | **Critical** | Unregistered component | Tag present but `customElements.get()` is undefined | Auto-fix (add registration) |
255
- | **Critical** | Broken layout | Overlapping elements, content outside bounds, zero-height | Auto-fix |
256
- | **Critical** | Wrong design system active | `--ig-theme` does not match the Phase 3 resolution | Auto-fix (theme import) |
257
- | **Major** | Wrong component | Figma shows a combo, code has a select | Auto-fix |
258
- | **Major** | Wrong variant | `variant="flat"` when the design shows contained | Auto-fix |
259
- | **Major** | Collection not bound | `data` / `dataSource` / `brushes` set as an attribute | Auto-fix |
260
- | **Minor** | Spacing off by > 4px | `gap: 24px` measured, Figma shows `16px` | Auto-fix if a single property |
261
- | **Minor** | Font size wrong by > 2px | `16px` measured, Figma shows `14px` | Auto-fix |
262
- | **Cosmetic** | Color shade | `rgb(50,50,50)` vs `#333333` (perceptually identical) | Report only |
263
- | **Cosmetic** | Spacing off by ≤ 4px | Rounding or sub-pixel difference | Report only |
227
+ | **Critical** | Missing element | Present in Figma, absent from DOM | Fix |
228
+ | **Critical** | Unregistered component | Tag present but `customElements.get()` is undefined | Fix (add registration) |
229
+ | **Critical** | Broken layout | Overlapping elements, content outside bounds, zero-height | Fix |
230
+ | **Critical** | Wrong design system active | `--ig-theme` does not match the Phase 3 resolution | Fix (theme import) |
231
+ | **Major** | Wrong component | Figma shows a combo, code has a select | Fix |
232
+ | **Major** | Wrong variant | `variant="flat"` when the design shows contained | Fix |
233
+ | **Major** | Collection not bound | `data` / `dataSource` set as an attribute, or no series brushes assigned | Fix |
234
+ | **Major** | Token-fixable mismatch | Color, radius, border, shadow, or text casing differs, or a control height differs by more than 4px, and a component token, palette seed, `--ig-size` step, or `--ig-<style>-<property>` override can close it | Fix |
235
+ | **Minor** | Spacing off by > 4px | `gap: 24px` measured, Figma shows `16px` | Fix |
236
+ | **Minor** | Font size wrong by > 2px | `16px` measured, Figma shows `14px` | Fix |
237
+ | **Cosmetic** | Color rounding | The same color after conversion: `rgb(51, 51, 51)` vs `#333333`. Any visibly different shade (`#333` vs `#2d2d2d`, a 500-vs-600 seed) is **Major** | Report only |
238
+ | **Cosmetic** | Size off by ≤ 4px | Spacing or control height within 4px, or font size within 2px, from rounding or sub-pixel layout | Report only |
239
+ | **Accepted** | Approved anatomy delta | Matches a delta-ledger entry the user approved (e.g. an M3 segmented button's check icon, a sheet rendered as a dialog) | Report only. Do not "fix" it; it does not count toward the 3-retry rule |
240
+
241
+ **Exit condition for an artboard:** no Critical, Major, or Minor issues remain. Only Cosmetic and Accepted items may be left, and both go into the final report.
242
+
243
+ > **Accepted needs the user's approval.** A delta is Accepted only after the user approves its ledger entry. Most entries come from Phase 2d. When Phase 5 finds a difference that tokens, documented `::part(...)` selectors, or slotted content cannot close, add it to the ledger and ask the user. Once they approve it, it is Accepted from then on. Until then, classify it normally, and never downgrade it silently.
244
+ >
245
+ > **Third-party kits (Path B):** color, radius, border, casing, and height mismatches are almost always fixable with component tokens or the `--ig-<style>-<property>` typography overrides. They are Major, never Accepted. Only *structural* differences (a label position the baseline cannot move, an adornment the component does not render, a behavior pattern with no equivalent) qualify for the ledger.
264
246
 
265
247
  ### Mismatch report format
266
248
 
@@ -269,20 +251,19 @@ ISSUE: <concise description of the mismatch>
269
251
  LOCATION: <component/section in the view>
270
252
  FIGMA: <value from the design context>
271
253
  RENDERED: <value measured by Playwright>
272
- SEVERITY: <Critical | Major | Minor | Cosmetic>
254
+ SEVERITY: <Critical | Major | Minor | Cosmetic | Accepted>
273
255
  FIX: <specific, one-line code change>
274
256
  ```
275
257
 
276
258
  Example:
277
259
 
278
260
  ```
279
- ISSUE: Card surface is transparent
280
- LOCATION: igc-card in the "Budget Categories" section
281
- FIGMA: background = #222222 (Surfaces table row 1)
261
+ ISSUE: Section surface is transparent
262
+ LOCATION: .budget-categories wrapper (Phase 1g Table B row "Budget Categories")
263
+ FIGMA: background = #222222
282
264
  RENDERED: backgroundColor = rgba(0, 0, 0, 0)
283
- SEVERITY: Critical
284
- FIX: create_component_theme("card", tokens: { background: "var(--ig-surface-100)" })
285
- and apply the generated block — do not set background on a wrapper div.
265
+ SEVERITY: Major
266
+ FIX: .budget-categories { background: var(--ig-surface-100); } /* the Table B values */
286
267
 
287
268
  ISSUE: Chart series colors are the default palette
288
269
  LOCATION: igc-category-chart in the "Spending" panel
@@ -300,11 +281,11 @@ FIX: chart.brushes = ['#9DE772', '#6DB1FF'] assigned as a property after va
300
281
  | Section | What to check |
301
282
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------ |
302
283
  | Top navigation | Height, background, slotted `start`/`end` content alignment, action icon positions |
303
- | Sidebar / nav drawer | Width (`--menu-full-width`), `position="relative"` vs modal, item spacing, icon + label alignment, selected state |
284
+ | Sidebar / nav drawer | Width (`--ig-nav-drawer-size`), `position="relative"` vs modal, item spacing, icon + label alignment, selected state |
304
285
  | Page header | Typography size and weight, breadcrumb spacing, action button prominence |
305
286
  | Data grid | Column widths (at least one fluid), header background, row height, cell padding, grid theme CSS actually loaded |
306
287
  | Cards / panels | **Background** (must not be `rgba(0,0,0,0)` when Figma shows a surface), border, radius, shadow, padding |
307
- | Surface containers | Every entry in the Phase 1g Surfaces table; children enclosed within the card's bounding rect |
288
+ | Surface containers | Every entry in the Phase 1g Table B; children enclosed within the card's bounding rect |
308
289
  | Form fields | `outlined` presence matching the Phase 1d variant; label placement; helper text slot |
309
290
  | Action controls | Count and names vs the Phase 1d inventory; `aria-label` on icon-only buttons |
310
291
  | Buttons | `variant` (flat/outlined/contained/fab), color, typography, padding |
@@ -358,6 +339,22 @@ igc-calendar {
358
339
 
359
340
  Choose the multiplier by visual judgment — never by mapping a Figma pixel value.
360
341
 
342
+ ### Typography correction
343
+
344
+ Fix the type style, not an internal class. Every type style is a set of `--ig-<style>-<property>` variables on `:root` that the components read (see `design-token-bridge.md § B4`):
345
+
346
+ ```css
347
+ /* Example: the page heading renders at 28px, the design shows 24px. Native <h1> elements
348
+ get the h1 type style inside an element with the `ig-typography` class. */
349
+ :root {
350
+ --ig-h1-font-size: 1.5rem; /* 24px */
351
+ }
352
+ ```
353
+
354
+ If the text belongs to a component, find which type style it uses in the component's doc, or use its typography-related design tokens from `theming_get_component_design_tokens`. Or style content you slot into it.
355
+
356
+ Inside a Lit view's shadow root, document CSS such as `.ig-typography h1` does not reach native headings. Apply the variables in the view's `static styles` yourself, for example `h1 { font-size: var(--ig-h1-font-size); font-weight: var(--ig-h1-font-weight); line-height: var(--ig-h1-line-height); }`.
357
+
361
358
  ### Color correction
362
359
 
363
360
  ```css
@@ -366,11 +363,8 @@ background: var(--ig-primary-500);
366
363
  color: var(--ig-primary-500-contrast);
367
364
  ```
368
365
 
369
- Use `get_color({ color: "primary", variant: "500", contrast: true })` when unsure of the
370
- exact variable name.
366
+ Use `get_color({ color: "primary", variant: "500", contrast: true })` when unsure of the exact variable name.
371
367
 
372
368
  ### Missing element
373
369
 
374
- If an element is in Figma but absent from the DOM, check in this order: registration
375
- (`customElements.get`) → import path → the slot name it should occupy → then go back to
376
- Phase 2 and re-read the component doc. A wrong slot name renders nothing and reports nothing.
370
+ If an element is in Figma but absent from the DOM, check in this order: registration (`customElements.get`) → import path → the slot name it should occupy → then go back to Phase 2 and re-read the component doc. A wrong slot name renders nothing and reports nothing.
@@ -1,6 +1,7 @@
1
1
  ---
2
+ license: MIT
2
3
  name: igniteui-wc-generate-from-image-design
3
- description: Implement application views from design images using Ignite UI Web Components. Uses MCP servers (igniteui-cli, igniteui-theming) to discover components, generate themes, and follow best practices. Triggers when the user provides a design image (screenshot, mockup, wireframe) and wants it built as a working view with Ignite UI Web Components. Also triggers when the user asks to "implement this design", "build this UI", "convert this mockup", or "create a page from this image" in an Ignite UI Web Components project.
4
+ description: "Implement application views from design images (screenshots, mockups, wireframes) using Ignite UI Web Components, with the igniteui-cli and igniteui-theming MCP servers for component discovery, theme generation, and best practices. WHEN TO USE: the user provides a design image and wants it built as a working view, or asks to 'implement this design', 'build this UI', 'convert this mockup', or 'create a page from this image' in an Ignite UI Web Components project. WHEN NOT TO USE: the design source is a Figma file or URL (use figma-to-app), no image is provided and the user only needs component suggestions (use choose-components), the task is only theming or restyling existing views (use customize-component-theme), or the task is package installation/framework setup (use integrate-with-framework)."
4
5
  user-invocable: true
5
6
  ---
6
7
 
@@ -98,11 +98,11 @@ Use the Web Components slot anatomy:
98
98
  ```
99
99
 
100
100
  ### Nav drawer width
101
- Width is controlled by two CSS custom properties exposed on the host — they are **not** design tokens and won't appear in `get_component_design_tokens`. Override them directly:
101
+ Width comes from the `navdrawer` design tokens `size` and `size--mini`, exposed as `--ig-nav-drawer-size` (default 15rem) and `--ig-nav-drawer-size--mini` (default depends on the design system). Set them with `create_component_theme("navdrawer", …)`, or directly:
102
102
  ```css
103
103
  igc-nav-drawer {
104
- --menu-full-width: 280px; /* default: 240px */
105
- --menu-mini-width: 56px; /* no default — collapses to content width if unset */
104
+ --ig-nav-drawer-size: 280px;
105
+ --ig-nav-drawer-size--mini: 56px;
106
106
  }
107
107
  ```
108
108
 
@@ -0,0 +1,133 @@
1
+ ---
2
+ license: MIT
3
+ name: igniteui-wc-grids
4
+ description: "Set up a data grid with Ignite UI Web Components, including grid selection, single-design-system theming, Shadow DOM theme injection, component registration, fluid layout, and sorting/filtering. WHEN TO USE: adding a grid to a Web Components app, or fixing an unstyled, mis-sized, or broken grid inside a custom element or Shadow DOM, or needing correct package, theme, layout, or sorting/filter setup. WHEN NOT TO USE: general component selection (use choose-components), Grid Lite to premium migration (use migrate-grid-lite-to-premium), framework wiring (use integrate-with-framework), app-wide theming (use customize-component-theme), bundle optimization (use optimize-bundle-size), or non-tabular components such as charts, lists, or tree views."
5
+ user-invocable: true
6
+ ---
7
+
8
+ # Using the Ignite UI for Web Components grids
9
+
10
+ ## Required Workflow
11
+
12
+ 1. **Pick the grid type/package** using the table below; ask if ambiguous.
13
+ 2. **Use only the verified import paths in this file** (`igniteui-webcomponents-grids`, `grids/combined.js`, `themes/<variant>/<design>.css`). For anything else (toolbar, export, pivot/tree/hierarchical APIs, properties/events), look it up with `list_components({ framework: "webcomponents", ... })` / `get_doc({ framework: "webcomponents", name: "<doc-name>" })` / `search_api({ platform: "webcomponents", query: "<keyword>" })` / `get_api_reference({ platform: "webcomponents", component: "<ClassName>" })` instead of guessing.
14
+
15
+ ## Choosing the Grid
16
+
17
+ | Need | Component | Package |
18
+ |---|---|---|
19
+ | Read-only table, sorting/filtering only | `<igc-grid-lite>` | `igniteui-grid-lite` (MIT) |
20
+ | Editing, selection, paging, grouping, summaries, export, toolbar | `<igc-grid>` | `igniteui-webcomponents-grids` (trial) / `@infragistics/igniteui-webcomponents-grids` (licensed; replace the package name in all imports below) |
21
+ | Parent-child, single schema (`managerId`/nested `children`) | `<igc-tree-grid>` | `igniteui-webcomponents-grids` (trial) / `@infragistics/igniteui-webcomponents-grids` (licensed) |
22
+ | Parent-child, different schema per level | `<igc-hierarchical-grid>` | `igniteui-webcomponents-grids` (trial) / `@infragistics/igniteui-webcomponents-grids` (licensed) |
23
+ | Cross-tab / OLAP analysis | `<igc-pivot-grid>` | `igniteui-webcomponents-grids` (trial) / `@infragistics/igniteui-webcomponents-grids` (licensed) |
24
+
25
+ Never mix `igc-grid-lite` with a premium grid type for the same table — pick one. For upgrading Grid Lite to `igc-grid`, use the migration skill above.
26
+
27
+ For Grid Lite, import the `igniteui-grid-lite` package and its elements directly. Load only the base Ignite UI theme; do not import the premium grid package or grid theme:
28
+
29
+ ```typescript
30
+ import { IgcGridLite, IgcGridLiteColumn } from 'igniteui-grid-lite';
31
+ import 'igniteui-webcomponents/themes/light/material.css';
32
+ ```
33
+
34
+ ## Theming Setup
35
+
36
+ - **Pick exactly one design system** (`material` | `bootstrap` | `fluent` | `indigo`) **and one variant** (`light` | `dark`) for the whole app. Never load two design systems together, and never load both a light and a dark file at once — toggle between the matching light/dark pair of the *same* design system instead.
37
+ - **For premium grids only** (`igc-grid`, `igc-tree-grid`, `igc-hierarchical-grid`, `igc-pivot-grid`), load both the base theme and the grid theme, same design system + variant — the grid package ships its own theme file for its internal structure (headers, cells, sort/filter icons, resize handles):
38
+
39
+ ```typescript
40
+ import 'igniteui-webcomponents/themes/light/material.css';
41
+ import 'igniteui-webcomponents-grids/grids/themes/light/material.css';
42
+ ```
43
+
44
+ Path pattern for both packages: `themes/<light|dark>/<material|bootstrap|fluent|indigo>.css` (grid package: `igniteui-webcomponents-grids/grids/themes/...`).
45
+
46
+ - These are document-level imports — they style the light DOM only. If the grid renders inside a Shadow root, see **Shadow DOM** below; a bare import never crosses into a shadow root.
47
+
48
+ ## Registering Components
49
+
50
+ For premium grids, register only the selected grid type:
51
+
52
+ ```typescript
53
+ import { IgcGridComponent } from 'igniteui-webcomponents-grids';
54
+ IgcGridComponent.register();
55
+
56
+ // Base package — register only what you use, not defineAllComponents()
57
+ import { defineComponents, IgcButtonComponent } from 'igniteui-webcomponents';
58
+ defineComponents(IgcButtonComponent);
59
+ ```
60
+
61
+ Use the corresponding `Igc*GridComponent.register()` method for tree, hierarchical, or pivot grids. Use `igniteui-webcomponents-grids/grids/combined.js` only when the application intentionally uses all premium grid types.
62
+
63
+ Built-in grid glyphs (sort direction, filter, expand/collapse) come from the library's internal SVG icon collection and render automatically once the grid module above is registered — no icon font and no manual `registerIcon`/`registerIconFromText` call is needed for them. Only register icons for custom glyphs the app adds itself.
64
+
65
+ ## Shadow DOM
66
+
67
+ The most common cause of a "broken grid" (e.g. a checkbox expanding to 1000px+ wide) is a Lit component rendering `<igc-grid>` in its own shadow tree without the grid theme reaching that tree. Import the theme as an inline string and inject it as a `<style>` tag in `render()`:
68
+
69
+ ```typescript
70
+ import { html, LitElement } from 'lit';
71
+ import gridTheme from 'igniteui-webcomponents-grids/grids/themes/light/material.css?inline';
72
+
73
+ class MyGridPanel extends LitElement {
74
+ private readonly data: Array<{ name: string }> = [
75
+ { name: 'Ada Lovelace' },
76
+ ];
77
+
78
+ render() {
79
+ return html`
80
+ <style>${gridTheme}</style>
81
+ <igc-grid .data=${this.data} allow-filtering="true" height="100%">
82
+ <igc-column field="name" sortable="true" filterable="true"></igc-column>
83
+ </igc-grid>
84
+ `;
85
+ }
86
+ }
87
+ ```
88
+
89
+ The ?inline suffix is Vite-specific. In other bundlers, use their equivalent method for raw-string CSS imports. If the grid looks broken, fix the missing theme injection — do not mask the symptom with fallback CSS overrides.
90
+
91
+ ## Fluid Layout
92
+
93
+ Let the grid fill its container instead of hardcoding pixel heights:
94
+
95
+ ```css
96
+ .app-shell { display: flex; flex-direction: column; block-size: 100vh; }
97
+ .app-header { flex: 0 0 auto; } /* fixed-height header */
98
+ .app-content { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; } /* min-height: 0 lets this row shrink instead of overflow */
99
+ igc-grid { flex: 1 1 auto; min-height: 0; block-size: 100%; }
100
+ ```
101
+
102
+ - The grid still needs a resolvable height for row virtualization — get it from the fluid layout (`100%` of a sized ancestor), not a guessed fixed pixel value on the grid itself.
103
+ - Omit column `width` unless a column needs a fixed size — columns are fluid by default; leave at least one column without `width` to absorb remaining space.
104
+
105
+ ## Sorting & Filtering
106
+
107
+ ```html
108
+ <igc-grid allow-filtering="true" height="100%">
109
+ <igc-column field="name" sortable="true" filterable="true"></igc-column>
110
+ </igc-grid>
111
+ ```
112
+
113
+ `allow-filtering="true"` on the grid is required for the filtering UI to appear — a column's `filterable="true"` alone has no visible effect. Boolean-looking attributes take quoted string values (`sortable="true"`, not bare `sortable`). For events, remote sort/filter, or programmatic APIs, see the migration skill above (same API whether or not the app is migrating from Grid Lite).
114
+
115
+ ## Verify with a Clean Run
116
+
117
+ - [ ] No console errors/warnings (missing element definitions, CSS import errors)
118
+ - [ ] Grid fully styled per the chosen design system — no unstyled/browser-default look
119
+ - [ ] Sort/filter icons render as glyphs, not empty boxes or ligature text
120
+ - [ ] Filtering UI is visible; sorting and filtering both work interactively
121
+ - [ ] Grid keeps filling its container on resize — no trailing empty space, no clipped rows
122
+ - [ ] No leftover commented-out theme blocks from an earlier attempt
123
+
124
+ ## Key Rules
125
+
126
+ 1. One design system, one variant, everywhere — never mix design systems or light/dark files.
127
+ 2. Always load both the base theme and the grid theme for that same design system + variant.
128
+ 3. Inject the grid theme into every Shadow root that renders `<igc-grid>`/`<igc-tree-grid>`/`<igc-hierarchical-grid>`/`<igc-pivot-grid>`.
129
+ 4. Register only the selected grid type and components actually used — no `defineAllComponents()`, no "just in case" bundles.
130
+ 5. Never guess deep import paths or APIs beyond what's verified here — look them up.
131
+ 6. Fluid layout by default: `min-height: 0` + `flex`/`grid` sizing; fixed pixel heights only when explicitly required.
132
+ 7. `allow-filtering="true"` on the grid + `sortable`/`filterable` per column to enable sorting/filtering UI.
133
+ 8. Fix root causes (missing theme/registration) instead of papering over symptoms with fallback CSS.
@@ -1,6 +1,7 @@
1
1
  ---
2
+ license: MIT
2
3
  name: igniteui-wc-integrate-with-framework
3
- description: Integrate Ignite UI Web Components packages into React, Angular, Vue, or vanilla JS applications with framework-specific configurations
4
+ description: "Install and integrate Ignite UI Web Components packages into React, Angular, Vue 3, LitElement, or vanilla JS/HTML apps, detecting the framework and applying framework-specific setup (package choice, component registration, theme imports, schemas/config, events and property binding). WHEN TO USE: the user wants to add Ignite UI Web Components or igniteui-react to a project, set up a new app with them, fix registration/'unknown element' errors, or needs framework-specific wiring for templates, events, or forms. WHEN NOT TO USE: picking which components to use (use choose-components), customizing themes or styles (use customize-component-theme), trimming bundle size or import granularity (use optimize-bundle-size), building a view from a design (use generate-from-image-design or figma-to-app), or projects using Ignite UI for Angular/Blazor native packages instead of Web Components."
4
5
  user-invocable: true
5
6
  ---
6
7
 
@@ -1,6 +1,7 @@
1
1
  ---
2
+ license: MIT
2
3
  name: igniteui-wc-migrate-grid-lite-to-premium
3
- description: Step-by-step migration guide from igniteui-grid-lite (IgcGridLite) to the premium igniteui-webcomponents-grids (IgcGridComponent), covering every import, class name, HTML tag, property, event, template, sorting, filtering, and theming API change.
4
+ description: "Step-by-step migration from igniteui-grid-lite (IgcGridLite, <igc-grid-lite>) to the premium igniteui-webcomponents-grids data grid (IgcGridComponent, <igc-grid>), covering imports, class names, HTML tags, properties, events, templates, sorting, filtering, remote data, and theming API changes. WHEN TO USE: the user wants to upgrade from Grid Lite to the premium grid, or needs enterprise features Grid Lite lacks (editing, selection, paging, grouping, summaries, Excel export, state persistence). WHEN NOT TO USE: starting a new grid from scratch (use choose-components), migrating between other grids (Tree Grid, Hierarchical Grid, Pivot Grid) or across major versions of the same package, the project uses igniteui-angular or Blazor grids, or the user only needs theming (use customize-component-theme)."
4
5
  user-invocable: true
5
6
  ---
6
7
 
@@ -1,6 +1,7 @@
1
1
  ---
2
+ license: MIT
2
3
  name: igniteui-wc-optimize-bundle-size
3
- description: Optimize application bundle size by importing only necessary components and using tree-shaking effectively
4
+ description: "Reduce application bundle size with Ignite UI Web Components by registering only needed components via named imports from the package root with defineComponents instead of defineAllComponents, lazy-loading heavy components, and verifying tree-shaking with bundle analysis. WHEN TO USE: the user reports a large bundle or slow load, asks how to import components individually, wants to lazy-load grids, charts, or dock manager, or needs to audit Ignite UI imports in Vite/webpack/Rollup builds. WHEN NOT TO USE: initial package installation or framework wiring (use integrate-with-framework), choosing components (use choose-components), theming (use customize-component-theme), or general performance issues unrelated to bundle size such as runtime rendering or data virtualization."
4
5
  user-invocable: true
5
6
  ---
6
7