@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,775 @@
1
+ "use client";
2
+
3
+ import { useState, useRef, useEffect, useCallback } from "react";
4
+ import DemoExample from "../../components/DemoExample";
5
+ import DemoPage from "../../components/DemoPage";
6
+ import ModusNavbar from "../../components/ModusNavbar";
7
+ import {
8
+ ModusWcSideNavigation,
9
+ ModusWcMenu,
10
+ ModusWcMenuItem,
11
+ ModusWcIcon,
12
+ } from "@trimble-oss/moduswebcomponents-react";
13
+
14
+ /**
15
+ * Demo page showcasing the Modus Side Navigation component.
16
+ *
17
+ * Demonstrates side navigation features including:
18
+ * - Navbar integration (recommended pattern)
19
+ * - Icons that remain visible when collapsed
20
+ * - Push mode layout
21
+ * - State management with React hooks
22
+ * - Interactive examples with state management
23
+ */
24
+ export default function SideNavigationDemoPage() {
25
+ // ============================================
26
+ // First example state (Navbar Integration)
27
+ // ============================================
28
+ const [navbarMenuExpanded, setNavbarMenuExpanded] = useState(false);
29
+ const [selectedItem1, setSelectedItem1] = useState<string | null>("home");
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ const sideNavRef1 = useRef<any>(null);
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ const menuRef1 = useRef<any>(null);
34
+
35
+ // User card configuration for first example
36
+ const userCard1 = {
37
+ name: "John Doe",
38
+ email: "john.doe@example.com",
39
+ avatarSrc: "",
40
+ avatarAlt: "User Avatar",
41
+ };
42
+
43
+ // ============================================
44
+ // Second example state (Sub-Menu)
45
+ // ============================================
46
+ const [subMenuNavbarExpanded, setSubMenuNavbarExpanded] = useState(false);
47
+ const [subMenuStates, setSubMenuStates] = useState<Record<string, boolean>>({
48
+ charts: false,
49
+ maps: false,
50
+ "map-2": false,
51
+ });
52
+ const [selectedSubMenuItem, setSelectedSubMenuItem] = useState<string | null>(
53
+ null,
54
+ );
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ const sideNavRef2 = useRef<any>(null);
57
+
58
+ // User card configuration for second example
59
+ const userCard2 = {
60
+ name: "Jane Smith",
61
+ email: "jane.smith@example.com",
62
+ avatarSrc: "",
63
+ avatarAlt: "User Avatar",
64
+ };
65
+
66
+ // ============================================
67
+ // Helper functions (must be defined before useEffect)
68
+ // ============================================
69
+
70
+ /**
71
+ * Handles expand change events (Storybook pattern).
72
+ * Collapses all child containers and resets icons when side navigation collapses.
73
+ */
74
+ const handleExpandChange = useCallback((event: CustomEvent<boolean>) => {
75
+ if (!event.detail) {
76
+ const sideNav = sideNavRef2.current;
77
+ if (!sideNav) return;
78
+
79
+ // Find the parent container of the side navigation
80
+ const container = sideNav.closest(
81
+ ".layout-with-navbar",
82
+ ) as HTMLElement;
83
+
84
+ if (container) {
85
+ // Collapse all child containers if the side navigation is collapsed
86
+ const childrenContainers = container.querySelectorAll(
87
+ ".side-nav-children-container",
88
+ );
89
+ childrenContainers.forEach((containerEl: Element) => {
90
+ containerEl.classList.add("side-nav-hidden");
91
+ containerEl.setAttribute("aria-hidden", "true");
92
+ });
93
+
94
+ // Reset all collapse icons to expand_more
95
+ const collapseIcons = container.querySelectorAll(
96
+ ".side-nav-dropdown-toggle",
97
+ );
98
+ collapseIcons.forEach((icon: Element) => {
99
+ if (icon.getAttribute("name") === "expand_less") {
100
+ icon.setAttribute("name", "expand_more");
101
+ }
102
+ });
103
+ }
104
+ }
105
+ }, []);
106
+
107
+ /**
108
+ * Collapses all sub-menus (called when side navigation collapses).
109
+ */
110
+ const collapseAllSubMenus = useCallback(() => {
111
+ console.log("Collapsing all sub-menus");
112
+ setSubMenuStates({
113
+ charts: false,
114
+ maps: false,
115
+ "map-2": false,
116
+ });
117
+ }, []);
118
+
119
+ // ============================================
120
+ // Navbar menu change handlers
121
+ // ============================================
122
+
123
+ /**
124
+ * Handles navbar main menu open state changes for first example.
125
+ * This is triggered when the hamburger menu button is clicked.
126
+ */
127
+ const handleNavbarMenuOpenChange1 = useCallback((isOpen: boolean) => {
128
+ console.log("Navbar main menu open change 1 - received:", isOpen);
129
+ // Just update React state - useEffect will sync to web component
130
+ setNavbarMenuExpanded(isOpen);
131
+ }, []);
132
+
133
+ /**
134
+ * Handles navbar main menu open state changes for second example.
135
+ */
136
+ const handleNavbarMenuOpenChange2 = useCallback(
137
+ (isOpen: boolean) => {
138
+ console.log("Navbar main menu open change 2 - received:", isOpen);
139
+ // Just update React state - useEffect will sync to web component
140
+ setSubMenuNavbarExpanded(isOpen);
141
+
142
+ // Collapse all sub-menus when side navigation collapses
143
+ if (!isOpen) {
144
+ collapseAllSubMenus();
145
+ }
146
+ },
147
+ [collapseAllSubMenus],
148
+ );
149
+
150
+ // ============================================
151
+ // Sync expanded prop to web component
152
+ // ============================================
153
+
154
+ /**
155
+ * Syncs React state to side navigation web component for first example.
156
+ */
157
+ useEffect(() => {
158
+ const sideNav = sideNavRef1.current;
159
+ if (sideNav && sideNav.expanded !== navbarMenuExpanded) {
160
+ sideNav.expanded = navbarMenuExpanded;
161
+ }
162
+ }, [navbarMenuExpanded]);
163
+
164
+ /**
165
+ * Syncs React state to side navigation web component for second example.
166
+ */
167
+ useEffect(() => {
168
+ const sideNav = sideNavRef2.current;
169
+ if (sideNav && sideNav.expanded !== subMenuNavbarExpanded) {
170
+ sideNav.expanded = subMenuNavbarExpanded;
171
+ }
172
+ }, [subMenuNavbarExpanded]);
173
+
174
+ // ============================================
175
+ // Side navigation expanded change handlers
176
+ // ============================================
177
+
178
+ /**
179
+ * Handles side navigation expanded state changes for first example.
180
+ * This syncs React state when side nav changes independently (e.g., click outside).
181
+ */
182
+ useEffect(() => {
183
+ const sideNav = sideNavRef1.current;
184
+ if (!sideNav) return;
185
+
186
+ const handleExpandedChange = (event: Event) => {
187
+ const customEvent = event as CustomEvent<boolean>;
188
+ const isExpanded = customEvent.detail;
189
+ console.log("Side navigation 1 expanded change:", isExpanded);
190
+
191
+ // Only update state if it's different to avoid circular updates
192
+ setNavbarMenuExpanded((prev) => {
193
+ if (prev !== isExpanded) {
194
+ return isExpanded;
195
+ }
196
+ return prev;
197
+ });
198
+ };
199
+
200
+ sideNav.addEventListener("expandedChange", handleExpandedChange);
201
+
202
+ return () => {
203
+ sideNav.removeEventListener("expandedChange", handleExpandedChange);
204
+ };
205
+ }, []);
206
+
207
+ /**
208
+ * Handles side navigation expanded state changes for second example.
209
+ */
210
+ useEffect(() => {
211
+ const sideNav = sideNavRef2.current;
212
+ if (!sideNav) return;
213
+
214
+ const handleExpandedChange = (event: Event) => {
215
+ const customEvent = event as CustomEvent<boolean>;
216
+ const isExpanded = customEvent.detail;
217
+ console.log("Side navigation 2 expanded change:", isExpanded);
218
+
219
+ // Only update state if it's different to avoid circular updates
220
+ setSubMenuNavbarExpanded((prev) => {
221
+ if (prev !== isExpanded) {
222
+ // Collapse all sub-menus when side navigation collapses
223
+ if (!isExpanded) {
224
+ collapseAllSubMenus();
225
+ handleExpandChange(customEvent);
226
+ }
227
+ return isExpanded;
228
+ }
229
+ return prev;
230
+ });
231
+ };
232
+
233
+ sideNav.addEventListener("expandedChange", handleExpandedChange);
234
+
235
+ return () => {
236
+ sideNav.removeEventListener("expandedChange", handleExpandedChange);
237
+ };
238
+ }, [collapseAllSubMenus, handleExpandChange]);
239
+
240
+ // Handle menu item selection for first example
241
+ useEffect(() => {
242
+ const menu = menuRef1.current;
243
+ if (!menu) return;
244
+
245
+ const handleItemSelect = (e: Event) => {
246
+ const customEvent = e as CustomEvent<{ value: string }>;
247
+ const value = customEvent.detail?.value;
248
+ if (value) {
249
+ setSelectedItem1(value);
250
+ }
251
+ };
252
+
253
+ menu.addEventListener("itemSelect", handleItemSelect);
254
+
255
+ return () => {
256
+ menu.removeEventListener("itemSelect", handleItemSelect);
257
+ };
258
+ }, []);
259
+
260
+ // Update selected state for menu items in first example
261
+ useEffect(() => {
262
+ const menu = menuRef1.current;
263
+ if (!menu) return;
264
+
265
+ const menuItems = menu.querySelectorAll("modus-wc-menu-item");
266
+ menuItems.forEach((item: Element) => {
267
+ const value = item.getAttribute("value");
268
+ if (value === selectedItem1) {
269
+ item.setAttribute("selected", "");
270
+ } else {
271
+ item.removeAttribute("selected");
272
+ }
273
+ });
274
+ }, [selectedItem1]);
275
+
276
+ // ============================================
277
+ // Event handlers
278
+ // ============================================
279
+
280
+ /**
281
+ * Toggles the expanded state of a sub-menu.
282
+ */
283
+ const toggleSubMenu = (menuKey: string, event: React.MouseEvent) => {
284
+ event.stopPropagation();
285
+ console.log("Toggling sub-menu:", menuKey);
286
+
287
+ setSubMenuStates((prev) => ({
288
+ ...prev,
289
+ [menuKey]: !prev[menuKey],
290
+ }));
291
+ };
292
+
293
+ /**
294
+ * Selects a menu item and updates the current selection.
295
+ */
296
+ const selectMenuItem = (itemKey: string) => {
297
+ console.log("Selected menu item:", itemKey);
298
+ setSelectedSubMenuItem(itemKey);
299
+ };
300
+
301
+ /**
302
+ * Handles collapse toggle for sub-menus (Storybook pattern).
303
+ */
304
+ const handleCollapseToggle = (e: React.MouseEvent) => {
305
+ const clickedEl = e.currentTarget as HTMLElement;
306
+ const parentLi = clickedEl.closest("li");
307
+ if (!parentLi) return;
308
+
309
+ // Find the icon element that needs to be toggled using the dropdown-toggle class
310
+ const iconEl = clickedEl.querySelector(
311
+ ".side-nav-dropdown-toggle",
312
+ ) as HTMLElement;
313
+ if (!iconEl) return;
314
+
315
+ // Find the parent side nav element
316
+ const sideNav = sideNavRef2.current;
317
+
318
+ // Toggle between expand_more and expand_less icons only if side nav is expanded
319
+ const isExpanded = iconEl.getAttribute("name") === "expand_more";
320
+ if (sideNav?.expanded) {
321
+ iconEl.setAttribute("name", isExpanded ? "expand_less" : "expand_more");
322
+ }
323
+
324
+ // Find and toggle children visibility
325
+ const childContainer = parentLi.nextElementSibling as HTMLElement;
326
+ if (
327
+ childContainer &&
328
+ childContainer.classList.contains("side-nav-children-container") &&
329
+ sideNav?.expanded
330
+ ) {
331
+ childContainer.classList.toggle("side-nav-hidden");
332
+ childContainer.setAttribute(
333
+ "aria-hidden",
334
+ !isExpanded ? "true" : "false",
335
+ );
336
+ }
337
+ };
338
+
339
+ return (
340
+ <>
341
+ <style>{`
342
+ .side-nav-children-container {
343
+ transition: height 0.2s ease-out;
344
+ }
345
+
346
+ .side-nav-collapse-icon {
347
+ min-width: 24px;
348
+ padding-inline-start: 0.2rem;
349
+ }
350
+
351
+ .side-nav-dropdown-menu {
352
+ overflow: hidden;
353
+ text-overflow: ellipsis;
354
+ white-space: nowrap;
355
+ }
356
+
357
+ .side-nav-flex-row {
358
+ align-items: center;
359
+ display: flex;
360
+ gap: 1.3rem;
361
+ padding: 0.8rem 0.25rem;
362
+ padding-left: 1rem;
363
+ cursor: pointer;
364
+ }
365
+
366
+ .side-nav-hidden {
367
+ display: none;
368
+ }
369
+
370
+ .side-nav-justify-end {
371
+ margin-left: auto;
372
+ }
373
+
374
+ .layout-with-navbar {
375
+ box-shadow: rgba(36, 35, 45, 0.3) 1px 0 4px;
376
+ display: flex;
377
+ flex-direction: column;
378
+ height: 100%;
379
+ }
380
+
381
+ .main-content-row {
382
+ display: flex;
383
+ flex: 1;
384
+ overflow: hidden;
385
+ position: relative;
386
+ min-height: 500px;
387
+ }
388
+
389
+ .side-nav-menu-width {
390
+ width: 100%;
391
+ }
392
+
393
+ .side-nav-nested-row {
394
+ padding-left: 4.5rem !important;
395
+ }
396
+
397
+ .side-nav-deeply-nested-row {
398
+ padding-left: 5.5rem !important;
399
+ }
400
+
401
+ .panel-content {
402
+ flex: 1;
403
+ padding: 1.5rem;
404
+ overflow: auto;
405
+ margin-left: 4rem; /* Account for collapsed side nav width */
406
+ }
407
+
408
+ .side-navigation {
409
+ position: absolute;
410
+ left: 0;
411
+ top: 0;
412
+ height: 100%;
413
+ z-index: 999;
414
+ }
415
+
416
+ .modus-wc-menu ul {
417
+ list-style: none;
418
+ margin: 0;
419
+ padding: 0;
420
+ }
421
+
422
+ .modus-wc-menu li ul {
423
+ margin-inline-start: 1.8rem;
424
+ }
425
+
426
+ .side-nav-menu-item-container {
427
+ list-style: none;
428
+ }
429
+
430
+ .side-nav-submenu-item {
431
+ padding: 0.8rem 0.25rem;
432
+ padding-left: 1rem;
433
+ cursor: pointer;
434
+ display: flex;
435
+ align-items: center;
436
+ }
437
+
438
+ .side-nav-nested-submenu {
439
+ margin-left: 1rem;
440
+ }
441
+
442
+ .side-nav-icon-left {
443
+ flex-shrink: 0;
444
+ }
445
+ `}</style>
446
+ <DemoPage
447
+ title="Modus Side Navigation"
448
+ description="A collapsible vertical navigation component that provides contextual menu options for application navigation. The component collapses to show icons only (4rem width) and expands to show full menu items with labels. Icons remain visible and properly positioned in both states."
449
+ >
450
+ {/* Navbar Integration Example */}
451
+ <DemoExample
452
+ title="Navbar Integration (Recommended Pattern)"
453
+ description="Side navigation controlled by the navbar's main menu button (hamburger menu). This is the standard Modus pattern used in applications."
454
+ >
455
+ <div
456
+ className="layout-with-navbar h-[600px] flex flex-col"
457
+ data-example="basic"
458
+ >
459
+ <ModusNavbar
460
+ userCard={userCard1}
461
+ visibility={{ mainMenu: true, user: true }}
462
+ onMainMenuOpenChange={handleNavbarMenuOpenChange1}
463
+ />
464
+
465
+ <div className="main-content-row flex flex-1 overflow-hidden">
466
+ <ModusWcSideNavigation
467
+ ref={sideNavRef1}
468
+ expanded={navbarMenuExpanded}
469
+ collapse-on-click-outside={true}
470
+ max-width="256px"
471
+ mode="push"
472
+ target-content="#basic-panel-content"
473
+ className="side-navigation h-full"
474
+ >
475
+ <ModusWcMenu ref={menuRef1} size="lg">
476
+ <ModusWcMenuItem label="Home" value="home" selected={true}>
477
+ <ModusWcIcon
478
+ slot="start-icon"
479
+ name="home"
480
+ decorative={true}
481
+ />
482
+ </ModusWcMenuItem>
483
+ <ModusWcMenuItem label="Profile" value="profile">
484
+ <ModusWcIcon
485
+ slot="start-icon"
486
+ name="person"
487
+ decorative={true}
488
+ />
489
+ </ModusWcMenuItem>
490
+ <ModusWcMenuItem label="Settings" value="settings">
491
+ <ModusWcIcon
492
+ slot="start-icon"
493
+ name="settings"
494
+ decorative={true}
495
+ />
496
+ </ModusWcMenuItem>
497
+ </ModusWcMenu>
498
+ </ModusWcSideNavigation>
499
+
500
+ <div
501
+ id="basic-panel-content"
502
+ className="panel-content flex-1 p-6"
503
+ >
504
+ <div className="text-lg font-semibold text-foreground mb-4">
505
+ Main Content Area
506
+ </div>
507
+ <div className="text-base text-foreground mb-4">
508
+ The side navigation of an application provides context through
509
+ accessible menu options and positions a consistent component
510
+ to connect to various pages in the application.
511
+ </div>
512
+ <div className="text-base text-foreground">
513
+ The side navigation is a collapsible side content of the
514
+ site's pages. It is located alongside the page's primary
515
+ content. The component is designed to add side content to a
516
+ fullscreen application. It is activated through the
517
+ "hamburger" menu in the Navbar.
518
+ </div>
519
+ <div className="mt-4 p-4 rounded-lg bg-card border border-border">
520
+ <div className="text-sm font-medium text-card-foreground mb-1">
521
+ Navigation State:
522
+ </div>
523
+ <div className="text-sm text-muted-foreground">
524
+ {navbarMenuExpanded ? "Expanded" : "Collapsed"}
525
+ </div>
526
+ {selectedItem1 && (
527
+ <div className="mt-2">
528
+ <div className="text-sm font-medium text-card-foreground mb-1">
529
+ Selected Item:
530
+ </div>
531
+ <div className="text-sm text-muted-foreground">
532
+ {selectedItem1}
533
+ </div>
534
+ </div>
535
+ )}
536
+ </div>
537
+ </div>
538
+ </div>
539
+ </div>
540
+ </DemoExample>
541
+
542
+ {/* Sub-Menu Example */}
543
+ <DemoExample
544
+ title="Side Navigation with Sub-Menus"
545
+ description="Advanced side navigation with collapsible sub-menus and nested menu items. Demonstrates hierarchical navigation with expand/collapse functionality."
546
+ >
547
+ <div
548
+ className="layout-with-navbar h-[700px] flex flex-col"
549
+ data-example="submenu"
550
+ >
551
+ <ModusNavbar
552
+ userCard={userCard2}
553
+ visibility={{ mainMenu: true, user: true }}
554
+ onMainMenuOpenChange={handleNavbarMenuOpenChange2}
555
+ />
556
+
557
+ <div className="main-content-row flex flex-1 overflow-hidden">
558
+ <ModusWcSideNavigation
559
+ ref={sideNavRef2}
560
+ expanded={subMenuNavbarExpanded}
561
+ collapse-on-click-outside={true}
562
+ max-width="256px"
563
+ mode="push"
564
+ target-content="#submenu-panel-content"
565
+ className="side-navigation h-full"
566
+ >
567
+ <ModusWcMenu
568
+ aria-label="Custom menu"
569
+ custom-class="side-nav-menu-width"
570
+ >
571
+ {/* Charts Menu with Sub-items */}
572
+ <li>
573
+ <div
574
+ className="side-nav-flex-row hover:bg-muted"
575
+ onClick={handleCollapseToggle}
576
+ >
577
+ <ModusWcIcon
578
+ name="bar_graph"
579
+ decorative={true}
580
+ className="side-nav-collapse-icon side-nav-icon-left"
581
+ />
582
+ <div className="side-nav-dropdown-menu">Charts</div>
583
+ <div className="side-nav-justify-end">
584
+ <ModusWcIcon
585
+ decorative={true}
586
+ name="expand_more"
587
+ className="side-nav-collapse-icon side-nav-dropdown-toggle"
588
+ />
589
+ </div>
590
+ </div>
591
+ </li>
592
+ <li
593
+ className="side-nav-children-container side-nav-hidden"
594
+ aria-hidden="true"
595
+ >
596
+ <ul>
597
+ <li>
598
+ <div
599
+ className="side-nav-flex-row side-nav-nested-row hover:bg-muted"
600
+ onClick={() => selectMenuItem("bar-chart")}
601
+ >
602
+ <div>Bar Chart</div>
603
+ </div>
604
+ </li>
605
+ <li>
606
+ <div
607
+ className="side-nav-flex-row side-nav-nested-row hover:bg-muted"
608
+ onClick={() => selectMenuItem("line-chart")}
609
+ >
610
+ <div>Line Chart</div>
611
+ </div>
612
+ </li>
613
+ <li>
614
+ <div
615
+ className="side-nav-flex-row side-nav-nested-row hover:bg-muted"
616
+ onClick={() => selectMenuItem("pie-chart")}
617
+ >
618
+ <div>Pie Chart</div>
619
+ </div>
620
+ </li>
621
+ </ul>
622
+ </li>
623
+
624
+ {/* Calendar Menu (no sub-items) */}
625
+ <li>
626
+ <div
627
+ className="side-nav-flex-row hover:bg-muted"
628
+ onClick={() => selectMenuItem("calendar")}
629
+ >
630
+ <ModusWcIcon
631
+ name="calendar"
632
+ decorative={true}
633
+ className="side-nav-collapse-icon side-nav-icon-left"
634
+ />
635
+ <div className="side-nav-dropdown-menu">Calendar</div>
636
+ </div>
637
+ </li>
638
+
639
+ {/* Maps Menu with Sub-items (using state-based approach) */}
640
+ <div className="side-nav-menu-item-container">
641
+ <div
642
+ className="side-nav-flex-row hover:bg-muted"
643
+ onClick={(e) => toggleSubMenu("maps", e)}
644
+ >
645
+ <ModusWcIcon
646
+ name="compass"
647
+ decorative={true}
648
+ className="side-nav-collapse-icon side-nav-icon-left"
649
+ />
650
+ <div className="side-nav-dropdown-menu">Maps</div>
651
+ <div className="side-nav-justify-end">
652
+ <ModusWcIcon
653
+ name={
654
+ subMenuStates["maps"]
655
+ ? "expand_less"
656
+ : "expand_more"
657
+ }
658
+ decorative={true}
659
+ className="side-nav-collapse-icon side-nav-dropdown-toggle"
660
+ />
661
+ </div>
662
+ </div>
663
+ <div
664
+ className={`side-nav-children-container ${
665
+ !subMenuStates["maps"] ? "side-nav-hidden" : ""
666
+ }`}
667
+ aria-hidden={!subMenuStates["maps"]}
668
+ >
669
+ <div
670
+ className="side-nav-submenu-item side-nav-nested-row hover:bg-muted"
671
+ onClick={() => selectMenuItem("map-1")}
672
+ >
673
+ <div>Map 1</div>
674
+ </div>
675
+ <div
676
+ className="side-nav-submenu-item side-nav-nested-row hover:bg-muted"
677
+ onClick={(e) => toggleSubMenu("map-2", e)}
678
+ >
679
+ <div>Map 2</div>
680
+ <div className="side-nav-justify-end">
681
+ <ModusWcIcon
682
+ name={
683
+ subMenuStates["map-2"]
684
+ ? "expand_less"
685
+ : "expand_more"
686
+ }
687
+ decorative={true}
688
+ className="side-nav-collapse-icon side-nav-dropdown-toggle"
689
+ />
690
+ </div>
691
+ </div>
692
+ <div
693
+ className={`side-nav-children-container side-nav-nested-submenu ${
694
+ !subMenuStates["map-2"] ? "side-nav-hidden" : ""
695
+ }`}
696
+ aria-hidden={!subMenuStates["map-2"]}
697
+ >
698
+ <div
699
+ className="side-nav-submenu-item side-nav-deeply-nested-row hover:bg-muted"
700
+ onClick={() => selectMenuItem("map-2-1")}
701
+ >
702
+ <div>Map 2-1</div>
703
+ </div>
704
+ <div
705
+ className="side-nav-submenu-item side-nav-deeply-nested-row hover:bg-muted"
706
+ onClick={() => selectMenuItem("map-2-2")}
707
+ >
708
+ <div>Map 2-2</div>
709
+ </div>
710
+ </div>
711
+ <div
712
+ className="side-nav-submenu-item side-nav-nested-row hover:bg-muted"
713
+ onClick={() => selectMenuItem("map-3")}
714
+ >
715
+ <div>Map 3</div>
716
+ </div>
717
+ </div>
718
+ </div>
719
+ </ModusWcMenu>
720
+ </ModusWcSideNavigation>
721
+
722
+ <div
723
+ id="submenu-panel-content"
724
+ className="panel-content flex-1 p-6"
725
+ >
726
+ <div className="text-lg font-semibold text-foreground mb-4">
727
+ Sub-Menu Navigation
728
+ </div>
729
+ <div className="text-base text-foreground mb-4">
730
+ This example demonstrates hierarchical navigation with
731
+ collapsible sub-menus. Click on menu items with arrows to
732
+ expand/collapse sub-menus. The navigation maintains state and
733
+ properly handles nested menu structures.
734
+ </div>
735
+ <div className="mt-4 p-4 rounded-lg bg-card border border-border">
736
+ <div className="text-sm font-medium text-card-foreground mb-2">
737
+ Current Selection:
738
+ </div>
739
+ <div className="text-sm text-muted-foreground">
740
+ {selectedSubMenuItem || "No item selected"}
741
+ </div>
742
+ </div>
743
+ <div className="mt-4 p-4 rounded-lg bg-muted">
744
+ <div className="text-sm font-medium text-foreground mb-2">
745
+ Sub-Menu States:
746
+ </div>
747
+ <div className="text-xs text-muted-foreground">
748
+ <div>
749
+ Charts:{" "}
750
+ {subMenuStates["charts"] ? "Expanded" : "Collapsed"}
751
+ </div>
752
+ <div>
753
+ Maps: {subMenuStates["maps"] ? "Expanded" : "Collapsed"}
754
+ </div>
755
+ <div>
756
+ Map 2: {subMenuStates["map-2"] ? "Expanded" : "Collapsed"}
757
+ </div>
758
+ </div>
759
+ </div>
760
+ <div className="mt-4 p-4 rounded-lg bg-card border border-border">
761
+ <div className="text-sm font-medium text-card-foreground mb-1">
762
+ Navigation State:
763
+ </div>
764
+ <div className="text-sm text-muted-foreground">
765
+ {subMenuNavbarExpanded ? "Expanded" : "Collapsed"}
766
+ </div>
767
+ </div>
768
+ </div>
769
+ </div>
770
+ </div>
771
+ </DemoExample>
772
+ </DemoPage>
773
+ </>
774
+ );
775
+ }