@wix/agent-skills 1.0.0

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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +29 -0
  4. package/skills/wix-app/SKILL.md +344 -0
  5. package/skills/wix-app/references/APP_IDENTIFIERS.md +35 -0
  6. package/skills/wix-app/references/APP_MARKET_REVIEW.md +311 -0
  7. package/skills/wix-app/references/APP_VALIDATION.md +171 -0
  8. package/skills/wix-app/references/BACKEND_API.md +233 -0
  9. package/skills/wix-app/references/BACKEND_EVENT.md +116 -0
  10. package/skills/wix-app/references/CODE_QUALITY.md +33 -0
  11. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +587 -0
  12. package/skills/wix-app/references/DASHBOARD_MENU_PLUGIN.md +157 -0
  13. package/skills/wix-app/references/DASHBOARD_MODAL.md +283 -0
  14. package/skills/wix-app/references/DASHBOARD_PAGE.md +403 -0
  15. package/skills/wix-app/references/DASHBOARD_PLUGIN.md +205 -0
  16. package/skills/wix-app/references/DATA_COLLECTION.md +451 -0
  17. package/skills/wix-app/references/DOCUMENTATION.md +42 -0
  18. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +65 -0
  19. package/skills/wix-app/references/EMBEDDED_SCRIPT.md +468 -0
  20. package/skills/wix-app/references/EXTENSION_REGISTRATION.md +96 -0
  21. package/skills/wix-app/references/SERVICE_PLUGIN.md +235 -0
  22. package/skills/wix-app/references/SITE_PLUGIN.md +436 -0
  23. package/skills/wix-app/references/STORES_VERSIONING.md +334 -0
  24. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +84 -0
  25. package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +345 -0
  26. package/skills/wix-app/references/dashboard-menu-plugin/blog-slots.md +71 -0
  27. package/skills/wix-app/references/dashboard-menu-plugin/bookings-slots.md +58 -0
  28. package/skills/wix-app/references/dashboard-menu-plugin/crm-slots.md +8 -0
  29. package/skills/wix-app/references/dashboard-menu-plugin/ecommerce-slots.md +17 -0
  30. package/skills/wix-app/references/dashboard-menu-plugin/events-slots.md +29 -0
  31. package/skills/wix-app/references/dashboard-menu-plugin/restaurants-slots.md +27 -0
  32. package/skills/wix-app/references/dashboard-menu-plugin/stores-slots.md +35 -0
  33. package/skills/wix-app/references/dashboard-page/API_SPEC.md +138 -0
  34. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +573 -0
  35. package/skills/wix-app/references/dashboard-page/DYNAMIC_PARAMETERS.md +269 -0
  36. package/skills/wix-app/references/dashboard-page/ECOM_NAVIGATION.md +164 -0
  37. package/skills/wix-app/references/dashboard-plugin/SLOTS.md +294 -0
  38. package/skills/wix-app/references/data-collection/WIX_DATA.md +270 -0
  39. package/skills/wix-app/references/data-collection/extension-template.ts +107 -0
  40. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +138 -0
  41. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +454 -0
  42. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +165 -0
  43. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +576 -0
  44. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +170 -0
  45. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +6 -0
  46. package/skills/wix-app/references/editor-react-component/PARTS.md +25 -0
  47. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +203 -0
  48. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +167 -0
  49. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +137 -0
  50. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +112 -0
  51. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +118 -0
  52. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +87 -0
  53. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +86 -0
  54. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +135 -0
  55. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +79 -0
  56. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +68 -0
  57. package/skills/wix-app/references/site-plugin/EXAMPLES.md +311 -0
  58. package/skills/wix-app/references/site-plugin/SLOTS.md +263 -0
  59. package/skills/wix-design-system/SKILL.md +129 -0
  60. package/skills/wix-design-system/references/file-structure.md +56 -0
  61. package/skills/wix-design-system/scripts/wds.cjs +531 -0
  62. package/skills/wix-headless/SKILL.md +418 -0
  63. package/skills/wix-headless/references/DISCOVERY.md +332 -0
  64. package/skills/wix-headless/references/ORCHESTRATION.md +269 -0
  65. package/skills/wix-headless/references/SETUP.md +154 -0
  66. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +152 -0
  67. package/skills/wix-headless/references/blog/BLOG_PAGES.md +299 -0
  68. package/skills/wix-headless/references/blog/BLOG_SETUP.md +218 -0
  69. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +32 -0
  70. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +373 -0
  71. package/skills/wix-headless/references/cms/FAQ_KNOWLEDGE_BASE.md +229 -0
  72. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +40 -0
  73. package/skills/wix-headless/references/cms/PORTFOLIO.md +454 -0
  74. package/skills/wix-headless/references/cms/RESOURCE_LIBRARY.md +356 -0
  75. package/skills/wix-headless/references/cms/TEAM_DIRECTORY.md +299 -0
  76. package/skills/wix-headless/references/commands/install-app.md +42 -0
  77. package/skills/wix-headless/references/commands/known-apps.json +5 -0
  78. package/skills/wix-headless/references/commands/mcp-bootstrap.md +28 -0
  79. package/skills/wix-headless/references/designer/INSTRUCTIONS.md +828 -0
  80. package/skills/wix-headless/references/ecom/CART_PAGES.md +120 -0
  81. package/skills/wix-headless/references/ecom/CART_WIRING.md +103 -0
  82. package/skills/wix-headless/references/ecom/COMPONENTS_CSS.md +132 -0
  83. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +59 -0
  84. package/skills/wix-headless/references/forms/CONTACT_FORM.md +477 -0
  85. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +43 -0
  86. package/skills/wix-headless/references/gift-cards/COMPONENTS.md +119 -0
  87. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +51 -0
  88. package/skills/wix-headless/references/gift-cards/PAGES.md +129 -0
  89. package/skills/wix-headless/references/images/INSTRUCTIONS.md +359 -0
  90. package/skills/wix-headless/references/shared/BUILD_NOISE.md +8 -0
  91. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +185 -0
  92. package/skills/wix-headless/references/shared/IMPLEMENTER.md +155 -0
  93. package/skills/wix-headless/references/shared/MCP_PREFIX.md +105 -0
  94. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +97 -0
  95. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +423 -0
  96. package/skills/wix-headless/references/shared/STYLING.md +117 -0
  97. package/skills/wix-headless/references/stores/BACK_IN_STOCK.md +178 -0
  98. package/skills/wix-headless/references/stores/CATEGORY_PAGES.md +86 -0
  99. package/skills/wix-headless/references/stores/COMPONENTS_CSS.md +129 -0
  100. package/skills/wix-headless/references/stores/HOME_AND_NAV.md +227 -0
  101. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +96 -0
  102. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +249 -0
  103. package/skills/wix-headless/references/stores/PRODUCT_PAGES.md +213 -0
  104. package/skills/wix-headless/references/stores/SHARED_WIRING.md +164 -0
  105. package/skills/wix-headless/references/verticals/_schema.json +160 -0
  106. package/skills/wix-headless/references/verticals/_schema.md +185 -0
  107. package/skills/wix-headless/references/verticals/blog.md +125 -0
  108. package/skills/wix-headless/references/verticals/cms.md +121 -0
  109. package/skills/wix-headless/references/verticals/ecom.md +96 -0
  110. package/skills/wix-headless/references/verticals/forms.md +106 -0
  111. package/skills/wix-headless/references/verticals/gift-cards.md +121 -0
  112. package/skills/wix-headless/references/verticals/stores.md +167 -0
  113. package/skills/wix-headless/scripts/check-manifest.mjs +198 -0
  114. package/skills/wix-headless/scripts/copy-utility-templates.mjs +153 -0
  115. package/skills/wix-headless/scripts/emit-design-tokens.mjs +77 -0
  116. package/skills/wix-headless/scripts/finalize-run-json.mjs +141 -0
  117. package/skills/wix-headless/scripts/init-site-json.mjs +63 -0
  118. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +124 -0
  119. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +190 -0
  120. package/skills/wix-headless/scripts/preview.sh +45 -0
  121. package/skills/wix-headless/scripts/release.sh +73 -0
  122. package/skills/wix-headless/scripts/scaffold.sh +53 -0
  123. package/skills/wix-headless/scripts/seed-utilities.sh +55 -0
  124. package/skills/wix-headless/shared-utilities/analytics.ts +40 -0
  125. package/skills/wix-headless/shared-utilities/ricos.ts +179 -0
  126. package/skills/wix-headless/shared-utilities/wix-image.ts +72 -0
  127. package/skills/wix-headless/templates/ecom/CartBadge.tsx +84 -0
  128. package/skills/wix-headless/templates/ecom/CartView.tsx +543 -0
  129. package/skills/wix-headless/templates/ecom/cart.astro +13 -0
  130. package/skills/wix-headless/templates/ecom/components-ecom.css +215 -0
  131. package/skills/wix-headless/templates/ecom/discounts.ts +71 -0
  132. package/skills/wix-headless/templates/ecom/thank-you.astro +24 -0
  133. package/skills/wix-headless/templates/gift-cards/GiftCardPurchase.tsx +172 -0
  134. package/skills/wix-headless/templates/gift-cards/_home-teaser-snippet.astro +42 -0
  135. package/skills/wix-headless/templates/gift-cards/_nav-snippet.astro +11 -0
  136. package/skills/wix-headless/templates/gift-cards/components-gift-cards.css +219 -0
  137. package/skills/wix-headless/templates/gift-cards/gift-cards.astro +51 -0
  138. package/skills/wix-headless/templates/gift-cards/gift-cards.ts +75 -0
  139. package/skills/wix-headless/templates/stores/AddToCartButton.tsx +77 -0
  140. package/skills/wix-headless/templates/stores/BackInStockForm.tsx +176 -0
  141. package/skills/wix-headless/templates/stores/CategoryRail.astro +69 -0
  142. package/skills/wix-headless/templates/stores/ProductCard.astro +79 -0
  143. package/skills/wix-headless/templates/stores/ProductPurchase.tsx +397 -0
  144. package/skills/wix-headless/templates/stores/SeoTags.astro +21 -0
  145. package/skills/wix-headless/templates/stores/back-in-stock.ts +67 -0
  146. package/skills/wix-headless/templates/stores/categories.ts +155 -0
  147. package/skills/wix-headless/templates/stores/category/[slug].astro +130 -0
  148. package/skills/wix-headless/templates/stores/components-stores.css +295 -0
  149. package/skills/wix-headless/templates/stores/products/[slug].astro +128 -0
  150. package/skills/wix-headless/templates/stores/products/index.astro +101 -0
  151. package/skills/wix-manage/SKILL.md +280 -0
  152. package/skills/wix-manage/references/app-installation/install-wix-apps.md +155 -0
  153. package/skills/wix-manage/references/app-installation/list-installed-apps.md +124 -0
  154. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +226 -0
  155. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +95 -0
  156. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +416 -0
  157. package/skills/wix-manage/references/bookings/bookings-staff-setup.md +255 -0
  158. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +462 -0
  159. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +278 -0
  160. package/skills/wix-manage/references/bookings/external-calendar-integration.md +258 -0
  161. package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +231 -0
  162. package/skills/wix-manage/references/calendar/configure-default-business-hours.md +226 -0
  163. package/skills/wix-manage/references/cms/cms-data-items-crud.md +422 -0
  164. package/skills/wix-manage/references/cms/cms-data-operations-extended.md +263 -0
  165. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +136 -0
  166. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +160 -0
  167. package/skills/wix-manage/references/cms/cms-schema-management.md +143 -0
  168. package/skills/wix-manage/references/contacts/bulk-delete-contacts.md +73 -0
  169. package/skills/wix-manage/references/contacts/bulk-label-and-unlabel-contacts.md +67 -0
  170. package/skills/wix-manage/references/domains/domain-search-and-purchase.md +434 -0
  171. package/skills/wix-manage/references/ecommerce/api-recommendation-tracking.md +420 -0
  172. package/skills/wix-manage/references/ecommerce/flow-add-free-shipping.md +267 -0
  173. package/skills/wix-manage/references/ecommerce/flow-bundle-and-save.md +290 -0
  174. package/skills/wix-manage/references/ecommerce/flow-fix-coverage-gaps.md +300 -0
  175. package/skills/wix-manage/references/ecommerce/flow-optimize-shipping-rates.md +364 -0
  176. package/skills/wix-manage/references/ecommerce/flow-seasonal-promotion.md +315 -0
  177. package/skills/wix-manage/references/ecommerce/flow-stock-mover.md +308 -0
  178. package/skills/wix-manage/references/ecommerce/flow-upsell-boost.md +271 -0
  179. package/skills/wix-manage/references/ecommerce/goal-clear-inventory.md +118 -0
  180. package/skills/wix-manage/references/ecommerce/goal-drive-cross-sells.md +122 -0
  181. package/skills/wix-manage/references/ecommerce/goal-increase-aov.md +132 -0
  182. package/skills/wix-manage/references/ecommerce/goal-reduce-cart-abandonment.md +148 -0
  183. package/skills/wix-manage/references/ecommerce/goal-seasonal-revenue.md +146 -0
  184. package/skills/wix-manage/references/ecommerce/guardrail-discount-conflicts.md +118 -0
  185. package/skills/wix-manage/references/ecommerce/guardrail-margin-protection.md +88 -0
  186. package/skills/wix-manage/references/ecommerce/guardrail-rate-pricing-sanity.md +108 -0
  187. package/skills/wix-manage/references/ecommerce/guardrail-shipping-health.md +124 -0
  188. package/skills/wix-manage/references/ecommerce/recipe-apply-shipping-recommendations.md +299 -0
  189. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +582 -0
  190. package/skills/wix-manage/references/ecommerce/setup-coupons.md +338 -0
  191. package/skills/wix-manage/references/ecommerce/setup-discount-rules.md +444 -0
  192. package/skills/wix-manage/references/ecommerce/setup-shipping-rates.md +86 -0
  193. package/skills/wix-manage/references/ecommerce/setup-shipping-regions.md +56 -0
  194. package/skills/wix-manage/references/ecommerce/setup-store-pickup-location.md +209 -0
  195. package/skills/wix-manage/references/ecommerce/skill-graph.md +139 -0
  196. package/skills/wix-manage/references/ecommerce/troubleshoot-checkout-delivery-dropoff.md +124 -0
  197. package/skills/wix-manage/references/ecommerce/troubleshoot-discount-not-applying.md +95 -0
  198. package/skills/wix-manage/references/events/list-events.md +203 -0
  199. package/skills/wix-manage/references/forms/create-form.md +260 -0
  200. package/skills/wix-manage/references/get-paid/create-payment-links.md +212 -0
  201. package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +57 -0
  202. package/skills/wix-manage/references/get-paid/payment-links-for-bookings.md +101 -0
  203. package/skills/wix-manage/references/media/upload-media-to-wix.md +216 -0
  204. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +77 -0
  205. package/skills/wix-manage/references/pricing-plans/pricing-plans-bookings-integration.md +166 -0
  206. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +336 -0
  207. package/skills/wix-manage/references/rich-content/ricos-converter-service.md +295 -0
  208. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +59 -0
  209. package/skills/wix-manage/references/sites/create-site-from-template.md +183 -0
  210. package/skills/wix-manage/references/sites/query-sites.md +125 -0
  211. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +57 -0
  212. package/skills/wix-manage/references/stores/bulk-create-products-with-options.md +1041 -0
  213. package/skills/wix-manage/references/stores/create-product-catalog-v1.md +125 -0
  214. package/skills/wix-manage/references/stores/create-product-from-image.md +824 -0
  215. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +566 -0
  216. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +194 -0
  217. package/skills/wix-manage/references/stores/query-products-catalog-v1.md +80 -0
  218. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +99 -0
  219. package/skills/wix-manage/references/stores/update-product-pre-order.md +213 -0
  220. package/skills/wix-manage/references/stores/update-product-with-options.md +318 -0
@@ -0,0 +1,138 @@
1
+ # Accessibility (ARIA)
2
+
3
+ Rules and patterns for ARIA accessibility support in Editor React components.
4
+
5
+ ---
6
+
7
+ ## Rules
8
+
9
+ ### All ARIA Attributes Through the `a11y` Prop
10
+
11
+ - **NEVER** add individual ARIA properties like `ariaLabel?: string`, `ariaDescribedBy?: string`, `role?: string`, etc. to a component's props interface.
12
+ - **ALL** accessibility attributes MUST come through the `a11y?: A11y` prop.
13
+ - The `A11y` type includes: `ariaLabel`, `ariaDescribedBy`, `ariaLabelledBy`, `role`, `ariaHidden`, `ariaLive`, and all other ARIA attributes.
14
+ - Users provide ARIA values through the `a11y` prop: `<Component a11y={{ ariaLabel: "..." }} />`
15
+
16
+ ### ARIA Label Rules
17
+
18
+ ARIA labels are user-facing content and must NEVER be hardcoded as string literals in JSX.
19
+
20
+ **Three patterns (in order of preference):**
21
+
22
+ 1. **No aria-label (preferred)** — Visible text content is sufficient:
23
+
24
+ ```tsx
25
+ <Button>Play</Button> // Visible text ✅
26
+ ```
27
+
28
+ 2. **User-configurable** — Via a11y prop (for root or element-specific labels, per requirements):
29
+
30
+ ```tsx
31
+ // User provides: <ComponentName a11y={{ ariaLabel: "Background music" }} />
32
+ // Component applies to root (using the a11y-to-HTML conversion utility):
33
+ {...(a11y && convertA11yKeysToHtmlFormat(a11y))}
34
+
35
+ // Or for inner elements (if requirements specify):
36
+ // elementProps.button.a11y gets passed to the button element
37
+ ```
38
+
39
+ 3. **System-required** — Via constants.ts (when requirements specify non-configurable label):
40
+
41
+ ```tsx
42
+ // constants.ts
43
+ export const ARIA_LABELS = {
44
+ playButton: 'Play audio',
45
+ muteButton: 'Mute audio',
46
+ } as const;
47
+
48
+ // component.tsx
49
+ import { ARIA_LABELS } from './constants';
50
+ <Button aria-label={ARIA_LABELS.playButton}>▶</Button>;
51
+ ```
52
+
53
+ **❌ NEVER hardcode string literals:**
54
+
55
+ ```tsx
56
+ // ❌ WRONG - hardcoded strings
57
+ <Button aria-label="Play">▶</Button>
58
+ <Button aria-label={isPlaying ? "Pause" : "Play"}>▶</Button>
59
+ <Slider aria-label="Volume" />
60
+ ```
61
+
62
+ **Why this matters:**
63
+
64
+ - Hardcoded strings cannot be translated or customized
65
+ - User-provided labels take precedence when available
66
+ - Constants allow centralized management and potential future translation
67
+
68
+ ### Detecting Icon-Only Interactive Elements
69
+
70
+ **Icon-only elements require aria-labels.** Detect with this checklist:
71
+
72
+ | Element Content | Needs aria-label? | Example |
73
+ | --------------------- | ----------------- | ----------------------------------------- |
74
+ | Visible text only | ❌ No | `<Button>Play</Button>` |
75
+ | Icon component + text | ❌ No | `<Button><PlayIcon />Play</Button>` |
76
+ | Icon/emoji only | ✅ YES | `<Button>▶</Button>` |
77
+ | Image only | ✅ YES | `<Button><img src="play.png" /></Button>` |
78
+ | SVG only | ✅ YES | `<Button><svg>...</svg></Button>` |
79
+
80
+ **Critical:** If button/link contains ONLY visual elements (icons, emojis, images, SVG) with NO text node, it MUST have aria-label from constants.
81
+
82
+ **Pattern for dynamic labels:**
83
+
84
+ ```tsx
85
+ // constants.ts
86
+ export const ARIA_LABELS = {
87
+ playButton: 'Play audio',
88
+ pauseButton: 'Pause audio',
89
+ } as const;
90
+
91
+ // component.tsx
92
+ <Button
93
+ aria-label={isPlaying ? ARIA_LABELS.pauseButton : ARIA_LABELS.playButton}
94
+ >
95
+ {isPlaying ? '⏸' : '▶'}
96
+ </Button>;
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Common Mistake: Individual ARIA Properties Instead of A11y Type
102
+
103
+ **❌ Wrong:**
104
+
105
+ ```typescript
106
+ import type { Direction } from '@wix/editor-react-types';
107
+
108
+ export interface TabsProps {
109
+ id?: string;
110
+ className?: string;
111
+ direction?: Direction;
112
+ ariaLabel?: string; // ❌ Individual ARIA prop
113
+ ariaDescribedBy?: string; // ❌ Individual ARIA prop
114
+ role?: string; // ❌ Individual ARIA prop
115
+ }
116
+ ```
117
+
118
+ **✅ Correct:**
119
+
120
+ ```typescript
121
+ import type { A11y, Direction } from '@wix/editor-react-types';
122
+ import { convertA11yKeysToHtmlFormat } from '@wix/react-component-utils';
123
+
124
+ export interface TabsProps {
125
+ id?: string;
126
+ className?: string;
127
+ direction?: Direction;
128
+ a11y?: A11y; // ✅ All ARIA attributes through this prop
129
+ }
130
+
131
+ // Usage:
132
+ <Tabs a11y={{ ariaLabel: "Navigation", role: "navigation" }} />
133
+
134
+ // In component:
135
+ {...(a11y && convertA11yKeysToHtmlFormat(a11y))}
136
+ ```
137
+
138
+ **Why:** The `A11y` type from `@wix/editor-react-types` provides a standardized way to handle ALL ARIA attributes (ariaLabel, ariaDescribedBy, ariaLabelledBy, role, ariaHidden, ariaLive, etc.). Individual ARIA props fragment the API and make it harder to use.
@@ -0,0 +1,454 @@
1
+ # Component API
2
+
3
+ Rules and patterns for props structure, elementProps, data types, file structure, containers, data-driven components, and array props.
4
+
5
+ ---
6
+
7
+ ## Should This Use elementProps or CSS?
8
+
9
+ ```
10
+ Does this element need:
11
+ - Configuration/data beyond styling
12
+ - Direction override
13
+ - State management
14
+ - Event handlers
15
+
16
+ │
17
+ ├─ YES
18
+ │ └─ ✅ Use elementProps
19
+ │
20
+ └─ NO → Is it purely visual/decorative (including conditionally displayed)?
21
+ │
22
+ ├─ YES (icons, separators, decorations, elements only hidden/shown via CSS)
23
+ │ └─ ❌ CSS class only (no elementProps)
24
+ │
25
+ └─ NO
26
+ └─ Re-evaluate: likely needs elementProps
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Rules
32
+
33
+ ### Component Props Structure
34
+
35
+ ```typescript
36
+ interface ComponentProps {
37
+ // Identity
38
+ id?: string;
39
+ className?: string;
40
+
41
+ // Mandatory features (from @wix/editor-react-types)
42
+ direction?: Direction;
43
+ a11y?: A11y; // ALL ARIA attributes come through this (ariaLabel, role, etc.)
44
+
45
+ // Component-specific props (NO children unless container-type - see container rules below)
46
+ label?: string;
47
+ items?: Array<ItemType>;
48
+ // ... from specification
49
+ // NEVER add: ariaLabel, ariaDescribedBy, role, etc. - use a11y prop instead
50
+
51
+ // Sub-component configuration (only if needed - see elementProps rules)
52
+ elementProps?: {
53
+ [partName]?: {
54
+ [configProp]?: string | boolean | number; // Only include if element needs config beyond className
55
+ direction?: Direction;
56
+ };
57
+ };
58
+ }
59
+ ```
60
+
61
+ ### When to Use elementProps
62
+
63
+ **Use `elementProps`** for parts that need:
64
+
65
+ - Configuration/data beyond just styling
66
+ - Direction override
67
+ - State management
68
+ - Event handlers
69
+
70
+ **DO NOT use `elementProps`** for:
71
+
72
+ - Elements with only visual styling (use CSS classes)
73
+ - Elements where conditional display is the only requirement (visibility controlled via CSS for per-breakpoint hiding, not React props)
74
+ - Elements that would only have `className` — skip them entirely
75
+ - Icons, decorations, separators
76
+
77
+ **Minimal elementProps rule:** If an element would only have `className?: string` in elementProps, do NOT include it.
78
+
79
+ ### What Qualifies as a Part
80
+
81
+ See [`PARTS.md`](PARTS.md) for the mandatory filter and full rules.
82
+
83
+ ### Derived values are not props
84
+
85
+ If a displayed value can be computed with a simple pure function from
86
+ other props and/or internal state, compute it internally — don't
87
+ expose it as a prop. Expose only the source inputs (use numeric types
88
+ when arithmetic is needed: `price: number`, not `price: string`).
89
+
90
+ **Example:** subtotal = `price × quantity` → computed inside the component, not a prop.
91
+
92
+ ### Data-Driven Components (NO children in exported props)
93
+
94
+ - Component's **exported interface** must NOT accept `children` prop
95
+ - ALL content MUST come through explicit named props (see "Derived values" above for what stays internal):
96
+ - Text (labels, placeholders, messages) → `label`, `text`, `placeholder`, etc.
97
+ - Media (images, videos, icons) → `imageSrc`, `videoUrl`, `iconName`, etc.
98
+ - Links (URLs, hrefs) → `link`, `href`, `url`, etc.
99
+ - Collections (list items, options, menu items) → `items`, `options`, `menuItems`, etc.
100
+ - **Internal implementation** can use children for composition between sub-components
101
+ - Hardcoded values are ONLY for fallback defaults when props are undefined
102
+
103
+ **Exception — Container-type components:** Components whose purpose is to wrap arbitrary child elements (e.g., BoxContainer) MAY accept `children: React.ReactNode`. This applies only to structural containers — data-driven leaf components (Button, Tabs, Accordion, etc.) must NOT use `children`.
104
+
105
+ ### Array Props: Data on Parent Only
106
+
107
+ When the parent component defines an array prop (e.g., `items`), child/item components receive a single item directly. They do NOT redeclare the data structure in their own props.
108
+
109
+ ### Array Element Types: Always Objects with Named Keys
110
+
111
+ Array elements MUST be objects with named keys. This enables stable item identity (each item can carry its own `id`/`key`), non-breaking extension (new fields can be added later without changing the prop signature), and semantic naming (each value has meaning instead of being an opaque scalar).
112
+
113
+ **Allowed forms:**
114
+
115
+ - Inline object literal: `Array<{ key: ValueType, ... }>`
116
+ - Named interface where the interface itself is an object with named keys (e.g. `Array<AccordionItem>` is OK because `AccordionItem` is `{ name, content }`)
117
+
118
+ **Never allowed as the array element:**
119
+
120
+ - Primitives: `Array<string>`, `Array<number>`, `Array<boolean>`
121
+ - Leaf data types from `@wix/editor-react-types`: `Array<Image>`, `Array<Link>`, `Array<Video>`, `Array<Audio>`, `Array<VectorArt>`, `Array<RichText>`. Wrap them in an object instead.
122
+ - Nested arrays: `Array<Array<{cover: image, caption: string}>>` `Array<{items: Array<image>, caption: string}>`
123
+
124
+ **❌ Wrong:**
125
+
126
+ ```typescript
127
+ tags: Array<string>;
128
+ prices: Array<number>;
129
+ flags: Array<boolean>;
130
+ images: Array<Image>;
131
+ links: Array<Link>;
132
+ nestedArrays: Array<Array<any>>
133
+ ```
134
+
135
+ **✅ Correct:**
136
+
137
+ ```typescript
138
+ tags: Array<{ label: string }>;
139
+ prices: Array<{ amount: number }>;
140
+ flags: Array<{ enabled: boolean }>;
141
+ gallery: Array<{ image: Image, caption?: string }>;
142
+ links: Array<{ link: Link, label: string }>;
143
+ items: Array<AccordionItem>; // AccordionItem is { name, content }
144
+ ```
145
+
146
+ ### Container Components (Blackbox Content)
147
+
148
+ When a component specification indicates a "container" or "slot" area where users can add nested content, use `React.ReactNode` for that content prop.
149
+
150
+ **When to use `React.ReactNode` for a content prop:**
151
+
152
+ - The specification describes a "container" or "content area"
153
+ - Users should be able to add arbitrary nested components
154
+ - The component doesn't control what goes inside that area
155
+
156
+ **RTL Support:** Elements that render `React.ReactNode` content MUST have `dir="ltr"` to prevent RTL inheritance from the parent component. See [`DIRECTIONALITY.md`](DIRECTIONALITY.md).
157
+
158
+ ### Component Data Types
159
+
160
+ When creating TypeScript interfaces for component props, use types from `@wix/editor-react-types` for more complex types, to see the allowed type from this library, look at the following file `node_modules/@wix/react-component-schema/dist/editor-react-types.d.ts`:
161
+
162
+ ```typescript
163
+ import type { Link } from "@wix/editor-react-types"; // Reference at node_modules/@wix/react-component-schema/dist/editor-react-types.d.ts
164
+ ```
165
+
166
+ ### External resources are forbidden
167
+
168
+ All resources rendered or fetched by the component (images, icons, fonts,
169
+ videos, audio, JSON data, etc.) MUST come from Wix services. Never reference
170
+ or call external (non-Wix) hosts — no `unsplash.com`, `placehold.co`,
171
+ `picsum.photos`, third-party CDN icon sets, or any custom backend the user
172
+ hasn't asked for. This rule covers both `src`/`href` attributes and any
173
+ runtime fetching.
174
+
175
+ Allowed image hosts: `static.wixstatic.com` (and other `*.wixstatic.com`
176
+ subdomains). Allowed data: values supplied through props (populated by the
177
+ editor) or imported local assets bundled with the component.
178
+
179
+ ### Default values for `Image` props
180
+
181
+ Image defaults belong in the component file's exported `defaultProps`
182
+ constant (the one consumed by `withDefaults(Component, defaultProps)` in
183
+ `component.tsx`). Use a Wix-hosted image from the Free-from-Wix public
184
+ media catalog and populate **only** `uri`, `url`, and `alt` — leave
185
+ `width`, `height`, `focalPoint`, etc. unset so the editor fills them when
186
+ the user picks a real image.
187
+
188
+ By default, use the canonical fallback URL from the examples below for
189
+ every `Image` default (`url` and `uri` derived from the same `fileName`).
190
+ **Only when the user explicitly asks for different/better default images**,
191
+ fetch candidates from the Wix Free-from-Wix catalog:
192
+
193
+ ```
194
+ GET https://publicmedia.wix.com/public/light_items?guid=bca5cb9f-45d2-4b11-8d6c-c9a7e7bd2873%3Aglobal%3Awix&pageSize=20&pageNumber=1&language=en&tags=free&mediaType=picture
195
+ ```
196
+
197
+ The endpoint is unauthenticated. Pick an item whose `displayTags` /
198
+ `title` fit the component's purpose, then build the `Image` default from
199
+ its `fileName`:
200
+
201
+ - `url` → `` `https://static.wixstatic.com/media/${fileName}` ``
202
+ - `uri` → `fileName`
203
+ - `alt` → a short human description (use the item's `title` or
204
+ `displayTags`)
205
+
206
+ Do not call this endpoint when the user hasn't asked for it — the
207
+ canonical fallback URL is fine for unattended scaffolds.
208
+
209
+ **Default image pool — use a different image for each slot:**
210
+
211
+ | # | fileName | Description |
212
+ |---|----------|-------------|
213
+ | 1 | `11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg` | Tropical beach aerial |
214
+ | 2 | `11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg` | Dead Sea landscape |
215
+ | 3 | `11062b_3682ebfcb08e4da5b3168b62819a1e68~mv2.jpg` | Palm tree sunset |
216
+ | 4 | `11062b_45e67783d39c4963ab9e4fc418173233~mv2.jpg` | Abstract pink waves |
217
+ | 5 | `11062b_4c11f014b0d04948b2e6f554076bc40a~mv2.jpg` | Coastal village aerial |
218
+
219
+ When a component needs **more than one** image default, cycle through
220
+ the pool above so every slot gets a visually distinct image. For a
221
+ single image, use image #1.
222
+
223
+ **Single `Image` prop:**
224
+
225
+ ```typescript
226
+ export const defaultProps = {
227
+ image: {
228
+ url: "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
229
+ uri: "11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
230
+ alt: "Default image",
231
+ },
232
+ } as const satisfies Omit<ExampleComponentProps, "id" | "className">;
233
+ ```
234
+
235
+ **Array of objects with an `Image` field:**
236
+
237
+ ```typescript
238
+ export const defaultProps = {
239
+ cards: [
240
+ {
241
+ title: "First card",
242
+ image: {
243
+ url: "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
244
+ uri: "11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
245
+ alt: "First card image",
246
+ },
247
+ },
248
+ {
249
+ title: "Second card",
250
+ image: {
251
+ url: "https://static.wixstatic.com/media/11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg",
252
+ uri: "11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg",
253
+ alt: "Second card image",
254
+ },
255
+ },
256
+ ],
257
+ } as const satisfies Omit<ExampleComponentProps, "id" | "className">;
258
+ ```
259
+
260
+ **Inline fallback for HTML `src` / `href`:** when rendering a raw HTML
261
+ attribute that takes a URL (`<img src>`, `<source src>`, `<video poster>`,
262
+ `<a href>` for an image link, etc.) and the value could be empty, fall
263
+ back to the same Wix-hosted URL — never to an external host or a relative
264
+ path that doesn't exist:
265
+
266
+ ```tsx
267
+ <img
268
+ src={
269
+ image?.url ||
270
+ "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg"
271
+ }
272
+ alt={image?.alt || "Default image"}
273
+ />
274
+ ```
275
+
276
+ ### Component File Splitting
277
+
278
+ Split logical UI pieces into separate named components. Never write inline JSX blocks for distinct complex UI pieces.
279
+
280
+ **File structure for complex components (many subcomponents):**
281
+
282
+ ```
283
+ ComponentName/
284
+ ├── components/ # Subcomponents folder
285
+ │ ├── SubComponent1/
286
+ │ │ ├── SubComponent1.tsx
287
+ │ │ ├── SubComponent1.module.scss
288
+ │ │ └── index.ts
289
+ │ └── SubComponent2/
290
+ │ ├── SubComponent2.tsx
291
+ │ └── index.ts
292
+ ├── hooks/ # Custom hooks folder
293
+ │ ├── index.ts
294
+ │ └── useCustomHook.ts
295
+ ```
296
+
297
+ **When to extract a sub-component:**
298
+
299
+ - JSX block represents a logical complex unit (button, control, section, item)
300
+ - Component has its own props interface
301
+ - Logic is reusable or testable independently
302
+ - Block has more than 15-20 lines of JSX
303
+
304
+ ---
305
+
306
+ ## Patterns
307
+
308
+ ### Data-Driven Pattern
309
+
310
+ **❌ Wrong:**
311
+
312
+ ```typescript
313
+ export interface ButtonProps {
314
+ children: React.ReactNode; // ❌
315
+ }
316
+ <Button>Click Me</Button>
317
+ ```
318
+
319
+ **✅ Correct:**
320
+
321
+ ```typescript
322
+ export interface ButtonProps {
323
+ label?: string;
324
+ icon?: string;
325
+ }
326
+ <Button label={label} icon={icon} />
327
+ ```
328
+
329
+ Component controls rendering internally:
330
+
331
+ ```typescript
332
+ const List = ({ items }) => (
333
+ <div>
334
+ {items.map(item => (
335
+ <ListItem key={item.id}>{item.label}</ListItem>
336
+ ))}
337
+ </div>
338
+ );
339
+ ```
340
+
341
+ ### Array Props Pattern
342
+
343
+ Parent defines array structure, child receives single item:
344
+
345
+ ```typescript
346
+ // Parent
347
+ interface ParentProps {
348
+ items: Array<AccordionItem>; // Array defined here
349
+ }
350
+
351
+ interface AccordionItem {
352
+ name: string;
353
+ content: React.ReactNode;
354
+ }
355
+
356
+ // Child receives single item
357
+ interface ChildProps {
358
+ item: AccordionItem & { id: string }; // Single item
359
+ isOpen?: boolean;
360
+ }
361
+
362
+ // Parent maps
363
+ items.map((item, index) => (
364
+ <Child key={index} item={{ ...item, id: index.toString() }} />
365
+ ))
366
+ ```
367
+
368
+ ### Container Components Pattern
369
+
370
+ For "container" or "slot" areas, use `React.ReactNode`:
371
+
372
+ ```typescript
373
+ interface AccordionItem {
374
+ name: string;
375
+ content: React.ReactNode; // Users add any content here
376
+ }
377
+
378
+ // Render
379
+ {items.map((item, index) => (
380
+ <div key={index} dir="ltr">
381
+ {typeof item.content === 'function' ? item.content({}) : item.content}
382
+ </div>
383
+ ))}
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Common Mistakes
389
+
390
+ ### Using children prop in exported interface
391
+
392
+ **❌ Wrong:**
393
+
394
+ ```typescript
395
+ export interface CardProps {
396
+ children: React.ReactNode; // ❌ children + React.ReactNode both forbidden
397
+ }
398
+ <Card><CardHeader>Title</CardHeader></Card>
399
+ ```
400
+
401
+ **✅ Correct:**
402
+
403
+ ```typescript
404
+ export interface CardProps {
405
+ title: string;
406
+ content: React.ReactNode;
407
+ }
408
+ <Card title="Title" content={<div>Content</div>} />
409
+ ```
410
+
411
+ ### Adding elementProps for CSS-only elements
412
+
413
+ **❌ Wrong:**
414
+
415
+ ```typescript
416
+ elementProps?: {
417
+ icon?: { className?: string; } // ❌ Only className
418
+ separator?: { className?: string; } // ❌ Only className
419
+ }
420
+ ```
421
+
422
+ **✅ Correct:**
423
+
424
+ ```typescript
425
+ // No elementProps for purely visual elements (including conditionally displayed)
426
+ // Style via CSS classes directly
427
+ ```
428
+
429
+ **Why:** If element only has `className` (even if it can be hidden/shown via CSS), skip elementProps entirely. Conditional display is controlled via CSS, not React props.
430
+
431
+ ### Using T[] array syntax
432
+
433
+ Use `Array<T>` over `T[]`.
434
+
435
+ **❌ Wrong:**
436
+
437
+ ```typescript
438
+ interface ComponentProps {
439
+ items: Item[]; // ❌ Wrong syntax
440
+ tags: string[]; // ❌ Wrong syntax
441
+ tags: Array<string>; // ❌ Element must be an object with named keys
442
+ }
443
+ ```
444
+
445
+ **✅ Correct:**
446
+
447
+ ```typescript
448
+ interface ComponentProps {
449
+ items: Array<Item>; // ✅ Correct syntax
450
+ tags: Array<{ label: string }>; // ✅ Element is an object with named keys
451
+ }
452
+ ```
453
+
454
+ See also: [Array Element Types: Always Objects with Named Keys](#array-element-types-always-objects-with-named-keys) — items must be objects with named keys.