@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,1096 @@
1
+ ---
2
+ description: Integration patterns for Modus Web Components with Angular standalone wrapper components
3
+ globs: ["**/*.ts", "**/*.html", "**/*.scss", "**/*.css"]
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Modus Web Components Angular Wrappers
8
+
9
+ Comprehensive guide for Angular standalone wrapper components that wrap Modus Web Components, focusing on signal-based APIs, TypeScript interfaces, and Tailwind CSS integration.
10
+
11
+ ## Table of Contents
12
+
13
+ 1. [Overview](#overview)
14
+ 2. [Wrapper Component Pattern](#wrapper-component-pattern)
15
+ 3. [Signal-Based API](#signal-based-api)
16
+ 4. [Component Structure](#component-structure)
17
+ 5. [Icon Integration](#icon-integration)
18
+ 6. [Styling Guidelines](#styling-guidelines)
19
+ 7. [Best Practices](#best-practices)
20
+ - [Type Verification - Critical Rules](#6-type-verification---critical-rules)
21
+
22
+ ---
23
+
24
+ ## Overview
25
+
26
+ ### What Are These Components?
27
+
28
+ This application uses **Angular standalone wrapper components** that wrap Modus Web Components (`modus-wc-*`). These wrappers:
29
+
30
+ - Provide **Angular-native APIs** using signals (`input()`, `output()`)
31
+ - Offer **TypeScript type safety** with exported interfaces
32
+ - Maintain **consistency** across the application
33
+ - Enable **future flexibility** to swap implementations
34
+ - Follow **Angular 20+** best practices with modern control flow
35
+
36
+ ### Available Wrapper Components
37
+
38
+ All wrapper components are located in `src/app/components/` and exported from `src/app/components/index.ts`:
39
+
40
+ ```typescript
41
+ import {
42
+ ModusButtonComponent,
43
+ ModusAlertComponent,
44
+ ModusIconComponent,
45
+ ModusTextInputComponent,
46
+ ModusSelectComponent,
47
+ // ... and many more
48
+ } from '@/app/components';
49
+ ```
50
+
51
+ **Reference**: See `src/app/components/index.ts` for the complete list of available components.
52
+
53
+ ---
54
+
55
+ ## Wrapper Component Pattern
56
+
57
+ ### Standard Component Structure
58
+
59
+ All wrapper components follow this consistent pattern:
60
+
61
+ ```typescript
62
+ import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';
63
+ import { CommonModule } from '@angular/common';
64
+ import { ModusWcButton } from '@trimble-oss/moduswebcomponents-angular';
65
+
66
+ /**
67
+ * Type definitions for component props
68
+ */
69
+ export type ButtonColor = 'primary' | 'secondary' | 'tertiary' | 'warning' | 'danger';
70
+ export type ButtonVariant = 'filled' | 'outlined' | 'borderless';
71
+ export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';
72
+
73
+ /**
74
+ * Props interface (optional but recommended for documentation)
75
+ */
76
+ export interface ModusButtonProps {
77
+ color?: ButtonColor;
78
+ variant?: ButtonVariant;
79
+ size?: ButtonSize;
80
+ disabled?: boolean;
81
+ // ... other props
82
+ }
83
+
84
+ @Component({
85
+ selector: 'modus-button', // ← Users invoke with <modus-button>, NOT <modus-wc-button>
86
+ standalone: true,
87
+ imports: [CommonModule, ModusWcButton],
88
+ changeDetection: ChangeDetectionStrategy.OnPush,
89
+ template: `
90
+ <!-- Inside the wrapper, we use modus-wc-button -->
91
+ <modus-wc-button
92
+ [color]="color()"
93
+ [variant]="variant()"
94
+ [size]="size()"
95
+ [disabled]="disabled()"
96
+ (buttonClick)="handleButtonClick($event)"
97
+ >
98
+ <ng-content></ng-content>
99
+ </modus-wc-button>
100
+ `,
101
+ })
102
+ export class ModusButtonComponent {
103
+ // Signal-based inputs
104
+ readonly color = input<ButtonColor>('primary');
105
+ readonly variant = input<ButtonVariant>('filled');
106
+ readonly size = input<ButtonSize>('md');
107
+ readonly disabled = input<boolean>(false);
108
+
109
+ // Signal-based output
110
+ readonly buttonClick = output<MouseEvent | KeyboardEvent>();
111
+
112
+ // Event handler
113
+ handleButtonClick(event: CustomEvent<MouseEvent | KeyboardEvent>): void {
114
+ if (!this.disabled()) {
115
+ this.buttonClick.emit(event.detail);
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ **Important**:
122
+
123
+ - **Users invoke wrapper components** with the wrapper selector: `<modus-button>`, `<modus-alert>`, `<modus-icon>`, etc.
124
+ - **Inside wrapper templates**, the underlying web component is used: `<modus-wc-button>`, `<modus-wc-alert>`, `<modus-wc-icon>`, etc.
125
+ - **Never use `<modus-wc-*>` directly** in application templates - always use the wrapper components.
126
+
127
+ ### Key Characteristics
128
+
129
+ 1. **Standalone Components**: All wrappers use `standalone: true`
130
+ 2. **Signal-Based API**: Use `input()` and `output()` instead of `@Input()` and `@Output()`
131
+ 3. **OnPush Change Detection**: Use `ChangeDetectionStrategy.OnPush` for performance
132
+ 4. **Type Exports**: Export types and interfaces for reuse
133
+ 5. **Direct Import**: Import Modus Web Components from `@trimble-oss/moduswebcomponents-angular`
134
+
135
+ ---
136
+
137
+ ## Signal-Based API
138
+
139
+ ### Input Signals
140
+
141
+ Use `input()` for component properties:
142
+
143
+ ```typescript
144
+ // Required input
145
+ readonly alertTitle = input.required<string>();
146
+
147
+ // Optional input with default
148
+ readonly color = input<ButtonColor>('primary');
149
+
150
+ // Optional input without default
151
+ readonly icon = input<string | undefined>();
152
+
153
+ // Optional callback input
154
+ readonly onButtonClick = input<(() => void) | undefined>();
155
+ ```
156
+
157
+ ### Output Signals
158
+
159
+ Use `output()` for component events:
160
+
161
+ ```typescript
162
+ // Event output
163
+ readonly buttonClick = output<MouseEvent | KeyboardEvent>();
164
+
165
+ // Void event output
166
+ readonly dismiss = output<void>();
167
+ ```
168
+
169
+ ### Template Usage
170
+
171
+ ```html
172
+ <!-- ✅ CORRECT: Use wrapper component selectors -->
173
+ <modus-button [color]="color()" [disabled]="disabled()" (buttonClick)="handleClick($event)">
174
+ Click Me
175
+ </modus-button>
176
+
177
+ <modus-alert alertTitle="Success" variant="success" [dismissible]="true" />
178
+
179
+ <modus-icon name="add" size="md" [decorative]="false" ariaLabel="Add item" />
180
+ ```
181
+
182
+ **Important**:
183
+
184
+ - Always use **wrapper component selectors** (`<modus-button>`, `<modus-alert>`, etc.) in your templates
185
+ - Never use the underlying web component selectors (`<modus-wc-button>`, `<modus-wc-alert>`, etc.) directly
186
+ - Always call signal functions with `()` in templates: `color()`, `disabled()`, etc.
187
+
188
+ **Reference**: See `src/app/components/theme-demo.component.ts` for complete usage examples.
189
+
190
+ ---
191
+
192
+ ## Component Structure
193
+
194
+ ### File Organization
195
+
196
+ Each wrapper component follows this structure:
197
+
198
+ ```
199
+ src/app/components/
200
+ ├── modus-button.component.ts # Component implementation
201
+ ├── modus-alert.component.ts # Another component
202
+ └── index.ts # Exports all components
203
+ ```
204
+
205
+ ### Component Template Pattern
206
+
207
+ All wrapper templates follow this pattern (inside the wrapper component):
208
+
209
+ 1. **Wrap the Modus Web Component**: Use `<modus-wc-*>` internally
210
+ 2. **Bind Signal Inputs**: Use `[prop]="signal()"` syntax
211
+ 3. **Handle Events**: Use `(event)="handler($event)"`
212
+ 4. **Project Content**: Use `<ng-content>` for slots
213
+ 5. **Use Modern Control Flow**: Use `@if`, `@for`, `@switch` (Angular 17+)
214
+
215
+ ### Usage Pattern: Application Templates vs. Wrapper Templates
216
+
217
+ **In Application Templates** (what you write in your components):
218
+
219
+ ```html
220
+ <!-- ✅ CORRECT: Use wrapper component selectors -->
221
+ <modus-button
222
+ [color]="color()"
223
+ [size]="size()"
224
+ icon="add"
225
+ iconPosition="left"
226
+ (buttonClick)="handleClick($event)"
227
+ >
228
+ Click Me
229
+ </modus-button>
230
+ ```
231
+
232
+ **Inside Wrapper Component Templates** (internal implementation):
233
+
234
+ ```typescript
235
+ template: `
236
+ <!-- Inside wrapper: use modus-wc-button -->
237
+ <modus-wc-button
238
+ [color]="color()"
239
+ [size]="size()"
240
+ (buttonClick)="handleButtonClick($event)"
241
+ >
242
+ @if (icon() && iconPosition() === 'left') {
243
+ <i class="modus-icons mr-2">{{ icon() }}</i>
244
+ }
245
+ <ng-content></ng-content>
246
+ @if (icon() && iconPosition() === 'right') {
247
+ <i class="modus-icons ml-2">{{ icon() }}</i>
248
+ }
249
+ @if (icon() && iconPosition() === 'only') {
250
+ <i class="modus-icons">{{ icon() }}</i>
251
+ }
252
+ </modus-wc-button>
253
+ `,
254
+ ```
255
+
256
+ **Key Distinction:**
257
+
258
+ - **Application code**: Always use `<modus-button>`, `<modus-alert>`, `<modus-icon>`, etc.
259
+ - **Wrapper implementation**: Uses `<modus-wc-button>`, `<modus-wc-alert>`, `<modus-wc-icon>`, etc.
260
+
261
+ **Reference**:
262
+
263
+ - See `src/app/components/modus-button.component.ts` for wrapper implementation
264
+ - See `src/app/components/theme-demo.component.ts` for application usage examples
265
+
266
+ ---
267
+
268
+ ## Icon Integration
269
+
270
+ ### Using Modus Icons in Templates
271
+
272
+ Use the `<modus-icon>` wrapper component or direct `<i>` tags:
273
+
274
+ ```html
275
+ <!-- Using modus-icon wrapper component -->
276
+ <modus-icon name="add" size="md" variant="outlined" [decorative]="false" ariaLabel="Add item" />
277
+
278
+ <!-- Using direct icon tag (for simple cases) -->
279
+ <i class="modus-icons mr-2">add</i>
280
+ ```
281
+
282
+ ### Icon Spacing with Tailwind
283
+
284
+ Always use Tailwind classes for icon spacing, never inline styles:
285
+
286
+ ```html
287
+ <!-- ✅ CORRECT: Use Tailwind classes -->
288
+ <i class="modus-icons mr-2">add</i>
289
+ <i class="modus-icons ml-2">chevron-right</i>
290
+
291
+ <!-- ❌ WRONG: Inline styles -->
292
+ <i class="modus-icons" [style.margin-right.px]="8">add</i>
293
+ ```
294
+
295
+ ### Icon Names
296
+
297
+ - Use **kebab-case** for icon names (e.g., `check_circle`, `user_add`)
298
+ - Refer to `data/modusIcons.ts` for all valid icon names
299
+ - Never use other icon libraries (Font Awesome, Material Icons, etc.)
300
+
301
+ **Reference**: See `src/app/components/modus-icon.component.ts` for the icon wrapper implementation.
302
+
303
+ ---
304
+
305
+ ## Styling Guidelines
306
+
307
+ ### Design System Colors
308
+
309
+ Always use design system Tailwind classes from `src/styles.css`:
310
+
311
+ ```html
312
+ <!-- ✅ CORRECT: Design system colors -->
313
+ <div class="bg-background text-foreground">
314
+ <div class="bg-card text-card-foreground border-default">Content</div>
315
+ </div>
316
+
317
+ <!-- ❌ WRONG: Generic Tailwind colors -->
318
+ <div class="bg-blue-500 text-white">Content</div>
319
+ ```
320
+
321
+ ### Border Utilities
322
+
323
+ Use custom border utilities for Tailwind v4 compatibility:
324
+
325
+ ```html
326
+ <!-- ✅ CORRECT: Custom border utilities -->
327
+ <div class="border-default border-primary">
328
+ <div class="border-thick-success">
329
+ <div class="border-bottom-default">
330
+ <!-- ❌ WRONG: Tailwind border colors -->
331
+ <div class="border border-blue-500"></div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+ ```
336
+
337
+ ### Opacity Utilities
338
+
339
+ Use custom opacity utilities instead of Tailwind's `/80` syntax:
340
+
341
+ ```html
342
+ <!-- ✅ CORRECT: Custom opacity utilities -->
343
+ <div class="text-foreground-80 bg-primary-20">
344
+ <!-- ❌ WRONG: Tailwind opacity syntax -->
345
+ <div class="text-foreground/80 bg-primary/20"></div>
346
+ </div>
347
+ ```
348
+
349
+ ### Inline Styles
350
+
351
+ **Never use inline styles** except for truly dynamic values:
352
+
353
+ ```html
354
+ <!-- ❌ WRONG: Static inline styles -->
355
+ <div style="padding: 1rem; margin: 0.5rem;">
356
+ <!-- ✅ CORRECT: Tailwind classes -->
357
+ <div class="p-4 m-2">
358
+ <!-- ✅ CORRECT: Dynamic values only -->
359
+ <div [style.width.px]="dynamicWidth"></div>
360
+ </div>
361
+ </div>
362
+ ```
363
+
364
+ **Reference**: See `src/styles.css` for all available design system utilities.
365
+
366
+ ---
367
+
368
+ ## Best Practices
369
+
370
+ ### 1. Component Patterns
371
+
372
+ - ✅ **Use signals** (`input()`, `output()`) for all component APIs
373
+ - ✅ **Export types and interfaces** for reuse across components
374
+ - ✅ **Use OnPush change detection** for performance
375
+ - ✅ **Keep components focused** - one responsibility per component
376
+ - ✅ **Document with JSDoc** - provide examples in component doc comments
377
+
378
+ ### 2. Template Patterns
379
+
380
+ - ✅ **Use modern control flow** (`@if`, `@for`, `@switch`)
381
+ - ✅ **Bind to signals** with `()` syntax: `[prop]="signal()"`
382
+ - ✅ **Use Tailwind classes** for all styling
383
+ - ✅ **Project content** with `<ng-content>` for flexibility
384
+ - ❌ **Never use inline styles** (except dynamic values)
385
+ - ❌ **Never use old control flow** (`*ngIf`, `*ngFor`, etc.)
386
+
387
+ ### 3. Event Handling
388
+
389
+ ```typescript
390
+ // ✅ CORRECT: Handle events properly
391
+ handleButtonClick(event: CustomEvent<MouseEvent | KeyboardEvent>): void {
392
+ if (!this.disabled()) {
393
+ // Extract detail from CustomEvent
394
+ const actualEvent = event.detail;
395
+ this.buttonClick.emit(actualEvent);
396
+
397
+ // Call optional callback
398
+ const callback = this.onButtonClick();
399
+ if (callback) {
400
+ callback();
401
+ }
402
+ }
403
+ }
404
+ ```
405
+
406
+ ### 4. Accessibility
407
+
408
+ - ✅ **Always provide `ariaLabel`** for icon-only buttons or interactive elements without visible text
409
+ - ✅ **Use semantic HTML** where possible
410
+ - ✅ **Support keyboard navigation** - Modus components handle this, but verify in wrappers
411
+ - ✅ **Test with screen readers** for critical components
412
+
413
+ ### 5. Type Safety
414
+
415
+ - ✅ **Export type definitions** for component props
416
+ - ✅ **Use TypeScript interfaces** for complex props
417
+ - ✅ **Type event outputs** correctly: `output<MouseEvent>()`
418
+ - ✅ **Use strict null checks** for optional props: `input<string | undefined>()`
419
+
420
+ ### 6. Type Verification - Critical Rules
421
+
422
+ ⚠️ **ALWAYS verify TypeScript types from `@trimble-oss/moduswebcomponents` package before using properties.**
423
+
424
+ **Common Pitfalls to Avoid**:
425
+
426
+ #### ❌ Don't Assume React Examples Match Angular Types
427
+
428
+ React examples may show properties that don't exist in TypeScript interfaces:
429
+
430
+ ```typescript
431
+ // ❌ WRONG: Assumed IBreadcrumb has 'current' property
432
+ { label: 'Home', url: '/', current: true } // ❌ Type error!
433
+
434
+ // ✅ CORRECT: IBreadcrumb only has 'label' and optional 'url'
435
+ { label: 'Home', url: '/' } // ✅ Valid
436
+ ```
437
+
438
+ **Always verify the actual type**:
439
+
440
+ ```typescript
441
+ import type { IBreadcrumb } from '@trimble-oss/moduswebcomponents';
442
+
443
+ // IBreadcrumb interface:
444
+ interface IBreadcrumb {
445
+ label: string; // Required
446
+ url?: string; // Optional
447
+ // No 'current' property exists!
448
+ }
449
+ ```
450
+
451
+ #### ❌ Don't Assume Multi-Select Changes Value Type
452
+
453
+ Even in multi-select mode, the `value` property remains a `string`, not `string[]`:
454
+
455
+ ```typescript
456
+ // ❌ WRONG: Assumed multi-select means value is string[]
457
+ <modus-autocomplete
458
+ [multiSelect]="true"
459
+ [value]="selectedItems()" // ❌ Type error! value expects string
460
+ />
461
+
462
+ // ✅ CORRECT: Don't bind value for multi-select, let component manage state
463
+ <modus-autocomplete
464
+ [multiSelect]="true"
465
+ [items]="items()" // items with selected: true handle multi-select
466
+ (itemSelect)="handleSelection($event)"
467
+ />
468
+ ```
469
+
470
+ #### ❌ Don't Add Properties Not in Type Definitions
471
+
472
+ Check the actual interface before using properties:
473
+
474
+ ```typescript
475
+ // ❌ WRONG: Assumed IAutocompleteNoResults has 'severity'
476
+ const noResults = {
477
+ label: 'No results',
478
+ subLabel: 'Try again',
479
+ severity: 'info', // ❌ Property doesn't exist!
480
+ };
481
+
482
+ // ✅ CORRECT: Check actual interface
483
+ interface IAutocompleteNoResults {
484
+ label: string;
485
+ subLabel: string;
486
+ // No 'severity' property!
487
+ }
488
+ ```
489
+
490
+ #### ✅ Verification Checklist
491
+
492
+ Before using any property or interface from Modus components:
493
+
494
+ 1. **Check the actual TypeScript type**:
495
+
496
+ ```typescript
497
+ import type {
498
+ IBreadcrumb,
499
+ IAutocompleteItem,
500
+ IAutocompleteNoResults,
501
+ } from '@trimble-oss/moduswebcomponents';
502
+ ```
503
+
504
+ 2. **Inspect existing implementations** in the codebase:
505
+
506
+ ```typescript
507
+ // Look at src/app/components/theme-demo.component.ts for examples
508
+ breadcrumbItems: IBreadcrumb[] = [
509
+ { label: 'Home', url: '/home' },
510
+ { label: 'Components' }, // No 'current' property
511
+ ];
512
+ ```
513
+
514
+ 3. **Read the wrapper component's interface** in `src/app/components/`:
515
+
516
+ ```typescript
517
+ // Check src/app/components/modus-breadcrumbs.component.ts
518
+ // to see the actual props interface
519
+ ```
520
+
521
+ 4. **Verify component documentation** - don't rely solely on React examples
522
+
523
+ **Key Principle**: The TypeScript compiler will catch these errors, but always verify types from the source package (`@trimble-oss/moduswebcomponents`) rather than assuming React examples match Angular types exactly.
524
+
525
+ ### 7. Angular Signals - Common Pitfalls
526
+
527
+ ⚠️ **Always pass values directly to `signal()`, not functions.**
528
+
529
+ #### ❌ Don't Use IIFE Pattern with `signal()`
530
+
531
+ The `signal()` function expects a value, not a function. Using an IIFE (Immediately Invoked Function Expression) pattern inside `signal()` will cause TypeScript parsing errors:
532
+
533
+ ```typescript
534
+ // ❌ WRONG: Passing a function to signal()
535
+ readonly minDate = signal<string>(() => {
536
+ const today = new Date();
537
+ return today.toISOString().split('T')[0];
538
+ });
539
+ // Error: Argument of type '() => string' is not assignable to parameter of type 'string'
540
+
541
+ // ❌ ALSO WRONG: IIFE syntax confuses the parser
542
+ readonly minDate = signal<string>(() => {
543
+ const today = new Date();
544
+ return today.toISOString().split('T')[0];
545
+ }()); // ← Still causes parsing errors!
546
+ // Error: Expected "=>" but found ")"
547
+ // Error: TS2345: Argument of type '() => string' is not assignable to parameter of type 'string'
548
+
549
+ // ✅ CORRECT: Use helper methods to compute values
550
+ private getTodayDate(): string {
551
+ const today = new Date();
552
+ return today.toISOString().split('T')[0];
553
+ }
554
+ readonly minDate = signal<string>(this.getTodayDate()); // ✅ Clean and readable
555
+
556
+ // ✅ ALSO CORRECT: Compute inline if simple
557
+ readonly today = signal<string>(new Date().toISOString().split('T')[0]);
558
+ ```
559
+
560
+ #### ❌ Don't Omit Event Parameters
561
+
562
+ Event handlers must accept the event parameter even if you don't use it:
563
+
564
+ ```typescript
565
+ // ❌ WRONG: Missing event parameter
566
+ handleCheckboxChange(): void {
567
+ this.featureEnabled.update((current) => !current);
568
+ }
569
+ // Error: Expected 1 arguments, but got 0
570
+
571
+ // ✅ CORRECT: Accept the event parameter
572
+ handleCheckboxChange(event: InputEvent): void {
573
+ this.featureEnabled.update((current) => !current);
574
+ // You can use the event if needed, or ignore it
575
+ }
576
+ ```
577
+
578
+ #### ✅ Signal Initialization Patterns
579
+
580
+ **Pattern 1: Direct Value**
581
+
582
+ ```typescript
583
+ readonly count = signal<number>(0);
584
+ readonly name = signal<string>('John');
585
+ readonly isActive = signal<boolean>(false);
586
+ ```
587
+
588
+ **Pattern 2: Computed Initial Value (Helper Method)**
589
+
590
+ ```typescript
591
+ private getTodayDate(): string {
592
+ const date = new Date();
593
+ return date.toISOString().split('T')[0];
594
+ }
595
+ readonly today = signal<string>(this.getTodayDate()); // ✅ Use helper method
596
+ ```
597
+
598
+ **Pattern 3: Helper Function**
599
+
600
+ ```typescript
601
+ private initializeDate(): string {
602
+ const today = new Date();
603
+ return today.toISOString().split('T')[0];
604
+ }
605
+ readonly minDate = signal<string>(this.initializeDate());
606
+ ```
607
+
608
+ **Pattern 4: Computed Signal (for derived values)**
609
+
610
+ ```typescript
611
+ readonly firstName = signal<string>('John');
612
+ readonly lastName = signal<string>('Doe');
613
+ readonly fullName = computed(() => `${this.firstName()} ${this.lastName()}`);
614
+ ```
615
+
616
+ ### 8. Modus Divider Component - Critical Usage Rules
617
+
618
+ ⚠️ **The divider component requires both property AND attribute bindings in the wrapper to work correctly.**
619
+
620
+ #### ✅ CORRECT: How to Use Divider Component
621
+
622
+ **Always use the Angular wrapper component (`modus-divider`), not the web component directly:**
623
+
624
+ ```html
625
+ <!-- ✅ CORRECT: Use Angular wrapper with property bindings -->
626
+ <modus-divider [orientation]="'horizontal'" />
627
+
628
+ <!-- ✅ CORRECT: With color -->
629
+ <modus-divider [orientation]="'horizontal'" color="primary" />
630
+
631
+ <!-- ✅ CORRECT: With content -->
632
+ <modus-divider [orientation]="'horizontal'" content="OR" />
633
+
634
+ <!-- ✅ CORRECT: Vertical divider in flex container -->
635
+ <div class="flex items-stretch gap-4 min-h-[60px]">
636
+ <div>Left Content</div>
637
+ <modus-divider [orientation]="'vertical'" />
638
+ <div>Right Content</div>
639
+ </div>
640
+ ```
641
+
642
+ #### ❌ INCORRECT: Don't Use Web Component Directly
643
+
644
+ **Never use `modus-wc-divider` directly in application code:**
645
+
646
+ ```html
647
+ <!-- ❌ WRONG: Don't use web component directly -->
648
+ <modus-wc-divider orientation="horizontal"></modus-wc-divider>
649
+ ```
650
+
651
+ **Why?**: The Angular wrapper (`modus-divider`) includes critical fixes for attribute binding that ensure the web component receives the correct attributes. Using the web component directly bypasses these fixes.
652
+
653
+ #### ✅ Horizontal Divider Requirements
654
+
655
+ Horizontal dividers work in any vertical layout:
656
+
657
+ ```html
658
+ <!-- ✅ CORRECT: Horizontal divider in vertical flex container -->
659
+ <div class="flex flex-col gap-2">
660
+ <p>Content above</p>
661
+ <modus-divider [orientation]="'horizontal'" />
662
+ <p>Content below</p>
663
+ </div>
664
+
665
+ <!-- ✅ CORRECT: Horizontal divider with color -->
666
+ <modus-divider [orientation]="'horizontal'" color="primary" />
667
+
668
+ <!-- ✅ CORRECT: Horizontal divider with content -->
669
+ <modus-divider [orientation]="'horizontal'" content="OR" />
670
+ ```
671
+
672
+ #### ✅ Vertical Divider Requirements
673
+
674
+ **Critical**: Vertical dividers need a flex container with `items-stretch`:
675
+
676
+ ```html
677
+ <!-- ✅ CORRECT: Vertical divider with items-stretch -->
678
+ <div class="flex items-stretch gap-4 min-h-[60px]">
679
+ <div class="flex items-center">Left</div>
680
+ <modus-divider [orientation]="'vertical'" />
681
+ <div class="flex items-center">Right</div>
682
+ </div>
683
+
684
+ <!-- ✅ CORRECT: Vertical divider with explicit height -->
685
+ <div class="flex items-stretch gap-4 min-h-[120px]">
686
+ <div class="flex-1">Left Section</div>
687
+ <modus-divider [orientation]="'vertical'" />
688
+ <div class="flex-1">Right Section</div>
689
+ </div>
690
+ ```
691
+
692
+ #### ❌ Vertical Divider Mistakes
693
+
694
+ ```html
695
+ <!-- ❌ WRONG: Missing items-stretch -->
696
+ <div class="flex items-center gap-4">
697
+ <div>Left</div>
698
+ <modus-divider [orientation]="'vertical'" />
699
+ <div>Right</div>
700
+ </div>
701
+ <!-- Vertical divider won't be visible - needs items-stretch -->
702
+
703
+ <!-- ❌ WRONG: No explicit height -->
704
+ <div class="flex gap-4">
705
+ <div>Left</div>
706
+ <modus-divider [orientation]="'vertical'" />
707
+ <div>Right</div>
708
+ </div>
709
+ <!-- Vertical divider might not have height to render -->
710
+
711
+ <!-- ❌ WRONG: items-center prevents stretching -->
712
+ <div class="flex items-center gap-4 min-h-[60px]">
713
+ <div>Left</div>
714
+ <modus-divider [orientation]="'vertical'" />
715
+ <div>Right</div>
716
+ </div>
717
+ <!-- items-center doesn't allow divider to stretch -->
718
+ ```
719
+
720
+ #### ✅ Key Rules for Divider Visibility
721
+
722
+ 1. **Always use `modus-divider` (Angular wrapper), not `modus-wc-divider`**
723
+ 2. **Horizontal dividers**: Work in any vertical layout - no special requirements
724
+ 3. **Vertical dividers**: **MUST** use `items-stretch` in flex container:
725
+ - ✅ `class="flex items-stretch gap-4 min-h-[60px]"`
726
+ - ❌ `class="flex items-center gap-4"` (won't work)
727
+ 4. **Vertical dividers**: **MUST** have explicit height on parent:
728
+ - ✅ `min-h-[60px]` or `min-h-[120px]`
729
+ - ❌ No height specified (divider might not render)
730
+ 5. **Use property bindings**: `[orientation]="'horizontal'"` (not string attributes)
731
+
732
+ #### Component Properties
733
+
734
+ ```typescript
735
+ // All properties use signal-based API
736
+ <modus-divider
737
+ [orientation]="'horizontal' | 'vertical'" // Required: specifies divider direction
738
+ [color]="'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'high-contrast'" // Optional
739
+ [content]="string" // Optional: text to display on divider
740
+ [position]="'start' | 'center' | 'end'" // Optional: where content appears (default: 'center')
741
+ [responsive]="boolean" // Optional: responsive behavior (default: true)
742
+ />
743
+ ```
744
+
745
+ #### Wrapper Component Implementation Details
746
+
747
+ **Why the wrapper needs both property and attribute bindings:**
748
+
749
+ The divider web component reads values from HTML attributes, not just properties. The wrapper component (`modus-divider`) includes both bindings to ensure attributes are set:
750
+
751
+ ```typescript
752
+ // In modus-divider.component.ts template:
753
+ <modus-wc-divider
754
+ [color]="color()" // Property binding
755
+ [orientation]="orientation()" // Property binding
756
+ [attr.color]="color()" // Attribute binding (critical!)
757
+ [attr.orientation]="orientation()" // Attribute binding (critical!)
758
+ />
759
+ ```
760
+
761
+ **This dual binding is essential** - without attribute bindings, the web component won't receive the values and dividers won't be visible.
762
+
763
+ #### Troubleshooting
764
+
765
+ **Problem**: Dividers not visible
766
+
767
+ - ✅ Check you're using `modus-divider` (wrapper), not `modus-wc-divider`
768
+ - ✅ For vertical: Ensure parent has `items-stretch` and explicit height (`min-h-[...]`)
769
+ - ✅ For horizontal: Works in any vertical layout
770
+
771
+ **Problem**: Vertical divider not stretching
772
+
773
+ - ✅ Use `items-stretch` (not `items-center`)
774
+ - ✅ Add `min-h-[60px]` or similar to parent container
775
+ - ✅ Ensure parent is a flex container (`flex`)
776
+
777
+ **Problem**: Divider with content not showing text
778
+
779
+ - ✅ Check `content` property is set: `[content]="'OR'"`
780
+ - ✅ Check `position` is set if needed: `[position]="'center'"`
781
+
782
+ ### 9. Component Documentation
783
+
784
+ All wrapper components should include:
785
+
786
+ ````typescript
787
+ /**
788
+ * Angular wrapper for the Modus Web Component [component name].
789
+ *
790
+ * Provides a typed, signal-driven API that wraps the underlying
791
+ * Modus Web Component while maintaining full compatibility.
792
+ *
793
+ * @example
794
+ * ```html
795
+ * <modus-button color="primary" size="md">
796
+ * Click Me
797
+ * </modus-button>
798
+ * ```
799
+ */
800
+ @Component({ ... })
801
+ export class ModusButtonComponent { ... }
802
+ ````
803
+
804
+ ---
805
+
806
+ ## Real-World Examples
807
+
808
+ ### Example 1: Simple Button Wrapper
809
+
810
+ **Wrapper Implementation**: `src/app/components/modus-button.component.ts`
811
+
812
+ ```typescript
813
+ @Component({
814
+ selector: 'modus-button', // ← Application uses <modus-button>
815
+ standalone: true,
816
+ imports: [CommonModule, ModusWcButton],
817
+ changeDetection: ChangeDetectionStrategy.OnPush,
818
+ template: `
819
+ <modus-wc-button <!-- ← Wrapper uses <modus-wc-button>
820
+ internally --> [color]="color()" [variant]="variant()" [size]="size()" [disabled]="disabled()"
821
+ (buttonClick)="handleButtonClick($event)" >
822
+ <ng-content></ng-content>
823
+ </modus-wc-button>
824
+ `,
825
+ })
826
+ export class ModusButtonComponent {
827
+ readonly color = input<ButtonColor>('primary');
828
+ readonly variant = input<ButtonVariant>('filled');
829
+ readonly size = input<ButtonSize>('md');
830
+ readonly disabled = input<boolean>(false);
831
+ readonly buttonClick = output<MouseEvent | KeyboardEvent>();
832
+
833
+ handleButtonClick(event: CustomEvent<MouseEvent | KeyboardEvent>): void {
834
+ if (!this.disabled()) {
835
+ this.buttonClick.emit(event.detail);
836
+ }
837
+ }
838
+ }
839
+ ```
840
+
841
+ **Application Usage** (in your component templates):
842
+
843
+ ```html
844
+ <!-- ✅ CORRECT: Use the wrapper selector -->
845
+ <modus-button [color]="'primary'" [size]="'md'" (buttonClick)="handleClick($event)">
846
+ Click Me
847
+ </modus-button>
848
+
849
+ <!-- ❌ WRONG: Never use modus-wc-button directly -->
850
+ <modus-wc-button [color]="'primary'">Click Me</modus-wc-button>
851
+ ```
852
+
853
+ **Reference**: See `src/app/components/theme-demo.component.ts` for real-world usage examples.
854
+
855
+ ### Example 2: Alert with Content Projection
856
+
857
+ **Wrapper Implementation**: `src/app/components/modus-alert.component.ts`
858
+
859
+ **Application Usage**:
860
+
861
+ ```html
862
+ <!-- ✅ CORRECT: Use <modus-alert> in your templates -->
863
+ <modus-alert
864
+ alertTitle="Success"
865
+ alertDescription="Changes saved successfully."
866
+ variant="success"
867
+ [dismissible]="true"
868
+ (dismiss)="handleDismiss()"
869
+ />
870
+ ```
871
+
872
+ ```typescript
873
+ @Component({
874
+ selector: 'modus-alert',
875
+ standalone: true,
876
+ imports: [CommonModule, ModusWcAlert],
877
+ changeDetection: ChangeDetectionStrategy.OnPush,
878
+ template: `
879
+ <modus-wc-alert
880
+ [alertTitle]="alertTitle()"
881
+ [variant]="variant()"
882
+ [dismissible]="dismissible()"
883
+ (dismissClick)="handleDismissClick()"
884
+ >
885
+ <ng-content select="[slot='content']" slot="content" />
886
+ <ng-content select="[slot='button']" slot="button" />
887
+ </modus-wc-alert>
888
+ `,
889
+ })
890
+ export class ModusAlertComponent {
891
+ readonly alertTitle = input.required<string>();
892
+ readonly variant = input<'error' | 'info' | 'success' | 'warning'>('info');
893
+ readonly dismissible = input<boolean>(false);
894
+ readonly dismiss = output<void>();
895
+
896
+ handleDismissClick(): void {
897
+ this.dismiss.emit();
898
+ }
899
+ }
900
+ ```
901
+
902
+ ### Example 3: Icon Component with Computed Properties
903
+
904
+ **Wrapper Implementation**: `src/app/components/modus-icon.component.ts`
905
+
906
+ **Application Usage**:
907
+
908
+ ```html
909
+ <!-- ✅ CORRECT: Use <modus-icon> in your templates -->
910
+ <modus-icon name="add" size="md" variant="outlined" [decorative]="false" ariaLabel="Add item" />
911
+ ```
912
+
913
+ ```typescript
914
+ @Component({
915
+ selector: 'modus-icon',
916
+ standalone: true,
917
+ imports: [CommonModule, ModusWcIcon],
918
+ changeDetection: ChangeDetectionStrategy.OnPush,
919
+ template: `
920
+ <modus-wc-icon
921
+ [name]="name()"
922
+ [size]="size()"
923
+ [decorative]="decorative()"
924
+ [attr.aria-label]="computedAriaLabel()"
925
+ />
926
+ `,
927
+ })
928
+ export class ModusIconComponent {
929
+ readonly name = input.required<string>();
930
+ readonly size = input<ModusIconSize>('md');
931
+ readonly decorative = input<boolean>(true);
932
+ readonly ariaLabel = input<string | undefined>();
933
+
934
+ // Computed property for conditional aria-label
935
+ readonly computedAriaLabel = computed(() =>
936
+ this.decorative() ? undefined : this.ariaLabel() ?? `${this.name()} icon`
937
+ );
938
+ }
939
+ ```
940
+
941
+ ---
942
+
943
+ ### Example 4: Navbar with Search Input Expansion
944
+
945
+ **Wrapper Implementation**: `src/app/components/modus-navbar.component.ts`
946
+
947
+ **Application Usage**: Managing navbar search input expansion requires proper state management.
948
+
949
+ **⚠️ Important: Navbar Placement**
950
+ The navbar **MUST** be placed in `app.html` (Angular component template), **NOT** in `index.html` (static HTML file). This is because:
951
+
952
+ - `index.html` is static HTML that only loads the Angular app via `<app-root></app-root>`
953
+ - Angular bindings (`[property]`, `(event)`), signals, and component state only work in component templates
954
+ - The navbar needs access to component properties, methods, and reactive state
955
+ - Placing it in `index.html` would break all Angular functionality (bindings, events, state management)
956
+
957
+ ```html
958
+ <modus-navbar
959
+ [userCard]="userCard"
960
+ [searchInputOpen]="searchInputOpen()"
961
+ [visibility]="{
962
+ user: true,
963
+ search: true,
964
+ searchInput: true,
965
+ help: false,
966
+ apps: false,
967
+ notifications: false,
968
+ mainMenu: false
969
+ }"
970
+ (searchClick)="onSearchClick($event)"
971
+ (searchInputOpenChange)="onSearchInputOpenChange($event)"
972
+ (searchChange)="onSearchChange($event)"
973
+ >
974
+ </modus-navbar>
975
+ ```
976
+
977
+ ```typescript
978
+ export class App implements OnInit {
979
+ // User card data for navbar (required)
980
+ readonly userCard: INavbarUserCard = {
981
+ name: 'John Doe',
982
+ email: 'john.doe@example.com',
983
+ avatarSrc: 'https://via.placeholder.com/64',
984
+ avatarAlt: 'User avatar',
985
+ };
986
+
987
+ // Search input state management
988
+ readonly searchInputOpen = signal(false);
989
+
990
+ /**
991
+ * Handle search button click - toggle search input manually
992
+ */
993
+ onSearchClick(event: MouseEvent | KeyboardEvent): void {
994
+ // Toggle the search input state
995
+ this.searchInputOpen.set(!this.searchInputOpen());
996
+ }
997
+
998
+ /**
999
+ * Handle search input open state change - sync our state with navbar
1000
+ */
1001
+ onSearchInputOpenChange(isOpen: boolean): void {
1002
+ // Keep state in sync (prevents conflicts if navbar manages state internally)
1003
+ if (this.searchInputOpen() !== isOpen) {
1004
+ this.searchInputOpen.set(isOpen);
1005
+ }
1006
+ }
1007
+
1008
+ /**
1009
+ * Handle search input value change
1010
+ */
1011
+ onSearchChange(event: { value: string }): void {
1012
+ console.log('Search value:', event.value);
1013
+ // Implement search logic here
1014
+ }
1015
+ }
1016
+ ```
1017
+
1018
+ **Key Points for Navbar Search**:
1019
+
1020
+ 1. **State Management**: Use a `signal` to track `searchInputOpen` state
1021
+ 2. **Visibility Settings**: Set both `search: true` (search button) and `searchInput: true` (search input field) in visibility
1022
+ 3. **Two-Way Binding**: Bind `[searchInputOpen]` to control state, and listen to `(searchInputOpenChange)` to sync
1023
+ 4. **Toggle on Click**: Handle `(searchClick)` to toggle the state when search button is clicked
1024
+ 5. **Sync Handler**: Handle `(searchInputOpenChange)` to keep state synchronized if the navbar manages state internally
1025
+
1026
+ **Why This Pattern**:
1027
+
1028
+ - The navbar requires explicit state management for the search input expansion
1029
+ - Binding `[searchInputOpen]` gives you control over the expansion state
1030
+ - Handling `(searchInputOpenChange)` ensures state stays synchronized
1031
+ - Setting `searchInput: true` in visibility makes the search input field visible when expanded
1032
+
1033
+ ---
1034
+
1035
+ ## Component List
1036
+
1037
+ All available wrapper components:
1038
+
1039
+ - `modus-accordion` - Accordion/collapsible sections
1040
+ - `modus-alert` - Alert/notification messages
1041
+ - `modus-autocomplete` - Autocomplete input
1042
+ - `modus-avatar` - User avatar display
1043
+ - `modus-badge` - Badge/counter component
1044
+ - `modus-breadcrumbs` - Navigation breadcrumbs
1045
+ - `modus-button` - Button with icon support
1046
+ - `modus-card` - Card container
1047
+ - `modus-checkbox` - Checkbox input
1048
+ - `modus-chip` - Chip/tag component
1049
+ - `modus-collapse` - Collapsible content
1050
+ - `modus-date` - Date picker input
1051
+ - `modus-divider` - Horizontal/vertical divider
1052
+ - `modus-dropdown-menu` - Dropdown menu
1053
+ - `modus-file-dropzone` - File upload dropzone
1054
+ - `modus-icon` - Icon wrapper component
1055
+ - `modus-loader` - Loading spinner
1056
+ - `modus-menu` / `modus-menu-item` - Menu components
1057
+ - `modus-modal` - Modal dialog
1058
+ - `modus-navbar` - Navigation bar
1059
+ - `modus-number-input` - Number input field
1060
+ - `modus-pagination` - Pagination controls
1061
+ - `modus-progress` - Progress bar
1062
+ - `modus-radio` - Radio button input
1063
+ - `modus-rating` - Star rating component
1064
+ - `modus-select` - Select/dropdown input
1065
+ - `modus-side-navigation` - Side navigation menu
1066
+ - `modus-skeleton` - Loading skeleton
1067
+ - `modus-slider` - Range slider
1068
+ - `modus-stepper` - Step indicator
1069
+ - `modus-switch` - Toggle switch
1070
+ - `modus-table` - Data table
1071
+ - `modus-tabs` - Tab navigation
1072
+ - `modus-text-input` - Text input field
1073
+ - `modus-textarea` - Textarea input
1074
+ - `modus-theme-switcher` - Theme switcher
1075
+ - `modus-time-input` - Time picker input
1076
+ - `modus-toast` - Toast notification
1077
+ - `modus-toolbar` - Toolbar component
1078
+ - `modus-tooltip` - Tooltip component
1079
+ - `modus-typography` - Typography component
1080
+ - `modus-utility-panel` - Utility panel
1081
+
1082
+ **Reference**: See `src/app/components/index.ts` for complete exports and `src/app/components/README.md` for detailed documentation.
1083
+
1084
+ ---
1085
+
1086
+ ## Reference Links
1087
+
1088
+ - **Modus Web Components**: [Documentation](https://trimble-oss.github.io/modus-wc-2.0/main/)
1089
+ - **Angular Signals**: [Angular Signals Guide](https://angular.io/guide/signals)
1090
+ - **Angular Standalone Components**: [Standalone Components Guide](https://angular.io/guide/standalone-components)
1091
+ - **Design System**: See `src/styles.css` and `.cursor/rules/angular-design-system.mdc`
1092
+ - **Component Source**: `src/app/components/`
1093
+
1094
+ ---
1095
+
1096
+ **All wrapper components follow these patterns. When creating new wrappers or modifying existing ones, refer to this guide and existing component implementations.**