@julianoczkowski/create-trimble-app 2.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 (450) hide show
  1. package/README.md +191 -0
  2. package/bin/create-trimble-app.js +9 -0
  3. package/package.json +67 -0
  4. package/src/cli.js +134 -0
  5. package/src/frameworks.js +28 -0
  6. package/src/scaffold.js +209 -0
  7. package/src/utils/file.js +47 -0
  8. package/src/utils/git.js +140 -0
  9. package/src/utils/install.js +25 -0
  10. package/src/utils/logger.js +124 -0
  11. package/templates/angular/.cursor/commands/remove-dev-content.md +394 -0
  12. package/templates/angular/.cursor/mcp.json +13 -0
  13. package/templates/angular/.cursor/rules/modus-angular-20.mdc +82 -0
  14. package/templates/angular/.cursor/rules/modus-angular-accordion-state-management-short.mdc +45 -0
  15. package/templates/angular/.cursor/rules/modus-angular-accordion-state-management.mdc +322 -0
  16. package/templates/angular/.cursor/rules/modus-angular-best-practices.mdc +472 -0
  17. package/templates/angular/.cursor/rules/modus-angular-border-usage-short.mdc +48 -0
  18. package/templates/angular/.cursor/rules/modus-angular-border-usage.mdc +286 -0
  19. package/templates/angular/.cursor/rules/modus-angular-button-group-usage-short.mdc +47 -0
  20. package/templates/angular/.cursor/rules/modus-angular-button-group-usage.mdc +263 -0
  21. package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion-short.mdc +36 -0
  22. package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion.mdc +92 -0
  23. package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing-short.mdc +34 -0
  24. package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing.mdc +185 -0
  25. package/templates/angular/.cursor/rules/modus-angular-color-usage-short.mdc +56 -0
  26. package/templates/angular/.cursor/rules/modus-angular-color-usage.mdc +208 -0
  27. package/templates/angular/.cursor/rules/modus-angular-components-reference.mdc +114 -0
  28. package/templates/angular/.cursor/rules/modus-angular-design-system.mdc +273 -0
  29. package/templates/angular/.cursor/rules/modus-angular-development-workflow-short.mdc +43 -0
  30. package/templates/angular/.cursor/rules/modus-angular-development-workflow.mdc +145 -0
  31. package/templates/angular/.cursor/rules/modus-angular-essentials.mdc +272 -0
  32. package/templates/angular/.cursor/rules/modus-angular-forms-validation-short.mdc +56 -0
  33. package/templates/angular/.cursor/rules/modus-angular-forms-validation.mdc +124 -0
  34. package/templates/angular/.cursor/rules/modus-angular-icon-names.mdc +70 -0
  35. package/templates/angular/.cursor/rules/modus-angular-icons-short.mdc +40 -0
  36. package/templates/angular/.cursor/rules/modus-angular-icons.mdc +137 -0
  37. package/templates/angular/.cursor/rules/modus-angular-implementation-guides-short.mdc +36 -0
  38. package/templates/angular/.cursor/rules/modus-angular-implementation-guides.mdc +301 -0
  39. package/templates/angular/.cursor/rules/modus-angular-integration-short.mdc +60 -0
  40. package/templates/angular/.cursor/rules/modus-angular-integration.mdc +1096 -0
  41. package/templates/angular/.cursor/rules/modus-angular-master.mdc +164 -0
  42. package/templates/angular/.cursor/rules/modus-angular-modal-usage-short.mdc +51 -0
  43. package/templates/angular/.cursor/rules/modus-angular-modal-usage.mdc +115 -0
  44. package/templates/angular/.cursor/rules/modus-angular-navbar-usage-short.mdc +49 -0
  45. package/templates/angular/.cursor/rules/modus-angular-navbar-usage.mdc +146 -0
  46. package/templates/angular/.cursor/rules/modus-angular-no-emojis.mdc +66 -0
  47. package/templates/angular/.cursor/rules/modus-angular-opacity-utilities-short.mdc +43 -0
  48. package/templates/angular/.cursor/rules/modus-angular-opacity-utilities.mdc +160 -0
  49. package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu-short.mdc +51 -0
  50. package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu.mdc +83 -0
  51. package/templates/angular/.cursor/rules/modus-angular-semantic-html-short.mdc +36 -0
  52. package/templates/angular/.cursor/rules/modus-angular-semantic-html.mdc +81 -0
  53. package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage-short.mdc +50 -0
  54. package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage.mdc +136 -0
  55. package/templates/angular/.cursor/rules/modus-angular-table-usage-short.mdc +52 -0
  56. package/templates/angular/.cursor/rules/modus-angular-table-usage.mdc +151 -0
  57. package/templates/angular/.cursor/rules/modus-angular-tailwind-usage-short.mdc +44 -0
  58. package/templates/angular/.cursor/rules/modus-angular-tailwind-usage.mdc +242 -0
  59. package/templates/angular/.cursor/rules/modus-angular-themes-short.mdc +54 -0
  60. package/templates/angular/.cursor/rules/modus-angular-themes.mdc +222 -0
  61. package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage-short.mdc +52 -0
  62. package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage.mdc +130 -0
  63. package/templates/angular/.cursor/rules/ux/gestalt-laws-detailed.mdc +514 -0
  64. package/templates/angular/.cursor/rules/ux/ux-ui-foundations.mdc +235 -0
  65. package/templates/angular/.cursor/skills/run-lint-checks/SKILL.md +169 -0
  66. package/templates/angular/.editorconfig +17 -0
  67. package/templates/angular/.github/dependabot.yml +19 -0
  68. package/templates/angular/.github/workflows/a11y-check.yml +135 -0
  69. package/templates/angular/.github/workflows/ci.yml +44 -0
  70. package/templates/angular/.husky/pre-commit +32 -0
  71. package/templates/angular/.postcssrc.json +5 -0
  72. package/templates/angular/.vscode/extensions.json +4 -0
  73. package/templates/angular/.vscode/launch.json +20 -0
  74. package/templates/angular/.vscode/tasks.json +42 -0
  75. package/templates/angular/CLAUDE.md +148 -0
  76. package/templates/angular/README.md +92 -0
  77. package/templates/angular/amplify.yml +25 -0
  78. package/templates/angular/angular.json +106 -0
  79. package/templates/angular/data/modusIcons.ts +861 -0
  80. package/templates/angular/package-lock.json +11030 -0
  81. package/templates/angular/package.json +66 -0
  82. package/templates/angular/public/angular-icon.svg +12 -0
  83. package/templates/angular/public/favicon.ico +0 -0
  84. package/templates/angular/public/modus-icons.css +49 -0
  85. package/templates/angular/public/vite.svg +1 -0
  86. package/templates/angular/scripts/README.md +410 -0
  87. package/templates/angular/scripts/check-border-violations.js +352 -0
  88. package/templates/angular/scripts/check-icon-names.js +402 -0
  89. package/templates/angular/scripts/check-inline-styles.js +292 -0
  90. package/templates/angular/scripts/check-modus-colors.js +282 -0
  91. package/templates/angular/scripts/check-modus-icons.js +263 -0
  92. package/templates/angular/scripts/check-opacity-utilities.js +426 -0
  93. package/templates/angular/scripts/check-semantic-html.js +452 -0
  94. package/templates/angular/scripts/check-typescript.js +109 -0
  95. package/templates/angular/src/app/app.config.ts +29 -0
  96. package/templates/angular/src/app/app.css +0 -0
  97. package/templates/angular/src/app/app.html +4 -0
  98. package/templates/angular/src/app/app.routes.ts +351 -0
  99. package/templates/angular/src/app/app.spec.ts +27 -0
  100. package/templates/angular/src/app/app.ts +47 -0
  101. package/templates/angular/src/app/components/README.md +77 -0
  102. package/templates/angular/src/app/components/index.ts +53 -0
  103. package/templates/angular/src/app/components/modus-accordion.component.ts +50 -0
  104. package/templates/angular/src/app/components/modus-alert.component.ts +133 -0
  105. package/templates/angular/src/app/components/modus-autocomplete.component.ts +262 -0
  106. package/templates/angular/src/app/components/modus-avatar.component.ts +75 -0
  107. package/templates/angular/src/app/components/modus-badge.component.ts +84 -0
  108. package/templates/angular/src/app/components/modus-breadcrumbs.component.ts +65 -0
  109. package/templates/angular/src/app/components/modus-button-group.component.ts +82 -0
  110. package/templates/angular/src/app/components/modus-button.component.ts +292 -0
  111. package/templates/angular/src/app/components/modus-card.component.ts +73 -0
  112. package/templates/angular/src/app/components/modus-checkbox.component.ts +117 -0
  113. package/templates/angular/src/app/components/modus-chip.component.ts +97 -0
  114. package/templates/angular/src/app/components/modus-collapse.component.ts +118 -0
  115. package/templates/angular/src/app/components/modus-date.component.ts +165 -0
  116. package/templates/angular/src/app/components/modus-dropdown-menu.component.ts +108 -0
  117. package/templates/angular/src/app/components/modus-file-dropzone.component.ts +121 -0
  118. package/templates/angular/src/app/components/modus-handle.component.ts +96 -0
  119. package/templates/angular/src/app/components/modus-icon.component.ts +81 -0
  120. package/templates/angular/src/app/components/modus-input-feedback.component.ts +54 -0
  121. package/templates/angular/src/app/components/modus-input-label.component.ts +62 -0
  122. package/templates/angular/src/app/components/modus-loader.component.ts +48 -0
  123. package/templates/angular/src/app/components/modus-logo.component.ts +115 -0
  124. package/templates/angular/src/app/components/modus-menu-item.component.ts +116 -0
  125. package/templates/angular/src/app/components/modus-menu.component.ts +58 -0
  126. package/templates/angular/src/app/components/modus-modal.component.ts +70 -0
  127. package/templates/angular/src/app/components/modus-navbar.component.ts +303 -0
  128. package/templates/angular/src/app/components/modus-number-input.component.ts +174 -0
  129. package/templates/angular/src/app/components/modus-pagination.component.ts +74 -0
  130. package/templates/angular/src/app/components/modus-panel.component.ts +61 -0
  131. package/templates/angular/src/app/components/modus-progress.component.ts +62 -0
  132. package/templates/angular/src/app/components/modus-radio.component.ts +102 -0
  133. package/templates/angular/src/app/components/modus-rating.component.ts +80 -0
  134. package/templates/angular/src/app/components/modus-select.component.ts +131 -0
  135. package/templates/angular/src/app/components/modus-side-navigation.component.ts +90 -0
  136. package/templates/angular/src/app/components/modus-skeleton.component.ts +54 -0
  137. package/templates/angular/src/app/components/modus-slider.component.ts +132 -0
  138. package/templates/angular/src/app/components/modus-stepper.component.ts +65 -0
  139. package/templates/angular/src/app/components/modus-switch.component.ts +118 -0
  140. package/templates/angular/src/app/components/modus-table.component.ts +204 -0
  141. package/templates/angular/src/app/components/modus-tabs.component.ts +82 -0
  142. package/templates/angular/src/app/components/modus-text-input.component.ts +221 -0
  143. package/templates/angular/src/app/components/modus-textarea.component.ts +168 -0
  144. package/templates/angular/src/app/components/modus-theme-switcher.component.ts +45 -0
  145. package/templates/angular/src/app/components/modus-time-input.component.ts +172 -0
  146. package/templates/angular/src/app/components/modus-toast.component.ts +63 -0
  147. package/templates/angular/src/app/components/modus-toolbar.component.ts +43 -0
  148. package/templates/angular/src/app/components/modus-tooltip.component.ts +83 -0
  149. package/templates/angular/src/app/components/modus-typography.component.ts +79 -0
  150. package/templates/angular/src/app/components/modus-utility-panel.component.ts +275 -0
  151. package/templates/angular/src/app/components/theme-demo.component.ts +1242 -0
  152. package/templates/angular/src/app/data/component-demos.ts +360 -0
  153. package/templates/angular/src/app/data/modus-icons.ts +806 -0
  154. package/templates/angular/src/app/demos/accordion/accordion-demo.component.ts +212 -0
  155. package/templates/angular/src/app/demos/alert/alert-demo.component.ts +108 -0
  156. package/templates/angular/src/app/demos/autocomplete/autocomplete-demo.component.ts +174 -0
  157. package/templates/angular/src/app/demos/avatar/avatar-demo.component.ts +149 -0
  158. package/templates/angular/src/app/demos/badge/badge-demo.component.ts +148 -0
  159. package/templates/angular/src/app/demos/breadcrumbs/breadcrumbs-demo.component.ts +96 -0
  160. package/templates/angular/src/app/demos/button/button-demo.component.ts +256 -0
  161. package/templates/angular/src/app/demos/button-group/button-group-demo.component.ts +215 -0
  162. package/templates/angular/src/app/demos/card/card-demo.component.ts +180 -0
  163. package/templates/angular/src/app/demos/checkbox/checkbox-demo.component.ts +71 -0
  164. package/templates/angular/src/app/demos/chip/chip-demo.component.ts +183 -0
  165. package/templates/angular/src/app/demos/date/date-demo.component.ts +193 -0
  166. package/templates/angular/src/app/demos/dropdown/dropdown-demo.component.ts +196 -0
  167. package/templates/angular/src/app/demos/file-dropzone/file-dropzone-demo.component.ts +176 -0
  168. package/templates/angular/src/app/demos/handle/handle-demo.component.ts +265 -0
  169. package/templates/angular/src/app/demos/icon/icon-demo.component.ts +65 -0
  170. package/templates/angular/src/app/demos/input-feedback/input-feedback-demo.component.ts +189 -0
  171. package/templates/angular/src/app/demos/input-label/input-label-demo.component.ts +330 -0
  172. package/templates/angular/src/app/demos/loader/loader-demo.component.ts +143 -0
  173. package/templates/angular/src/app/demos/logo/logo-demo.component.ts +191 -0
  174. package/templates/angular/src/app/demos/menu/menu-demo.component.ts +72 -0
  175. package/templates/angular/src/app/demos/modal/modal-demo.component.ts +278 -0
  176. package/templates/angular/src/app/demos/navbar/navbar-demo.component.ts +135 -0
  177. package/templates/angular/src/app/demos/number-input/number-input-demo.component.ts +175 -0
  178. package/templates/angular/src/app/demos/pagination/pagination-demo.component.ts +134 -0
  179. package/templates/angular/src/app/demos/panel/panel-demo.component.ts +235 -0
  180. package/templates/angular/src/app/demos/progress/progress-demo.component.ts +169 -0
  181. package/templates/angular/src/app/demos/radio/radio-demo.component.ts +161 -0
  182. package/templates/angular/src/app/demos/rating/rating-demo.component.ts +97 -0
  183. package/templates/angular/src/app/demos/select/select-demo.component.ts +107 -0
  184. package/templates/angular/src/app/demos/shared/demo-example-clean.component.ts +41 -0
  185. package/templates/angular/src/app/demos/shared/demo-example.component.ts +42 -0
  186. package/templates/angular/src/app/demos/shared/demo-page.component.ts +97 -0
  187. package/templates/angular/src/app/demos/shared/index.ts +3 -0
  188. package/templates/angular/src/app/demos/side-navigation/side-navigation-demo.component.ts +524 -0
  189. package/templates/angular/src/app/demos/skeleton/skeleton-demo.component.ts +112 -0
  190. package/templates/angular/src/app/demos/slider/slider-demo.component.ts +76 -0
  191. package/templates/angular/src/app/demos/stepper/stepper-demo.component.ts +79 -0
  192. package/templates/angular/src/app/demos/switch/switch-demo.component.ts +113 -0
  193. package/templates/angular/src/app/demos/table/table-demo.component.ts +405 -0
  194. package/templates/angular/src/app/demos/tabs/tabs-demo.component.ts +318 -0
  195. package/templates/angular/src/app/demos/text-input/text-input-demo.component.ts +160 -0
  196. package/templates/angular/src/app/demos/textarea/textarea-demo.component.ts +95 -0
  197. package/templates/angular/src/app/demos/theme-switcher/theme-switcher-demo.component.ts +38 -0
  198. package/templates/angular/src/app/demos/time-input/time-input-demo.component.ts +130 -0
  199. package/templates/angular/src/app/demos/toast/toast-demo.component.ts +258 -0
  200. package/templates/angular/src/app/demos/toolbar/toolbar-demo.component.ts +54 -0
  201. package/templates/angular/src/app/demos/tooltip/tooltip-demo.component.ts +163 -0
  202. package/templates/angular/src/app/demos/utility-panel/utility-panel-demo.component.ts +197 -0
  203. package/templates/angular/src/app/dev/dev-config.ts +119 -0
  204. package/templates/angular/src/app/dev/dev-panel/dev-panel.component.ts +215 -0
  205. package/templates/angular/src/app/dev/dev-panel.service.ts +63 -0
  206. package/templates/angular/src/app/dev/index.ts +8 -0
  207. package/templates/angular/src/app/dev/theme-switcher-dropdown/theme-switcher-dropdown.component.ts +134 -0
  208. package/templates/angular/src/app/dev-pages/color-palette/color-palette.component.ts +229 -0
  209. package/templates/angular/src/app/dev-pages/components-gallery/components-gallery.component.ts +486 -0
  210. package/templates/angular/src/app/dev-pages/icons/icons.component.ts +149 -0
  211. package/templates/angular/src/app/pages/home/home.component.ts +251 -0
  212. package/templates/angular/src/app/services/README.md +57 -0
  213. package/templates/angular/src/app/services/theme.service.ts +163 -0
  214. package/templates/angular/src/environments/environment.development.ts +8 -0
  215. package/templates/angular/src/environments/environment.ts +8 -0
  216. package/templates/angular/src/index.html +14 -0
  217. package/templates/angular/src/main.ts +6 -0
  218. package/templates/angular/src/styles.css +1328 -0
  219. package/templates/angular/tsconfig.app.json +15 -0
  220. package/templates/angular/tsconfig.json +35 -0
  221. package/templates/angular/tsconfig.spec.json +14 -0
  222. package/templates/config.json +23 -0
  223. package/templates/react/.cursor/commands/remove-dev-content.md +311 -0
  224. package/templates/react/.cursor/mcp.json +13 -0
  225. package/templates/react/.cursor/rules/README.md +240 -0
  226. package/templates/react/.cursor/rules/border-usage-guidelines-short.mdc +22 -0
  227. package/templates/react/.cursor/rules/border-usage-guidelines.mdc +380 -0
  228. package/templates/react/.cursor/rules/chrome-devtools-testing-react-short.mdc +23 -0
  229. package/templates/react/.cursor/rules/development-workflow-react-short.mdc +23 -0
  230. package/templates/react/.cursor/rules/development-workflow-react.mdc +292 -0
  231. package/templates/react/.cursor/rules/implementation-guides-react-short.mdc +23 -0
  232. package/templates/react/.cursor/rules/implementation-guides-react.mdc +446 -0
  233. package/templates/react/.cursor/rules/modus-accordion-state-management-react-short.mdc +23 -0
  234. package/templates/react/.cursor/rules/modus-accordion-state-management-react.mdc +445 -0
  235. package/templates/react/.cursor/rules/modus-button-group-usage-react-short.mdc +23 -0
  236. package/templates/react/.cursor/rules/modus-button-group-usage-react.mdc +117 -0
  237. package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react-short.mdc +23 -0
  238. package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react.mdc +492 -0
  239. package/templates/react/.cursor/rules/modus-color-usage-react-short.mdc +23 -0
  240. package/templates/react/.cursor/rules/modus-color-usage-react.mdc +420 -0
  241. package/templates/react/.cursor/rules/modus-components-reference.mdc +366 -0
  242. package/templates/react/.cursor/rules/modus-icon-names.mdc +63 -0
  243. package/templates/react/.cursor/rules/modus-icons-react-short.mdc +24 -0
  244. package/templates/react/.cursor/rules/modus-icons-react.mdc +402 -0
  245. package/templates/react/.cursor/rules/modus-modal-implementation-react-short.mdc +23 -0
  246. package/templates/react/.cursor/rules/modus-modal-implementation-react.mdc +831 -0
  247. package/templates/react/.cursor/rules/modus-navbar-side-navigation-react-short.mdc +23 -0
  248. package/templates/react/.cursor/rules/modus-navbar-side-navigation-react.mdc +247 -0
  249. package/templates/react/.cursor/rules/modus-no-emojis-react-short.mdc +23 -0
  250. package/templates/react/.cursor/rules/modus-opacity-utilities-react-short.mdc +70 -0
  251. package/templates/react/.cursor/rules/modus-opacity-utilities-react.mdc +208 -0
  252. package/templates/react/.cursor/rules/modus-react-best-practices-short.mdc +23 -0
  253. package/templates/react/.cursor/rules/modus-react-best-practices.mdc +508 -0
  254. package/templates/react/.cursor/rules/modus-react-essentials.mdc +209 -0
  255. package/templates/react/.cursor/rules/modus-react-integration-short.mdc +23 -0
  256. package/templates/react/.cursor/rules/modus-react-integration.mdc +509 -0
  257. package/templates/react/.cursor/rules/modus-react-key-warnings-short.mdc +23 -0
  258. package/templates/react/.cursor/rules/modus-react-key-warnings.mdc +805 -0
  259. package/templates/react/.cursor/rules/modus-react-master.mdc +160 -0
  260. package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react-short.mdc +23 -0
  261. package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react.mdc +442 -0
  262. package/templates/react/.cursor/rules/modus-semantic-html-react-short.mdc +23 -0
  263. package/templates/react/.cursor/rules/modus-semantic-html-react.mdc +427 -0
  264. package/templates/react/.cursor/rules/modus-tailwind-usage-react-short.mdc +23 -0
  265. package/templates/react/.cursor/rules/modus-tailwind-usage-react.mdc +642 -0
  266. package/templates/react/.cursor/rules/modus-themes-react-short.mdc +23 -0
  267. package/templates/react/.cursor/rules/modus-themes-react.mdc +506 -0
  268. package/templates/react/.cursor/rules/ux/gestalt-laws-detailed.mdc +456 -0
  269. package/templates/react/.cursor/rules/ux/ux-ui-foundations.mdc +211 -0
  270. package/templates/react/.cursor/skills/create-modus-form-component/SKILL.md +518 -0
  271. package/templates/react/.cursor/skills/create-modus-wrapper-component/SKILL.md +252 -0
  272. package/templates/react/.cursor/skills/fix-modus-component-event-issues/SKILL.md +345 -0
  273. package/templates/react/.cursor/skills/handle-modus-checkbox-value-bug/SKILL.md +202 -0
  274. package/templates/react/.cursor/skills/implement-modus-modal-with-refs/SKILL.md +386 -0
  275. package/templates/react/.cursor/skills/integrate-modus-icons/SKILL.md +300 -0
  276. package/templates/react/.cursor/skills/run-lint-checks/SKILL.md +235 -0
  277. package/templates/react/.cursor/skills/set-up-modus-event-listeners/SKILL.md +284 -0
  278. package/templates/react/.cursor/skills/style-modus-components-with-tailwind/SKILL.md +382 -0
  279. package/templates/react/.env.development +3 -0
  280. package/templates/react/.env.production +3 -0
  281. package/templates/react/.github/CODEOWNERS +28 -0
  282. package/templates/react/.github/ISSUE_TEMPLATE/bug_report.yml +176 -0
  283. package/templates/react/.github/ISSUE_TEMPLATE/config.yml +20 -0
  284. package/templates/react/.github/ISSUE_TEMPLATE/documentation.yml +115 -0
  285. package/templates/react/.github/ISSUE_TEMPLATE/feature_request.yml +171 -0
  286. package/templates/react/.github/ISSUE_TEMPLATE/question.yml +139 -0
  287. package/templates/react/.github/copilot-instructions.md +80 -0
  288. package/templates/react/.github/instructions/components.instructions.md +82 -0
  289. package/templates/react/.github/instructions/demos.instructions.md +82 -0
  290. package/templates/react/.github/instructions/pages.instructions.md +76 -0
  291. package/templates/react/.github/instructions/styles.instructions.md +77 -0
  292. package/templates/react/.github/instructions/typescript.instructions.md +101 -0
  293. package/templates/react/.github/pull_request_template.md +188 -0
  294. package/templates/react/.github/workflows/ci.yml +43 -0
  295. package/templates/react/.github/workflows/claude-code-review.yml +44 -0
  296. package/templates/react/.github/workflows/claude.yml +50 -0
  297. package/templates/react/.husky/pre-commit +28 -0
  298. package/templates/react/.vscode/extensions.json +8 -0
  299. package/templates/react/CLAUDE.md +119 -0
  300. package/templates/react/CODE_OF_CONDUCT.md +79 -0
  301. package/templates/react/CONTRIBUTING.md +65 -0
  302. package/templates/react/LICENSE +21 -0
  303. package/templates/react/README.md +728 -0
  304. package/templates/react/SECURITY.md +50 -0
  305. package/templates/react/eslint.config.js +23 -0
  306. package/templates/react/index.html +13 -0
  307. package/templates/react/package-lock.json +5209 -0
  308. package/templates/react/package.json +49 -0
  309. package/templates/react/postcss.config.js +6 -0
  310. package/templates/react/public/react.svg +1 -0
  311. package/templates/react/public/vite.svg +1 -0
  312. package/templates/react/readme_assets/getting_started_header.png +0 -0
  313. package/templates/react/readme_assets/hero.png +0 -0
  314. package/templates/react/readme_assets/modus_comp.png +0 -0
  315. package/templates/react/readme_assets/modus_figma_mcp.png +0 -0
  316. package/templates/react/readme_assets/teaser_comp.gif +0 -0
  317. package/templates/react/scripts/README.md +343 -0
  318. package/templates/react/scripts/check-border-violations.js +483 -0
  319. package/templates/react/scripts/check-icon-names.js +486 -0
  320. package/templates/react/scripts/check-inline-styles.js +364 -0
  321. package/templates/react/scripts/check-modus-colors.js +247 -0
  322. package/templates/react/scripts/check-modus-icons.js +256 -0
  323. package/templates/react/scripts/check-opacity-utilities.js +481 -0
  324. package/templates/react/scripts/check-semantic-html.js +476 -0
  325. package/templates/react/scripts/check-typescript.js +109 -0
  326. package/templates/react/src/App.css +42 -0
  327. package/templates/react/src/App.tsx +54 -0
  328. package/templates/react/src/assets/react.svg +1 -0
  329. package/templates/react/src/components/DemoExample.tsx +61 -0
  330. package/templates/react/src/components/DemoPage.tsx +81 -0
  331. package/templates/react/src/components/ModusAccordion.tsx +89 -0
  332. package/templates/react/src/components/ModusAlert.tsx +85 -0
  333. package/templates/react/src/components/ModusAutocomplete.tsx +207 -0
  334. package/templates/react/src/components/ModusAvatar.tsx +50 -0
  335. package/templates/react/src/components/ModusBadge.tsx +82 -0
  336. package/templates/react/src/components/ModusBreadcrumbs.tsx +75 -0
  337. package/templates/react/src/components/ModusButton.tsx +244 -0
  338. package/templates/react/src/components/ModusButtonGroup.tsx +91 -0
  339. package/templates/react/src/components/ModusCard.tsx +70 -0
  340. package/templates/react/src/components/ModusCheckbox.tsx +168 -0
  341. package/templates/react/src/components/ModusChip.tsx +93 -0
  342. package/templates/react/src/components/ModusDate.tsx +154 -0
  343. package/templates/react/src/components/ModusDropdownMenu.tsx +148 -0
  344. package/templates/react/src/components/ModusFileDropzone.tsx +140 -0
  345. package/templates/react/src/components/ModusHandle.tsx +101 -0
  346. package/templates/react/src/components/ModusIcon.tsx +49 -0
  347. package/templates/react/src/components/ModusInputFeedback.tsx +52 -0
  348. package/templates/react/src/components/ModusInputLabel.tsx +50 -0
  349. package/templates/react/src/components/ModusLoader.tsx +42 -0
  350. package/templates/react/src/components/ModusLogo.tsx +102 -0
  351. package/templates/react/src/components/ModusMenu.tsx +119 -0
  352. package/templates/react/src/components/ModusMenuItem.tsx +86 -0
  353. package/templates/react/src/components/ModusModal.tsx +145 -0
  354. package/templates/react/src/components/ModusNavbar.tsx +504 -0
  355. package/templates/react/src/components/ModusNumberInput.tsx +230 -0
  356. package/templates/react/src/components/ModusPagination.tsx +94 -0
  357. package/templates/react/src/components/ModusPanel.tsx +92 -0
  358. package/templates/react/src/components/ModusProgress.tsx +70 -0
  359. package/templates/react/src/components/ModusProvider.tsx +18 -0
  360. package/templates/react/src/components/ModusRadio.tsx +114 -0
  361. package/templates/react/src/components/ModusRating.tsx +108 -0
  362. package/templates/react/src/components/ModusSelect.tsx +171 -0
  363. package/templates/react/src/components/ModusSideNavigation.tsx +149 -0
  364. package/templates/react/src/components/ModusSkeleton.tsx +42 -0
  365. package/templates/react/src/components/ModusSlider.tsx +128 -0
  366. package/templates/react/src/components/ModusStepper.tsx +85 -0
  367. package/templates/react/src/components/ModusSwitch.tsx +130 -0
  368. package/templates/react/src/components/ModusTable.tsx +309 -0
  369. package/templates/react/src/components/ModusTabs.tsx +114 -0
  370. package/templates/react/src/components/ModusTextInput.tsx +179 -0
  371. package/templates/react/src/components/ModusTextarea.tsx +164 -0
  372. package/templates/react/src/components/ModusThemeSwitcher.tsx +58 -0
  373. package/templates/react/src/components/ModusTimeInput.tsx +176 -0
  374. package/templates/react/src/components/ModusToast.tsx +207 -0
  375. package/templates/react/src/components/ModusToolbar.tsx +70 -0
  376. package/templates/react/src/components/ModusTooltip.tsx +97 -0
  377. package/templates/react/src/components/ModusUtilityPanel.tsx +198 -0
  378. package/templates/react/src/components/ThemeSwitcherDropdown.tsx +117 -0
  379. package/templates/react/src/components/ThemeToggleSimple.tsx +157 -0
  380. package/templates/react/src/config/routes.ts +196 -0
  381. package/templates/react/src/contexts/ThemeContext.tsx +81 -0
  382. package/templates/react/src/contexts/ThemeContextData.tsx +89 -0
  383. package/templates/react/src/data/modusIcons.ts +865 -0
  384. package/templates/react/src/demos/accordion-demo/page.tsx +236 -0
  385. package/templates/react/src/demos/alert-demo/page.tsx +94 -0
  386. package/templates/react/src/demos/autocomplete-demo/page.tsx +166 -0
  387. package/templates/react/src/demos/avatar-demo/page.tsx +135 -0
  388. package/templates/react/src/demos/badge-demo/page.tsx +174 -0
  389. package/templates/react/src/demos/breadcrumbs-demo/page.tsx +88 -0
  390. package/templates/react/src/demos/button-demo/page.tsx +261 -0
  391. package/templates/react/src/demos/button-group-demo/page.tsx +231 -0
  392. package/templates/react/src/demos/card-demo/page.tsx +241 -0
  393. package/templates/react/src/demos/checkbox-demo/page.tsx +79 -0
  394. package/templates/react/src/demos/chip-demo/page.tsx +197 -0
  395. package/templates/react/src/demos/date-demo/page.tsx +179 -0
  396. package/templates/react/src/demos/dropdown-demo/page.tsx +150 -0
  397. package/templates/react/src/demos/file-dropzone-demo/page.tsx +186 -0
  398. package/templates/react/src/demos/handle-demo/page.tsx +313 -0
  399. package/templates/react/src/demos/icon-demo/page.tsx +72 -0
  400. package/templates/react/src/demos/input-feedback-demo/page.tsx +202 -0
  401. package/templates/react/src/demos/input-label-demo/page.tsx +392 -0
  402. package/templates/react/src/demos/loader-demo/page.tsx +138 -0
  403. package/templates/react/src/demos/logo-demo/page.tsx +292 -0
  404. package/templates/react/src/demos/menu-demo/page.tsx +70 -0
  405. package/templates/react/src/demos/modal-demo/page.tsx +332 -0
  406. package/templates/react/src/demos/navbar-demo/page.tsx +141 -0
  407. package/templates/react/src/demos/number-input-demo/page.tsx +180 -0
  408. package/templates/react/src/demos/pagination-demo/page.tsx +147 -0
  409. package/templates/react/src/demos/panel-demo/page.tsx +376 -0
  410. package/templates/react/src/demos/progress-demo/page.tsx +185 -0
  411. package/templates/react/src/demos/radio-demo/page.tsx +242 -0
  412. package/templates/react/src/demos/rating-demo/page.tsx +97 -0
  413. package/templates/react/src/demos/select-demo/page.tsx +111 -0
  414. package/templates/react/src/demos/side-navigation-demo/page.tsx +775 -0
  415. package/templates/react/src/demos/skeleton-demo/page.tsx +107 -0
  416. package/templates/react/src/demos/slider-demo/page.tsx +78 -0
  417. package/templates/react/src/demos/stepper-demo/page.tsx +86 -0
  418. package/templates/react/src/demos/switch-demo/page.tsx +146 -0
  419. package/templates/react/src/demos/table-demo/page.tsx +489 -0
  420. package/templates/react/src/demos/tabs-demo/page.tsx +187 -0
  421. package/templates/react/src/demos/text-input-demo/page.tsx +151 -0
  422. package/templates/react/src/demos/textarea-demo/page.tsx +73 -0
  423. package/templates/react/src/demos/theme-switcher-demo/page.tsx +26 -0
  424. package/templates/react/src/demos/time-input-demo/page.tsx +148 -0
  425. package/templates/react/src/demos/toast-demo/page.tsx +302 -0
  426. package/templates/react/src/demos/toolbar-demo/page.tsx +49 -0
  427. package/templates/react/src/demos/tooltip-demo/page.tsx +209 -0
  428. package/templates/react/src/demos/typography-test/page.tsx +28 -0
  429. package/templates/react/src/demos/utility-panel-demo/page.tsx +197 -0
  430. package/templates/react/src/dev/DevPanel.tsx +219 -0
  431. package/templates/react/src/dev/DevPanelContext.ts +14 -0
  432. package/templates/react/src/dev/DevPanelProvider.tsx +63 -0
  433. package/templates/react/src/dev/DevRoutes.tsx +98 -0
  434. package/templates/react/src/dev/config.ts +127 -0
  435. package/templates/react/src/dev/index.ts +8 -0
  436. package/templates/react/src/dev/useDevPanel.ts +17 -0
  437. package/templates/react/src/dev-pages/ColorPalettePage.tsx +347 -0
  438. package/templates/react/src/dev-pages/ComponentsGalleryPage.tsx +489 -0
  439. package/templates/react/src/dev-pages/IconsPage.tsx +137 -0
  440. package/templates/react/src/dev-pages/index.ts +3 -0
  441. package/templates/react/src/hooks/useTheme.ts +15 -0
  442. package/templates/react/src/index.css +635 -0
  443. package/templates/react/src/main.tsx +14 -0
  444. package/templates/react/src/pages/HomePage.tsx +283 -0
  445. package/templates/react/src/vite-env.d.ts +9 -0
  446. package/templates/react/tailwind.config.js +58 -0
  447. package/templates/react/tsconfig.app.json +27 -0
  448. package/templates/react/tsconfig.json +7 -0
  449. package/templates/react/tsconfig.node.json +25 -0
  450. package/templates/react/vite.config.ts +18 -0
@@ -0,0 +1,202 @@
1
+ ---
2
+ name: handle-modus-checkbox-value-bug
3
+ description: Apply the critical checkbox value inversion workaround when working with ModusCheckbox components
4
+ ---
5
+
6
+ # Handle Modus Checkbox Value Bug
7
+
8
+ Apply the critical value inversion workaround for ModusWcCheckbox components.
9
+
10
+ ## Critical Bug
11
+
12
+ The `ModusWcCheckbox` web component has a **value inversion bug** where the `value` property returns the **opposite** of the actual checked state:
13
+
14
+ - When checkbox is **checked**: `target.value` returns `false`
15
+ - When checkbox is **unchecked**: `target.value` returns `true`
16
+
17
+ This is the **opposite** of what developers expect.
18
+
19
+ ## When to Use
20
+
21
+ Use this skill when:
22
+ - Implementing checkbox functionality with ModusCheckbox
23
+ - Fixing checkbox-related bugs
24
+ - Handling checkbox value changes
25
+ - Creating forms with checkboxes
26
+
27
+ ## Reference Implementation
28
+
29
+ See `src/components/ModusCheckbox.tsx:116-130` for the complete workaround implementation.
30
+
31
+ ## The Fix
32
+
33
+ Always invert the value when reading from checkbox events:
34
+
35
+ ```tsx
36
+ const handleValueChange = (event: Event) => {
37
+ const customEvent = event as CustomEvent<InputEvent>;
38
+
39
+ // 🚨 CRITICAL: Handle the value inversion bug
40
+ const rawValue = (customEvent.target as HTMLModusWcCheckboxElement).value;
41
+ const actualValue = !rawValue; // ✅ CORRECT: Invert the value
42
+
43
+ // Use actualValue for your logic
44
+ setChecked(actualValue);
45
+ };
46
+ ```
47
+
48
+ ## Complete Pattern
49
+
50
+ ```tsx
51
+ import { useEffect, useRef } from "react";
52
+ import { ModusWcCheckbox } from "@trimble-oss/moduswebcomponents-react";
53
+
54
+ export default function ModusCheckbox({
55
+ value = false,
56
+ onValueChange,
57
+ }: {
58
+ value?: boolean;
59
+ onValueChange?: (event: CustomEvent<boolean>) => void;
60
+ }) {
61
+ const checkboxRef = useRef<HTMLModusWcCheckboxElement>(null);
62
+
63
+ useEffect(() => {
64
+ const checkbox = checkboxRef.current;
65
+ if (!checkbox) return;
66
+
67
+ const handleValueChange = (event: Event) => {
68
+ const customEvent = event as CustomEvent<InputEvent>;
69
+
70
+ // 🚨 CRITICAL BUG WORKAROUND: The ModusWcCheckbox component has a value
71
+ // inversion bug where the `value` property returns the opposite of the
72
+ // actual checked state. This function corrects this by inverting the
73
+ // raw value before passing it to the parent component.
74
+ const rawValue = (customEvent.target as HTMLModusWcCheckboxElement).value;
75
+ const actualValue = !rawValue; // ✅ CORRECT: Invert the value
76
+
77
+ // Create a new event with the corrected value
78
+ const correctedEvent = new CustomEvent("valueChange", {
79
+ detail: actualValue,
80
+ bubbles: true,
81
+ cancelable: true,
82
+ });
83
+
84
+ onValueChange?.(correctedEvent);
85
+ };
86
+
87
+ if (onValueChange) {
88
+ checkbox.addEventListener("inputChange", handleValueChange);
89
+ }
90
+
91
+ return () => {
92
+ if (onValueChange) {
93
+ checkbox.removeEventListener("inputChange", handleValueChange);
94
+ }
95
+ };
96
+ }, [onValueChange]);
97
+
98
+ return (
99
+ <ModusWcCheckbox
100
+ ref={checkboxRef}
101
+ value={value}
102
+ />
103
+ );
104
+ }
105
+ ```
106
+
107
+ ## Usage in Forms
108
+
109
+ When using checkboxes in forms:
110
+
111
+ ```tsx
112
+ function MyForm() {
113
+ const [agreeToTerms, setAgreeToTerms] = useState(false);
114
+
115
+ return (
116
+ <ModusCheckbox
117
+ value={agreeToTerms}
118
+ onValueChange={(event) => {
119
+ // event.detail is already corrected (inverted)
120
+ setAgreeToTerms(event.detail);
121
+ }}
122
+ label="I agree to the terms and conditions"
123
+ />
124
+ );
125
+ }
126
+ ```
127
+
128
+ ## Multiple Checkboxes
129
+
130
+ When handling multiple checkboxes:
131
+
132
+ ```tsx
133
+ function CheckboxGroup() {
134
+ const [checkboxes, setCheckboxes] = useState({
135
+ option1: false,
136
+ option2: true,
137
+ option3: false,
138
+ });
139
+
140
+ const handleCheckboxChange = (key: string, event: CustomEvent<boolean>) => {
141
+ // event.detail is already corrected
142
+ setCheckboxes(prev => ({
143
+ ...prev,
144
+ [key]: event.detail,
145
+ }));
146
+ };
147
+
148
+ return (
149
+ <>
150
+ <ModusCheckbox
151
+ value={checkboxes.option1}
152
+ onValueChange={(e) => handleCheckboxChange('option1', e)}
153
+ label="Option 1"
154
+ />
155
+ <ModusCheckbox
156
+ value={checkboxes.option2}
157
+ onValueChange={(e) => handleCheckboxChange('option2', e)}
158
+ label="Option 2"
159
+ />
160
+ <ModusCheckbox
161
+ value={checkboxes.option3}
162
+ onValueChange={(e) => handleCheckboxChange('option3', e)}
163
+ label="Option 3"
164
+ />
165
+ </>
166
+ );
167
+ }
168
+ ```
169
+
170
+ ## Important Notes
171
+
172
+ 1. **The bug is in `target.value`**: The inversion happens when reading `event.target.value`, not in `event.detail`
173
+ 2. **Always invert**: Never trust the raw value - always invert it
174
+ 3. **Wrapper handles it**: The `ModusCheckbox` wrapper component already handles this, so if you're using the wrapper, you don't need to invert again
175
+ 4. **Document the bug**: Add comments explaining the workaround
176
+
177
+ ## Testing
178
+
179
+ To verify the fix works:
180
+
181
+ ```tsx
182
+ // Test that checked state matches expected value
183
+ <ModusCheckbox
184
+ value={isChecked}
185
+ onValueChange={(event) => {
186
+ console.log('Raw value (inverted):', event.detail);
187
+ console.log('Expected checked:', isChecked);
188
+ // These should match after inversion
189
+ }}
190
+ />
191
+ ```
192
+
193
+ ## Common Mistakes
194
+
195
+ 1. **Forgetting to invert**: Using raw value directly
196
+ 2. **Double inversion**: Inverting when using the wrapper component (it already handles it)
197
+ 3. **Wrong event**: Using `inputChange` instead of reading `target.value`
198
+
199
+ ## Related Files
200
+
201
+ - `src/components/ModusCheckbox.tsx` - Complete wrapper implementation
202
+ - `.cursor/rules/modus-checkbox-value-inversion-react.mdc` - Detailed documentation
@@ -0,0 +1,386 @@
1
+ ---
2
+ name: implement-modus-modal-with-refs
3
+ description: Create Modus modals using the forwardRef + useImperativeHandle pattern for programmatic control
4
+ ---
5
+
6
+ # Implement Modus Modal with Refs
7
+
8
+ Create Modus modal components using the `forwardRef` + `useImperativeHandle` pattern for programmatic control.
9
+
10
+ ## When to Use
11
+
12
+ Use this skill when:
13
+ - Creating modal dialogs that need to be opened/closed programmatically
14
+ - You need to control modal state from parent components
15
+ - Building modals with custom triggers (not just button clicks)
16
+
17
+ ## Pattern Overview
18
+
19
+ Modus modals require:
20
+ 1. **`forwardRef`** to expose methods to parent components
21
+ 2. **`useImperativeHandle`** to define the API (`openModal`, `closeModal`)
22
+ 3. **`querySelector("dialog")`** to access the native dialog element
23
+ 4. **Event listeners** for dialog close events
24
+
25
+ ## Reference Implementation
26
+
27
+ See `src/components/ModusModal.tsx` for the complete implementation.
28
+
29
+ ## Complete Template
30
+
31
+ ```tsx
32
+ import { ModusWcModal } from "@trimble-oss/moduswebcomponents-react";
33
+ import type { ReactNode } from "react";
34
+ import { useRef, useEffect, forwardRef, useImperativeHandle } from "react";
35
+
36
+ /**
37
+ * Props for the ModusModal component.
38
+ */
39
+ interface ModusModalProps {
40
+ /** A unique identifier for the modal. */
41
+ modalId: string;
42
+ /** The ARIA label for the modal. */
43
+ ariaLabel?: string;
44
+
45
+ /** The type of backdrop for the modal. */
46
+ backdrop?: 'default' | 'static';
47
+ /** The position of the modal. */
48
+ position?: 'top' | 'center' | 'bottom';
49
+ /** Whether the modal should be fullscreen. */
50
+ fullscreen?: boolean;
51
+ /** Whether to show the fullscreen toggle button. */
52
+ showFullscreenToggle?: boolean;
53
+ /** Whether to show the close button. */
54
+ showClose?: boolean;
55
+ /** A custom CSS class to apply to the modal. */
56
+ customClass?: string;
57
+
58
+ /** The header content of the modal. */
59
+ header?: ReactNode;
60
+ /** The main content of the modal. */
61
+ children: ReactNode;
62
+ /** The footer content of the modal. */
63
+ footer?: ReactNode;
64
+
65
+ /** A callback function to handle the close event. */
66
+ onClose?: () => void;
67
+ }
68
+
69
+ /**
70
+ * A ref object for the ModusModal component.
71
+ */
72
+ export interface ModusModalRef {
73
+ /** Opens the modal. */
74
+ openModal: () => void;
75
+ /** Closes the modal. */
76
+ closeModal: () => void;
77
+ }
78
+
79
+ /**
80
+ * Renders a Modus modal component.
81
+ * @param {ModusModalProps} props - The component props.
82
+ * @param {React.Ref<ModusModalRef>} ref - The ref object for the modal.
83
+ * @returns {JSX.Element} The rendered modal component.
84
+ */
85
+ const ModusModal = forwardRef<ModusModalRef, ModusModalProps>(
86
+ (
87
+ {
88
+ modalId,
89
+ ariaLabel,
90
+ backdrop = 'default',
91
+ position = 'center',
92
+ fullscreen = false,
93
+ showFullscreenToggle = false,
94
+ showClose = true,
95
+ customClass,
96
+ header,
97
+ children,
98
+ footer,
99
+ onClose,
100
+ },
101
+ ref
102
+ ) => {
103
+ const modalRef = useRef<HTMLModusWcModalElement>(null);
104
+
105
+ const openModal = () => {
106
+ if (modalRef.current) {
107
+ const dialog = modalRef.current.querySelector(
108
+ "dialog"
109
+ ) as HTMLDialogElement;
110
+ if (dialog) {
111
+ dialog.showModal();
112
+ }
113
+ }
114
+ };
115
+
116
+ const closeModal = () => {
117
+ if (modalRef.current) {
118
+ const dialog = modalRef.current.querySelector(
119
+ "dialog"
120
+ ) as HTMLDialogElement;
121
+ if (dialog) {
122
+ dialog.close();
123
+ }
124
+ }
125
+ };
126
+
127
+ useImperativeHandle(ref, () => ({
128
+ openModal,
129
+ closeModal,
130
+ }));
131
+
132
+ // Handle modal events
133
+ useEffect(() => {
134
+ const modal = modalRef.current;
135
+ if (modal) {
136
+ const handleClose = () => {
137
+ onClose?.();
138
+ };
139
+
140
+ const dialogElement = modal.querySelector("dialog");
141
+ if (dialogElement) {
142
+ dialogElement.addEventListener("close", handleClose);
143
+ return () => {
144
+ dialogElement.removeEventListener("close", handleClose);
145
+ };
146
+ }
147
+ }
148
+ }, [onClose]);
149
+
150
+ return (
151
+ <ModusWcModal
152
+ ref={modalRef}
153
+ modal-id={modalId}
154
+ aria-label={ariaLabel}
155
+ backdrop={backdrop}
156
+ position={position}
157
+ fullscreen={fullscreen}
158
+ show-fullscreen-toggle={showFullscreenToggle}
159
+ show-close={showClose}
160
+ custom-class={customClass}
161
+ >
162
+ {header && <div slot="header">{header}</div>}
163
+ <div slot="content">{children}</div>
164
+ {footer && <div slot="footer">{footer}</div>}
165
+ </ModusWcModal>
166
+ );
167
+ }
168
+ );
169
+
170
+ ModusModal.displayName = "ModusModal";
171
+
172
+ export default ModusModal;
173
+ ```
174
+
175
+ ## Usage Pattern
176
+
177
+ ```tsx
178
+ import { useRef } from "react";
179
+ import ModusButton from "./components/ModusButton";
180
+ import ModusModal, { type ModusModalRef } from "./components/ModusModal";
181
+
182
+ function MyComponent() {
183
+ const modalRef = useRef<ModusModalRef>(null);
184
+
185
+ return (
186
+ <>
187
+ <ModusButton
188
+ onButtonClick={() => {
189
+ modalRef.current?.openModal();
190
+ }}
191
+ >
192
+ Open Modal
193
+ </ModusButton>
194
+
195
+ <ModusModal
196
+ ref={modalRef}
197
+ modalId="my-modal"
198
+ ariaLabel="Example modal"
199
+ onClose={() => {
200
+ console.log("Modal closed");
201
+ }}
202
+ header={
203
+ <div className="text-xl font-semibold text-foreground">
204
+ Modal Title
205
+ </div>
206
+ }
207
+ footer={
208
+ <div className="flex gap-2">
209
+ <ModusButton
210
+ variant="borderless"
211
+ onButtonClick={() => {
212
+ modalRef.current?.closeModal();
213
+ }}
214
+ >
215
+ Cancel
216
+ </ModusButton>
217
+ <ModusButton
218
+ onButtonClick={() => {
219
+ modalRef.current?.closeModal();
220
+ }}
221
+ >
222
+ Confirm
223
+ </ModusButton>
224
+ </div>
225
+ }
226
+ >
227
+ <div className="text-sm text-foreground opacity-80">
228
+ Modal content goes here.
229
+ </div>
230
+ </ModusModal>
231
+ </>
232
+ );
233
+ }
234
+ ```
235
+
236
+ ## Key Patterns
237
+
238
+ ### 1. forwardRef Pattern
239
+
240
+ ```tsx
241
+ const ModusModal = forwardRef<ModusModalRef, ModusModalProps>(
242
+ (props, ref) => {
243
+ // Component implementation
244
+ }
245
+ );
246
+ ```
247
+
248
+ ### 2. useImperativeHandle
249
+
250
+ ```tsx
251
+ useImperativeHandle(ref, () => ({
252
+ openModal,
253
+ closeModal,
254
+ }));
255
+ ```
256
+
257
+ ### 3. Dialog Access
258
+
259
+ ```tsx
260
+ const openModal = () => {
261
+ if (modalRef.current) {
262
+ const dialog = modalRef.current.querySelector(
263
+ "dialog"
264
+ ) as HTMLDialogElement;
265
+ if (dialog) {
266
+ dialog.showModal();
267
+ }
268
+ }
269
+ };
270
+ ```
271
+
272
+ **Critical**: Always use `querySelector("dialog")` - don't try to access dialog methods directly on the web component.
273
+
274
+ ### 4. Slot Structure
275
+
276
+ Modus modals use slots for content:
277
+
278
+ ```tsx
279
+ <ModusWcModal>
280
+ {header && <div slot="header">{header}</div>}
281
+ <div slot="content">{children}</div>
282
+ {footer && <div slot="footer">{footer}</div>}
283
+ </ModusWcModal>
284
+ ```
285
+
286
+ ### 5. Event Handling
287
+
288
+ Listen to the native dialog `close` event:
289
+
290
+ ```tsx
291
+ useEffect(() => {
292
+ const modal = modalRef.current;
293
+ if (modal) {
294
+ const dialogElement = modal.querySelector("dialog");
295
+ if (dialogElement) {
296
+ dialogElement.addEventListener("close", handleClose);
297
+ return () => {
298
+ dialogElement.removeEventListener("close", handleClose);
299
+ };
300
+ }
301
+ }
302
+ }, [onClose]);
303
+ ```
304
+
305
+ ## Modal Variants
306
+
307
+ ### Centered Modal (Default)
308
+
309
+ ```tsx
310
+ <ModusModal
311
+ ref={modalRef}
312
+ modalId="centered-modal"
313
+ position="center"
314
+ // ... other props
315
+ />
316
+ ```
317
+
318
+ ### Top Positioned Modal
319
+
320
+ ```tsx
321
+ <ModusModal
322
+ ref={modalRef}
323
+ modalId="top-modal"
324
+ position="top"
325
+ // ... other props
326
+ />
327
+ ```
328
+
329
+ ### Bottom Positioned Modal
330
+
331
+ ```tsx
332
+ <ModusModal
333
+ ref={modalRef}
334
+ modalId="bottom-modal"
335
+ position="bottom"
336
+ // ... other props
337
+ />
338
+ ```
339
+
340
+ ### Fullscreen Modal
341
+
342
+ ```tsx
343
+ <ModusModal
344
+ ref={modalRef}
345
+ modalId="fullscreen-modal"
346
+ fullscreen={true}
347
+ showFullscreenToggle={true}
348
+ // ... other props
349
+ />
350
+ ```
351
+
352
+ ### Static Backdrop Modal
353
+
354
+ ```tsx
355
+ <ModusModal
356
+ ref={modalRef}
357
+ modalId="static-modal"
358
+ backdrop="static"
359
+ // ... other props
360
+ />
361
+ ```
362
+
363
+ ## Common Mistakes
364
+
365
+ 1. **Missing displayName**: Always set `displayName` for forwardRef components
366
+ 2. **Wrong dialog access**: Use `querySelector("dialog")`, not direct property access
367
+ 3. **Missing null checks**: Always check `modalRef.current` before use
368
+ 4. **Wrong event**: Listen to `close` event on dialog element, not web component
369
+ 5. **Forgetting cleanup**: Always remove event listeners in cleanup function
370
+
371
+ ## Testing Checklist
372
+
373
+ - [ ] Modal opens when `openModal()` is called
374
+ - [ ] Modal closes when `closeModal()` is called
375
+ - [ ] `onClose` callback fires when modal closes
376
+ - [ ] ESC key closes modal (if backdrop is default)
377
+ - [ ] Clicking outside closes modal (if backdrop is default)
378
+ - [ ] Static backdrop prevents outside clicks from closing
379
+ - [ ] Slots render correctly (header, content, footer)
380
+ - [ ] ARIA label is set for accessibility
381
+
382
+ ## Related Files
383
+
384
+ - `src/components/ModusModal.tsx` - Complete implementation
385
+ - `src/demos/modal-demo/page.tsx` - Usage examples
386
+ - `.cursor/rules/modus-modal-implementation-react.mdc` - Detailed documentation