@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.
- package/README.md +191 -0
- package/bin/create-trimble-app.js +9 -0
- package/package.json +67 -0
- package/src/cli.js +134 -0
- package/src/frameworks.js +28 -0
- package/src/scaffold.js +209 -0
- package/src/utils/file.js +47 -0
- package/src/utils/git.js +140 -0
- package/src/utils/install.js +25 -0
- package/src/utils/logger.js +124 -0
- package/templates/angular/.cursor/commands/remove-dev-content.md +394 -0
- package/templates/angular/.cursor/mcp.json +13 -0
- package/templates/angular/.cursor/rules/modus-angular-20.mdc +82 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management-short.mdc +45 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management.mdc +322 -0
- package/templates/angular/.cursor/rules/modus-angular-best-practices.mdc +472 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage-short.mdc +48 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage.mdc +286 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage-short.mdc +47 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage.mdc +263 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion.mdc +92 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing-short.mdc +34 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing.mdc +185 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage.mdc +208 -0
- package/templates/angular/.cursor/rules/modus-angular-components-reference.mdc +114 -0
- package/templates/angular/.cursor/rules/modus-angular-design-system.mdc +273 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow.mdc +145 -0
- package/templates/angular/.cursor/rules/modus-angular-essentials.mdc +272 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation.mdc +124 -0
- package/templates/angular/.cursor/rules/modus-angular-icon-names.mdc +70 -0
- package/templates/angular/.cursor/rules/modus-angular-icons-short.mdc +40 -0
- package/templates/angular/.cursor/rules/modus-angular-icons.mdc +137 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides.mdc +301 -0
- package/templates/angular/.cursor/rules/modus-angular-integration-short.mdc +60 -0
- package/templates/angular/.cursor/rules/modus-angular-integration.mdc +1096 -0
- package/templates/angular/.cursor/rules/modus-angular-master.mdc +164 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage.mdc +115 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage-short.mdc +49 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage.mdc +146 -0
- package/templates/angular/.cursor/rules/modus-angular-no-emojis.mdc +66 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities.mdc +160 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu.mdc +83 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html.mdc +81 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage-short.mdc +50 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage.mdc +136 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage.mdc +151 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage-short.mdc +44 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage.mdc +242 -0
- package/templates/angular/.cursor/rules/modus-angular-themes-short.mdc +54 -0
- package/templates/angular/.cursor/rules/modus-angular-themes.mdc +222 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage.mdc +130 -0
- package/templates/angular/.cursor/rules/ux/gestalt-laws-detailed.mdc +514 -0
- package/templates/angular/.cursor/rules/ux/ux-ui-foundations.mdc +235 -0
- package/templates/angular/.cursor/skills/run-lint-checks/SKILL.md +169 -0
- package/templates/angular/.editorconfig +17 -0
- package/templates/angular/.github/dependabot.yml +19 -0
- package/templates/angular/.github/workflows/a11y-check.yml +135 -0
- package/templates/angular/.github/workflows/ci.yml +44 -0
- package/templates/angular/.husky/pre-commit +32 -0
- package/templates/angular/.postcssrc.json +5 -0
- package/templates/angular/.vscode/extensions.json +4 -0
- package/templates/angular/.vscode/launch.json +20 -0
- package/templates/angular/.vscode/tasks.json +42 -0
- package/templates/angular/CLAUDE.md +148 -0
- package/templates/angular/README.md +92 -0
- package/templates/angular/amplify.yml +25 -0
- package/templates/angular/angular.json +106 -0
- package/templates/angular/data/modusIcons.ts +861 -0
- package/templates/angular/package-lock.json +11030 -0
- package/templates/angular/package.json +66 -0
- package/templates/angular/public/angular-icon.svg +12 -0
- package/templates/angular/public/favicon.ico +0 -0
- package/templates/angular/public/modus-icons.css +49 -0
- package/templates/angular/public/vite.svg +1 -0
- package/templates/angular/scripts/README.md +410 -0
- package/templates/angular/scripts/check-border-violations.js +352 -0
- package/templates/angular/scripts/check-icon-names.js +402 -0
- package/templates/angular/scripts/check-inline-styles.js +292 -0
- package/templates/angular/scripts/check-modus-colors.js +282 -0
- package/templates/angular/scripts/check-modus-icons.js +263 -0
- package/templates/angular/scripts/check-opacity-utilities.js +426 -0
- package/templates/angular/scripts/check-semantic-html.js +452 -0
- package/templates/angular/scripts/check-typescript.js +109 -0
- package/templates/angular/src/app/app.config.ts +29 -0
- package/templates/angular/src/app/app.css +0 -0
- package/templates/angular/src/app/app.html +4 -0
- package/templates/angular/src/app/app.routes.ts +351 -0
- package/templates/angular/src/app/app.spec.ts +27 -0
- package/templates/angular/src/app/app.ts +47 -0
- package/templates/angular/src/app/components/README.md +77 -0
- package/templates/angular/src/app/components/index.ts +53 -0
- package/templates/angular/src/app/components/modus-accordion.component.ts +50 -0
- package/templates/angular/src/app/components/modus-alert.component.ts +133 -0
- package/templates/angular/src/app/components/modus-autocomplete.component.ts +262 -0
- package/templates/angular/src/app/components/modus-avatar.component.ts +75 -0
- package/templates/angular/src/app/components/modus-badge.component.ts +84 -0
- package/templates/angular/src/app/components/modus-breadcrumbs.component.ts +65 -0
- package/templates/angular/src/app/components/modus-button-group.component.ts +82 -0
- package/templates/angular/src/app/components/modus-button.component.ts +292 -0
- package/templates/angular/src/app/components/modus-card.component.ts +73 -0
- package/templates/angular/src/app/components/modus-checkbox.component.ts +117 -0
- package/templates/angular/src/app/components/modus-chip.component.ts +97 -0
- package/templates/angular/src/app/components/modus-collapse.component.ts +118 -0
- package/templates/angular/src/app/components/modus-date.component.ts +165 -0
- package/templates/angular/src/app/components/modus-dropdown-menu.component.ts +108 -0
- package/templates/angular/src/app/components/modus-file-dropzone.component.ts +121 -0
- package/templates/angular/src/app/components/modus-handle.component.ts +96 -0
- package/templates/angular/src/app/components/modus-icon.component.ts +81 -0
- package/templates/angular/src/app/components/modus-input-feedback.component.ts +54 -0
- package/templates/angular/src/app/components/modus-input-label.component.ts +62 -0
- package/templates/angular/src/app/components/modus-loader.component.ts +48 -0
- package/templates/angular/src/app/components/modus-logo.component.ts +115 -0
- package/templates/angular/src/app/components/modus-menu-item.component.ts +116 -0
- package/templates/angular/src/app/components/modus-menu.component.ts +58 -0
- package/templates/angular/src/app/components/modus-modal.component.ts +70 -0
- package/templates/angular/src/app/components/modus-navbar.component.ts +303 -0
- package/templates/angular/src/app/components/modus-number-input.component.ts +174 -0
- package/templates/angular/src/app/components/modus-pagination.component.ts +74 -0
- package/templates/angular/src/app/components/modus-panel.component.ts +61 -0
- package/templates/angular/src/app/components/modus-progress.component.ts +62 -0
- package/templates/angular/src/app/components/modus-radio.component.ts +102 -0
- package/templates/angular/src/app/components/modus-rating.component.ts +80 -0
- package/templates/angular/src/app/components/modus-select.component.ts +131 -0
- package/templates/angular/src/app/components/modus-side-navigation.component.ts +90 -0
- package/templates/angular/src/app/components/modus-skeleton.component.ts +54 -0
- package/templates/angular/src/app/components/modus-slider.component.ts +132 -0
- package/templates/angular/src/app/components/modus-stepper.component.ts +65 -0
- package/templates/angular/src/app/components/modus-switch.component.ts +118 -0
- package/templates/angular/src/app/components/modus-table.component.ts +204 -0
- package/templates/angular/src/app/components/modus-tabs.component.ts +82 -0
- package/templates/angular/src/app/components/modus-text-input.component.ts +221 -0
- package/templates/angular/src/app/components/modus-textarea.component.ts +168 -0
- package/templates/angular/src/app/components/modus-theme-switcher.component.ts +45 -0
- package/templates/angular/src/app/components/modus-time-input.component.ts +172 -0
- package/templates/angular/src/app/components/modus-toast.component.ts +63 -0
- package/templates/angular/src/app/components/modus-toolbar.component.ts +43 -0
- package/templates/angular/src/app/components/modus-tooltip.component.ts +83 -0
- package/templates/angular/src/app/components/modus-typography.component.ts +79 -0
- package/templates/angular/src/app/components/modus-utility-panel.component.ts +275 -0
- package/templates/angular/src/app/components/theme-demo.component.ts +1242 -0
- package/templates/angular/src/app/data/component-demos.ts +360 -0
- package/templates/angular/src/app/data/modus-icons.ts +806 -0
- package/templates/angular/src/app/demos/accordion/accordion-demo.component.ts +212 -0
- package/templates/angular/src/app/demos/alert/alert-demo.component.ts +108 -0
- package/templates/angular/src/app/demos/autocomplete/autocomplete-demo.component.ts +174 -0
- package/templates/angular/src/app/demos/avatar/avatar-demo.component.ts +149 -0
- package/templates/angular/src/app/demos/badge/badge-demo.component.ts +148 -0
- package/templates/angular/src/app/demos/breadcrumbs/breadcrumbs-demo.component.ts +96 -0
- package/templates/angular/src/app/demos/button/button-demo.component.ts +256 -0
- package/templates/angular/src/app/demos/button-group/button-group-demo.component.ts +215 -0
- package/templates/angular/src/app/demos/card/card-demo.component.ts +180 -0
- package/templates/angular/src/app/demos/checkbox/checkbox-demo.component.ts +71 -0
- package/templates/angular/src/app/demos/chip/chip-demo.component.ts +183 -0
- package/templates/angular/src/app/demos/date/date-demo.component.ts +193 -0
- package/templates/angular/src/app/demos/dropdown/dropdown-demo.component.ts +196 -0
- package/templates/angular/src/app/demos/file-dropzone/file-dropzone-demo.component.ts +176 -0
- package/templates/angular/src/app/demos/handle/handle-demo.component.ts +265 -0
- package/templates/angular/src/app/demos/icon/icon-demo.component.ts +65 -0
- package/templates/angular/src/app/demos/input-feedback/input-feedback-demo.component.ts +189 -0
- package/templates/angular/src/app/demos/input-label/input-label-demo.component.ts +330 -0
- package/templates/angular/src/app/demos/loader/loader-demo.component.ts +143 -0
- package/templates/angular/src/app/demos/logo/logo-demo.component.ts +191 -0
- package/templates/angular/src/app/demos/menu/menu-demo.component.ts +72 -0
- package/templates/angular/src/app/demos/modal/modal-demo.component.ts +278 -0
- package/templates/angular/src/app/demos/navbar/navbar-demo.component.ts +135 -0
- package/templates/angular/src/app/demos/number-input/number-input-demo.component.ts +175 -0
- package/templates/angular/src/app/demos/pagination/pagination-demo.component.ts +134 -0
- package/templates/angular/src/app/demos/panel/panel-demo.component.ts +235 -0
- package/templates/angular/src/app/demos/progress/progress-demo.component.ts +169 -0
- package/templates/angular/src/app/demos/radio/radio-demo.component.ts +161 -0
- package/templates/angular/src/app/demos/rating/rating-demo.component.ts +97 -0
- package/templates/angular/src/app/demos/select/select-demo.component.ts +107 -0
- package/templates/angular/src/app/demos/shared/demo-example-clean.component.ts +41 -0
- package/templates/angular/src/app/demos/shared/demo-example.component.ts +42 -0
- package/templates/angular/src/app/demos/shared/demo-page.component.ts +97 -0
- package/templates/angular/src/app/demos/shared/index.ts +3 -0
- package/templates/angular/src/app/demos/side-navigation/side-navigation-demo.component.ts +524 -0
- package/templates/angular/src/app/demos/skeleton/skeleton-demo.component.ts +112 -0
- package/templates/angular/src/app/demos/slider/slider-demo.component.ts +76 -0
- package/templates/angular/src/app/demos/stepper/stepper-demo.component.ts +79 -0
- package/templates/angular/src/app/demos/switch/switch-demo.component.ts +113 -0
- package/templates/angular/src/app/demos/table/table-demo.component.ts +405 -0
- package/templates/angular/src/app/demos/tabs/tabs-demo.component.ts +318 -0
- package/templates/angular/src/app/demos/text-input/text-input-demo.component.ts +160 -0
- package/templates/angular/src/app/demos/textarea/textarea-demo.component.ts +95 -0
- package/templates/angular/src/app/demos/theme-switcher/theme-switcher-demo.component.ts +38 -0
- package/templates/angular/src/app/demos/time-input/time-input-demo.component.ts +130 -0
- package/templates/angular/src/app/demos/toast/toast-demo.component.ts +258 -0
- package/templates/angular/src/app/demos/toolbar/toolbar-demo.component.ts +54 -0
- package/templates/angular/src/app/demos/tooltip/tooltip-demo.component.ts +163 -0
- package/templates/angular/src/app/demos/utility-panel/utility-panel-demo.component.ts +197 -0
- package/templates/angular/src/app/dev/dev-config.ts +119 -0
- package/templates/angular/src/app/dev/dev-panel/dev-panel.component.ts +215 -0
- package/templates/angular/src/app/dev/dev-panel.service.ts +63 -0
- package/templates/angular/src/app/dev/index.ts +8 -0
- package/templates/angular/src/app/dev/theme-switcher-dropdown/theme-switcher-dropdown.component.ts +134 -0
- package/templates/angular/src/app/dev-pages/color-palette/color-palette.component.ts +229 -0
- package/templates/angular/src/app/dev-pages/components-gallery/components-gallery.component.ts +486 -0
- package/templates/angular/src/app/dev-pages/icons/icons.component.ts +149 -0
- package/templates/angular/src/app/pages/home/home.component.ts +251 -0
- package/templates/angular/src/app/services/README.md +57 -0
- package/templates/angular/src/app/services/theme.service.ts +163 -0
- package/templates/angular/src/environments/environment.development.ts +8 -0
- package/templates/angular/src/environments/environment.ts +8 -0
- package/templates/angular/src/index.html +14 -0
- package/templates/angular/src/main.ts +6 -0
- package/templates/angular/src/styles.css +1328 -0
- package/templates/angular/tsconfig.app.json +15 -0
- package/templates/angular/tsconfig.json +35 -0
- package/templates/angular/tsconfig.spec.json +14 -0
- package/templates/config.json +23 -0
- package/templates/react/.cursor/commands/remove-dev-content.md +311 -0
- package/templates/react/.cursor/mcp.json +13 -0
- package/templates/react/.cursor/rules/README.md +240 -0
- package/templates/react/.cursor/rules/border-usage-guidelines-short.mdc +22 -0
- package/templates/react/.cursor/rules/border-usage-guidelines.mdc +380 -0
- package/templates/react/.cursor/rules/chrome-devtools-testing-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react.mdc +292 -0
- package/templates/react/.cursor/rules/implementation-guides-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/implementation-guides-react.mdc +446 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react.mdc +445 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react.mdc +117 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react.mdc +492 -0
- package/templates/react/.cursor/rules/modus-color-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-color-usage-react.mdc +420 -0
- package/templates/react/.cursor/rules/modus-components-reference.mdc +366 -0
- package/templates/react/.cursor/rules/modus-icon-names.mdc +63 -0
- package/templates/react/.cursor/rules/modus-icons-react-short.mdc +24 -0
- package/templates/react/.cursor/rules/modus-icons-react.mdc +402 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react.mdc +831 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react.mdc +247 -0
- package/templates/react/.cursor/rules/modus-no-emojis-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react-short.mdc +70 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react.mdc +208 -0
- package/templates/react/.cursor/rules/modus-react-best-practices-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-best-practices.mdc +508 -0
- package/templates/react/.cursor/rules/modus-react-essentials.mdc +209 -0
- package/templates/react/.cursor/rules/modus-react-integration-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-integration.mdc +509 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings.mdc +805 -0
- package/templates/react/.cursor/rules/modus-react-master.mdc +160 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react.mdc +442 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react.mdc +427 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react.mdc +642 -0
- package/templates/react/.cursor/rules/modus-themes-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-themes-react.mdc +506 -0
- package/templates/react/.cursor/rules/ux/gestalt-laws-detailed.mdc +456 -0
- package/templates/react/.cursor/rules/ux/ux-ui-foundations.mdc +211 -0
- package/templates/react/.cursor/skills/create-modus-form-component/SKILL.md +518 -0
- package/templates/react/.cursor/skills/create-modus-wrapper-component/SKILL.md +252 -0
- package/templates/react/.cursor/skills/fix-modus-component-event-issues/SKILL.md +345 -0
- package/templates/react/.cursor/skills/handle-modus-checkbox-value-bug/SKILL.md +202 -0
- package/templates/react/.cursor/skills/implement-modus-modal-with-refs/SKILL.md +386 -0
- package/templates/react/.cursor/skills/integrate-modus-icons/SKILL.md +300 -0
- package/templates/react/.cursor/skills/run-lint-checks/SKILL.md +235 -0
- package/templates/react/.cursor/skills/set-up-modus-event-listeners/SKILL.md +284 -0
- package/templates/react/.cursor/skills/style-modus-components-with-tailwind/SKILL.md +382 -0
- package/templates/react/.env.development +3 -0
- package/templates/react/.env.production +3 -0
- package/templates/react/.github/CODEOWNERS +28 -0
- package/templates/react/.github/ISSUE_TEMPLATE/bug_report.yml +176 -0
- package/templates/react/.github/ISSUE_TEMPLATE/config.yml +20 -0
- package/templates/react/.github/ISSUE_TEMPLATE/documentation.yml +115 -0
- package/templates/react/.github/ISSUE_TEMPLATE/feature_request.yml +171 -0
- package/templates/react/.github/ISSUE_TEMPLATE/question.yml +139 -0
- package/templates/react/.github/copilot-instructions.md +80 -0
- package/templates/react/.github/instructions/components.instructions.md +82 -0
- package/templates/react/.github/instructions/demos.instructions.md +82 -0
- package/templates/react/.github/instructions/pages.instructions.md +76 -0
- package/templates/react/.github/instructions/styles.instructions.md +77 -0
- package/templates/react/.github/instructions/typescript.instructions.md +101 -0
- package/templates/react/.github/pull_request_template.md +188 -0
- package/templates/react/.github/workflows/ci.yml +43 -0
- package/templates/react/.github/workflows/claude-code-review.yml +44 -0
- package/templates/react/.github/workflows/claude.yml +50 -0
- package/templates/react/.husky/pre-commit +28 -0
- package/templates/react/.vscode/extensions.json +8 -0
- package/templates/react/CLAUDE.md +119 -0
- package/templates/react/CODE_OF_CONDUCT.md +79 -0
- package/templates/react/CONTRIBUTING.md +65 -0
- package/templates/react/LICENSE +21 -0
- package/templates/react/README.md +728 -0
- package/templates/react/SECURITY.md +50 -0
- package/templates/react/eslint.config.js +23 -0
- package/templates/react/index.html +13 -0
- package/templates/react/package-lock.json +5209 -0
- package/templates/react/package.json +49 -0
- package/templates/react/postcss.config.js +6 -0
- package/templates/react/public/react.svg +1 -0
- package/templates/react/public/vite.svg +1 -0
- package/templates/react/readme_assets/getting_started_header.png +0 -0
- package/templates/react/readme_assets/hero.png +0 -0
- package/templates/react/readme_assets/modus_comp.png +0 -0
- package/templates/react/readme_assets/modus_figma_mcp.png +0 -0
- package/templates/react/readme_assets/teaser_comp.gif +0 -0
- package/templates/react/scripts/README.md +343 -0
- package/templates/react/scripts/check-border-violations.js +483 -0
- package/templates/react/scripts/check-icon-names.js +486 -0
- package/templates/react/scripts/check-inline-styles.js +364 -0
- package/templates/react/scripts/check-modus-colors.js +247 -0
- package/templates/react/scripts/check-modus-icons.js +256 -0
- package/templates/react/scripts/check-opacity-utilities.js +481 -0
- package/templates/react/scripts/check-semantic-html.js +476 -0
- package/templates/react/scripts/check-typescript.js +109 -0
- package/templates/react/src/App.css +42 -0
- package/templates/react/src/App.tsx +54 -0
- package/templates/react/src/assets/react.svg +1 -0
- package/templates/react/src/components/DemoExample.tsx +61 -0
- package/templates/react/src/components/DemoPage.tsx +81 -0
- package/templates/react/src/components/ModusAccordion.tsx +89 -0
- package/templates/react/src/components/ModusAlert.tsx +85 -0
- package/templates/react/src/components/ModusAutocomplete.tsx +207 -0
- package/templates/react/src/components/ModusAvatar.tsx +50 -0
- package/templates/react/src/components/ModusBadge.tsx +82 -0
- package/templates/react/src/components/ModusBreadcrumbs.tsx +75 -0
- package/templates/react/src/components/ModusButton.tsx +244 -0
- package/templates/react/src/components/ModusButtonGroup.tsx +91 -0
- package/templates/react/src/components/ModusCard.tsx +70 -0
- package/templates/react/src/components/ModusCheckbox.tsx +168 -0
- package/templates/react/src/components/ModusChip.tsx +93 -0
- package/templates/react/src/components/ModusDate.tsx +154 -0
- package/templates/react/src/components/ModusDropdownMenu.tsx +148 -0
- package/templates/react/src/components/ModusFileDropzone.tsx +140 -0
- package/templates/react/src/components/ModusHandle.tsx +101 -0
- package/templates/react/src/components/ModusIcon.tsx +49 -0
- package/templates/react/src/components/ModusInputFeedback.tsx +52 -0
- package/templates/react/src/components/ModusInputLabel.tsx +50 -0
- package/templates/react/src/components/ModusLoader.tsx +42 -0
- package/templates/react/src/components/ModusLogo.tsx +102 -0
- package/templates/react/src/components/ModusMenu.tsx +119 -0
- package/templates/react/src/components/ModusMenuItem.tsx +86 -0
- package/templates/react/src/components/ModusModal.tsx +145 -0
- package/templates/react/src/components/ModusNavbar.tsx +504 -0
- package/templates/react/src/components/ModusNumberInput.tsx +230 -0
- package/templates/react/src/components/ModusPagination.tsx +94 -0
- package/templates/react/src/components/ModusPanel.tsx +92 -0
- package/templates/react/src/components/ModusProgress.tsx +70 -0
- package/templates/react/src/components/ModusProvider.tsx +18 -0
- package/templates/react/src/components/ModusRadio.tsx +114 -0
- package/templates/react/src/components/ModusRating.tsx +108 -0
- package/templates/react/src/components/ModusSelect.tsx +171 -0
- package/templates/react/src/components/ModusSideNavigation.tsx +149 -0
- package/templates/react/src/components/ModusSkeleton.tsx +42 -0
- package/templates/react/src/components/ModusSlider.tsx +128 -0
- package/templates/react/src/components/ModusStepper.tsx +85 -0
- package/templates/react/src/components/ModusSwitch.tsx +130 -0
- package/templates/react/src/components/ModusTable.tsx +309 -0
- package/templates/react/src/components/ModusTabs.tsx +114 -0
- package/templates/react/src/components/ModusTextInput.tsx +179 -0
- package/templates/react/src/components/ModusTextarea.tsx +164 -0
- package/templates/react/src/components/ModusThemeSwitcher.tsx +58 -0
- package/templates/react/src/components/ModusTimeInput.tsx +176 -0
- package/templates/react/src/components/ModusToast.tsx +207 -0
- package/templates/react/src/components/ModusToolbar.tsx +70 -0
- package/templates/react/src/components/ModusTooltip.tsx +97 -0
- package/templates/react/src/components/ModusUtilityPanel.tsx +198 -0
- package/templates/react/src/components/ThemeSwitcherDropdown.tsx +117 -0
- package/templates/react/src/components/ThemeToggleSimple.tsx +157 -0
- package/templates/react/src/config/routes.ts +196 -0
- package/templates/react/src/contexts/ThemeContext.tsx +81 -0
- package/templates/react/src/contexts/ThemeContextData.tsx +89 -0
- package/templates/react/src/data/modusIcons.ts +865 -0
- package/templates/react/src/demos/accordion-demo/page.tsx +236 -0
- package/templates/react/src/demos/alert-demo/page.tsx +94 -0
- package/templates/react/src/demos/autocomplete-demo/page.tsx +166 -0
- package/templates/react/src/demos/avatar-demo/page.tsx +135 -0
- package/templates/react/src/demos/badge-demo/page.tsx +174 -0
- package/templates/react/src/demos/breadcrumbs-demo/page.tsx +88 -0
- package/templates/react/src/demos/button-demo/page.tsx +261 -0
- package/templates/react/src/demos/button-group-demo/page.tsx +231 -0
- package/templates/react/src/demos/card-demo/page.tsx +241 -0
- package/templates/react/src/demos/checkbox-demo/page.tsx +79 -0
- package/templates/react/src/demos/chip-demo/page.tsx +197 -0
- package/templates/react/src/demos/date-demo/page.tsx +179 -0
- package/templates/react/src/demos/dropdown-demo/page.tsx +150 -0
- package/templates/react/src/demos/file-dropzone-demo/page.tsx +186 -0
- package/templates/react/src/demos/handle-demo/page.tsx +313 -0
- package/templates/react/src/demos/icon-demo/page.tsx +72 -0
- package/templates/react/src/demos/input-feedback-demo/page.tsx +202 -0
- package/templates/react/src/demos/input-label-demo/page.tsx +392 -0
- package/templates/react/src/demos/loader-demo/page.tsx +138 -0
- package/templates/react/src/demos/logo-demo/page.tsx +292 -0
- package/templates/react/src/demos/menu-demo/page.tsx +70 -0
- package/templates/react/src/demos/modal-demo/page.tsx +332 -0
- package/templates/react/src/demos/navbar-demo/page.tsx +141 -0
- package/templates/react/src/demos/number-input-demo/page.tsx +180 -0
- package/templates/react/src/demos/pagination-demo/page.tsx +147 -0
- package/templates/react/src/demos/panel-demo/page.tsx +376 -0
- package/templates/react/src/demos/progress-demo/page.tsx +185 -0
- package/templates/react/src/demos/radio-demo/page.tsx +242 -0
- package/templates/react/src/demos/rating-demo/page.tsx +97 -0
- package/templates/react/src/demos/select-demo/page.tsx +111 -0
- package/templates/react/src/demos/side-navigation-demo/page.tsx +775 -0
- package/templates/react/src/demos/skeleton-demo/page.tsx +107 -0
- package/templates/react/src/demos/slider-demo/page.tsx +78 -0
- package/templates/react/src/demos/stepper-demo/page.tsx +86 -0
- package/templates/react/src/demos/switch-demo/page.tsx +146 -0
- package/templates/react/src/demos/table-demo/page.tsx +489 -0
- package/templates/react/src/demos/tabs-demo/page.tsx +187 -0
- package/templates/react/src/demos/text-input-demo/page.tsx +151 -0
- package/templates/react/src/demos/textarea-demo/page.tsx +73 -0
- package/templates/react/src/demos/theme-switcher-demo/page.tsx +26 -0
- package/templates/react/src/demos/time-input-demo/page.tsx +148 -0
- package/templates/react/src/demos/toast-demo/page.tsx +302 -0
- package/templates/react/src/demos/toolbar-demo/page.tsx +49 -0
- package/templates/react/src/demos/tooltip-demo/page.tsx +209 -0
- package/templates/react/src/demos/typography-test/page.tsx +28 -0
- package/templates/react/src/demos/utility-panel-demo/page.tsx +197 -0
- package/templates/react/src/dev/DevPanel.tsx +219 -0
- package/templates/react/src/dev/DevPanelContext.ts +14 -0
- package/templates/react/src/dev/DevPanelProvider.tsx +63 -0
- package/templates/react/src/dev/DevRoutes.tsx +98 -0
- package/templates/react/src/dev/config.ts +127 -0
- package/templates/react/src/dev/index.ts +8 -0
- package/templates/react/src/dev/useDevPanel.ts +17 -0
- package/templates/react/src/dev-pages/ColorPalettePage.tsx +347 -0
- package/templates/react/src/dev-pages/ComponentsGalleryPage.tsx +489 -0
- package/templates/react/src/dev-pages/IconsPage.tsx +137 -0
- package/templates/react/src/dev-pages/index.ts +3 -0
- package/templates/react/src/hooks/useTheme.ts +15 -0
- package/templates/react/src/index.css +635 -0
- package/templates/react/src/main.tsx +14 -0
- package/templates/react/src/pages/HomePage.tsx +283 -0
- package/templates/react/src/vite-env.d.ts +9 -0
- package/templates/react/tailwind.config.js +58 -0
- package/templates/react/tsconfig.app.json +27 -0
- package/templates/react/tsconfig.json +7 -0
- package/templates/react/tsconfig.node.json +25 -0
- package/templates/react/vite.config.ts +18 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: set-up-modus-event-listeners
|
|
3
|
+
description: Properly set up and clean up event listeners for Modus web components using useEffect patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Set Up Modus Event Listeners
|
|
7
|
+
|
|
8
|
+
Properly set up and clean up event listeners for Modus web components following established patterns.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Adding event handling to any Modus wrapper component
|
|
14
|
+
- Components need to respond to web component events
|
|
15
|
+
- You need to sync React state with web component state
|
|
16
|
+
- Handling user interactions from Modus components
|
|
17
|
+
|
|
18
|
+
## Pattern Overview
|
|
19
|
+
|
|
20
|
+
All Modus event listeners follow this pattern:
|
|
21
|
+
|
|
22
|
+
1. **Use `useRef`** to get component reference
|
|
23
|
+
2. **Use `useEffect`** to set up listeners
|
|
24
|
+
3. **Check for component existence** before adding listeners
|
|
25
|
+
4. **Create typed handler functions** for each event
|
|
26
|
+
5. **Conditionally attach listeners** based on prop existence
|
|
27
|
+
6. **Return cleanup function** to remove listeners
|
|
28
|
+
|
|
29
|
+
## Reference Examples
|
|
30
|
+
|
|
31
|
+
- **Simple events**: `src/components/ModusCheckbox.tsx:91-150`
|
|
32
|
+
- **Multiple events**: `src/components/ModusDropdownMenu.tsx:79-112`
|
|
33
|
+
- **Complex events**: `src/components/ModusNavbar.tsx` (multiple event handlers)
|
|
34
|
+
|
|
35
|
+
## Basic Template
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { useEffect, useRef } from "react";
|
|
39
|
+
import { ModusWcComponent } from "@trimble-oss/moduswebcomponents-react";
|
|
40
|
+
|
|
41
|
+
export default function ModusComponent({
|
|
42
|
+
onEventName,
|
|
43
|
+
}: {
|
|
44
|
+
onEventName?: (event: CustomEvent<EventDetailType>) => void;
|
|
45
|
+
}) {
|
|
46
|
+
const componentRef = useRef<HTMLModusWcComponentElement>(null);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const component = componentRef.current;
|
|
50
|
+
if (!component) return;
|
|
51
|
+
|
|
52
|
+
const handleEventName = (event: Event) => {
|
|
53
|
+
onEventName?.(event as CustomEvent<EventDetailType>);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (onEventName) {
|
|
57
|
+
component.addEventListener("eventName", handleEventName);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
if (onEventName) {
|
|
62
|
+
component.removeEventListener("eventName", handleEventName);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}, [onEventName]);
|
|
66
|
+
|
|
67
|
+
return <ModusWcComponent ref={componentRef} />;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Multiple Event Handlers
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
export default function ModusComponent({
|
|
75
|
+
onInputChange,
|
|
76
|
+
onInputFocus,
|
|
77
|
+
onInputBlur,
|
|
78
|
+
onValueChange,
|
|
79
|
+
}: {
|
|
80
|
+
onInputChange?: (event: CustomEvent<InputEvent>) => void;
|
|
81
|
+
onInputFocus?: (event: CustomEvent<FocusEvent>) => void;
|
|
82
|
+
onInputBlur?: (event: CustomEvent<FocusEvent>) => void;
|
|
83
|
+
onValueChange?: (event: CustomEvent<boolean>) => void;
|
|
84
|
+
}) {
|
|
85
|
+
const componentRef = useRef<HTMLModusWcComponentElement>(null);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const component = componentRef.current;
|
|
89
|
+
if (!component) return;
|
|
90
|
+
|
|
91
|
+
const handleInputChange = (event: Event) => {
|
|
92
|
+
onInputChange?.(event as CustomEvent<InputEvent>);
|
|
93
|
+
};
|
|
94
|
+
const handleInputFocus = (event: Event) => {
|
|
95
|
+
onInputFocus?.(event as CustomEvent<FocusEvent>);
|
|
96
|
+
};
|
|
97
|
+
const handleInputBlur = (event: Event) => {
|
|
98
|
+
onInputBlur?.(event as CustomEvent<FocusEvent>);
|
|
99
|
+
};
|
|
100
|
+
const handleValueChange = (event: Event) => {
|
|
101
|
+
onValueChange?.(event as CustomEvent<boolean>);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
if (onInputChange)
|
|
105
|
+
component.addEventListener("inputChange", handleInputChange);
|
|
106
|
+
if (onInputFocus)
|
|
107
|
+
component.addEventListener("inputFocus", handleInputFocus);
|
|
108
|
+
if (onInputBlur)
|
|
109
|
+
component.addEventListener("inputBlur", handleInputBlur);
|
|
110
|
+
if (onValueChange)
|
|
111
|
+
component.addEventListener("inputChange", handleValueChange);
|
|
112
|
+
|
|
113
|
+
return () => {
|
|
114
|
+
if (onInputChange)
|
|
115
|
+
component.removeEventListener("inputChange", handleInputChange);
|
|
116
|
+
if (onInputFocus)
|
|
117
|
+
component.removeEventListener("inputFocus", handleInputFocus);
|
|
118
|
+
if (onInputBlur)
|
|
119
|
+
component.removeEventListener("inputBlur", handleInputBlur);
|
|
120
|
+
if (onValueChange)
|
|
121
|
+
component.removeEventListener("inputChange", handleValueChange);
|
|
122
|
+
};
|
|
123
|
+
}, [onInputChange, onInputFocus, onInputBlur, onValueChange]);
|
|
124
|
+
|
|
125
|
+
return <ModusWcComponent ref={componentRef} />;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Key Patterns
|
|
130
|
+
|
|
131
|
+
### 1. Null Check First
|
|
132
|
+
|
|
133
|
+
Always check if component exists:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
const component = componentRef.current;
|
|
138
|
+
if (!component) return; // ✅ Early return if no component
|
|
139
|
+
|
|
140
|
+
// Set up listeners
|
|
141
|
+
}, [dependencies]);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 2. Conditional Listener Attachment
|
|
145
|
+
|
|
146
|
+
Only attach listeners if handlers are provided:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
if (onEventName) {
|
|
150
|
+
component.addEventListener("eventName", handleEventName);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. Proper Cleanup
|
|
155
|
+
|
|
156
|
+
Always remove listeners in cleanup:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
return () => {
|
|
160
|
+
if (onEventName) {
|
|
161
|
+
component.removeEventListener("eventName", handleEventName);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 4. Type Casting
|
|
167
|
+
|
|
168
|
+
Cast events to proper CustomEvent types:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
const handleEvent = (event: Event) => {
|
|
172
|
+
onEvent?.(event as CustomEvent<EventDetailType>);
|
|
173
|
+
};
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 5. Dependencies Array
|
|
177
|
+
|
|
178
|
+
Include all handler props in dependencies:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
// ...
|
|
183
|
+
}, [onEventName, onOtherEvent]); // ✅ Include all handlers
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Common Event Names
|
|
187
|
+
|
|
188
|
+
Modus components use these event names:
|
|
189
|
+
|
|
190
|
+
| Component | Event Name | Detail Type |
|
|
191
|
+
|-----------|------------|-------------|
|
|
192
|
+
| Checkbox | `inputChange` | `InputEvent` |
|
|
193
|
+
| Checkbox | `inputFocus` | `FocusEvent` |
|
|
194
|
+
| Checkbox | `inputBlur` | `FocusEvent` |
|
|
195
|
+
| DropdownMenu | `itemSelect` | `{ value: string }` |
|
|
196
|
+
| DropdownMenu | `menuVisibilityChange` | `{ isVisible: boolean }` |
|
|
197
|
+
| Navbar | `searchClick` | `MouseEvent \| KeyboardEvent` |
|
|
198
|
+
| Navbar | `mainMenuOpenChange` | `boolean` |
|
|
199
|
+
| Accordion | `expandedChange` | `{ expanded: boolean; index: number }` |
|
|
200
|
+
|
|
201
|
+
Check Modus documentation for component-specific events.
|
|
202
|
+
|
|
203
|
+
## Advanced Patterns
|
|
204
|
+
|
|
205
|
+
### Event with Side Effects
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
const handleItemSelect = (event: Event) => {
|
|
209
|
+
const customEvent = event as CustomEvent<{ value: string }>;
|
|
210
|
+
onItemSelect?.(customEvent);
|
|
211
|
+
|
|
212
|
+
// Close menu after selection
|
|
213
|
+
const dropdown = dropdownRef.current;
|
|
214
|
+
if (dropdown) {
|
|
215
|
+
dropdown.menuVisible = false;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Reference: `src/components/ModusDropdownMenu.tsx:86-94`
|
|
221
|
+
|
|
222
|
+
### Event Value Transformation
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
const handleValueChange = (event: Event) => {
|
|
226
|
+
const customEvent = event as CustomEvent<InputEvent>;
|
|
227
|
+
|
|
228
|
+
// Transform or validate value
|
|
229
|
+
const rawValue = (customEvent.target as HTMLModusWcComponentElement).value;
|
|
230
|
+
const transformedValue = transformValue(rawValue);
|
|
231
|
+
|
|
232
|
+
onValueChange?.(new CustomEvent("valueChange", {
|
|
233
|
+
detail: transformedValue,
|
|
234
|
+
}));
|
|
235
|
+
};
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Debounced Events
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
import { useCallback } from "react";
|
|
242
|
+
import { debounce } from "lodash"; // or your debounce utility
|
|
243
|
+
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
const component = componentRef.current;
|
|
246
|
+
if (!component) return;
|
|
247
|
+
|
|
248
|
+
const debouncedHandler = debounce((event: Event) => {
|
|
249
|
+
onSearchChange?.(event as CustomEvent<{ value: string }>);
|
|
250
|
+
}, 300);
|
|
251
|
+
|
|
252
|
+
component.addEventListener("searchChange", debouncedHandler);
|
|
253
|
+
|
|
254
|
+
return () => {
|
|
255
|
+
component.removeEventListener("searchChange", debouncedHandler);
|
|
256
|
+
debouncedHandler.cancel(); // Cancel pending debounced calls
|
|
257
|
+
};
|
|
258
|
+
}, [onSearchChange]);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Common Mistakes
|
|
262
|
+
|
|
263
|
+
1. **Missing cleanup**: Always return cleanup function
|
|
264
|
+
2. **Wrong dependencies**: Include all handler props in dependency array
|
|
265
|
+
3. **Missing null check**: Always check `componentRef.current` exists
|
|
266
|
+
4. **Wrong event names**: Check Modus docs for exact event names
|
|
267
|
+
5. **Not removing listeners**: Must remove in cleanup to prevent memory leaks
|
|
268
|
+
6. **Type casting errors**: Use proper CustomEvent types
|
|
269
|
+
|
|
270
|
+
## Testing Checklist
|
|
271
|
+
|
|
272
|
+
- [ ] Event listeners are attached when component mounts
|
|
273
|
+
- [ ] Event listeners are removed when component unmounts
|
|
274
|
+
- [ ] Handlers are called when events fire
|
|
275
|
+
- [ ] Multiple handlers work correctly
|
|
276
|
+
- [ ] Cleanup prevents memory leaks
|
|
277
|
+
- [ ] TypeScript types are correct
|
|
278
|
+
|
|
279
|
+
## Related Files
|
|
280
|
+
|
|
281
|
+
- `src/components/ModusCheckbox.tsx` - Basic event handling
|
|
282
|
+
- `src/components/ModusDropdownMenu.tsx` - Multiple events
|
|
283
|
+
- `src/components/ModusNavbar.tsx` - Complex event handling
|
|
284
|
+
- `.cursor/rules/modus-react-integration.mdc` - Integration patterns
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: style-modus-components-with-tailwind
|
|
3
|
+
description: Style Modus components using custom border and opacity utilities that work with CSS variables, avoiding Tailwind patterns that don't work with runtime CSS variables
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Style Modus Components with Tailwind
|
|
7
|
+
|
|
8
|
+
Style Modus components using custom border and opacity utilities that work with CSS variables, avoiding Tailwind patterns that don't work with runtime CSS variables.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Styling Modus components with borders
|
|
14
|
+
- Applying opacity to design system colors
|
|
15
|
+
- Creating theme-aware components
|
|
16
|
+
- Avoiding common Tailwind + CSS variable pitfalls
|
|
17
|
+
- Ensuring components work in all 6 Modus themes
|
|
18
|
+
|
|
19
|
+
## The Core Problem
|
|
20
|
+
|
|
21
|
+
**Tailwind CSS** processes colors at **build time**, but **Modus Design System** uses **CSS variables** that resolve at **runtime**. This creates incompatibilities:
|
|
22
|
+
|
|
23
|
+
- ❌ `border-red-500` - Hardcoded color, not theme-aware
|
|
24
|
+
- ❌ `text-foreground/80` - Doesn't work with CSS variables
|
|
25
|
+
- ❌ `border border-destructive` - May not work reliably
|
|
26
|
+
|
|
27
|
+
**Solution**: Use custom utilities that work with CSS variables at runtime.
|
|
28
|
+
|
|
29
|
+
## Reference Documentation
|
|
30
|
+
|
|
31
|
+
For detailed technical explanation, see: `docs/tailwind-css-variables-problem.md`
|
|
32
|
+
|
|
33
|
+
## Custom Border Utilities
|
|
34
|
+
|
|
35
|
+
### Available Border Utilities
|
|
36
|
+
|
|
37
|
+
**Standard borders (1px)**:
|
|
38
|
+
- `border-default` - Default border color
|
|
39
|
+
- `border-success` - Success color border
|
|
40
|
+
- `border-warning` - Warning color border
|
|
41
|
+
- `border-destructive` - Error/destructive color border
|
|
42
|
+
- `border-primary` - Primary/info color border
|
|
43
|
+
|
|
44
|
+
**Thick borders (2px)**:
|
|
45
|
+
- `border-thick` - Thick default border
|
|
46
|
+
- `border-thick-success` - Thick success border
|
|
47
|
+
- `border-thick-warning` - Thick warning border
|
|
48
|
+
- `border-thick-destructive` - Thick destructive border
|
|
49
|
+
- `border-thick-primary` - Thick primary border
|
|
50
|
+
|
|
51
|
+
**Dashed borders**:
|
|
52
|
+
- `border-dashed` - Dashed default border
|
|
53
|
+
- `border-dashed-success` - Dashed success border
|
|
54
|
+
- `border-dashed-warning` - Dashed warning border
|
|
55
|
+
- `border-dashed-destructive` - Dashed destructive border
|
|
56
|
+
|
|
57
|
+
**Directional borders**:
|
|
58
|
+
- `border-top-default`, `border-bottom-success`, `border-left-warning`, `border-right-destructive`
|
|
59
|
+
- Pattern: `border-{direction}-{color}`
|
|
60
|
+
|
|
61
|
+
### Correct Border Usage
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
// ✅ CORRECT: Use custom border utilities
|
|
65
|
+
<div className="border-destructive">Error message</div>
|
|
66
|
+
<div className="border-success">Success message</div>
|
|
67
|
+
<div className="border-thick-primary">Important content</div>
|
|
68
|
+
<div className="border-bottom-default">Separator</div>
|
|
69
|
+
|
|
70
|
+
// ❌ WRONG: Don't use Tailwind color classes
|
|
71
|
+
<div className="border border-red-500">Error</div>
|
|
72
|
+
<div className="border-2 border-green-500">Success</div>
|
|
73
|
+
<div className="border border-blue-500">Info</div>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Border Examples
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// Alert with border
|
|
80
|
+
<div className="bg-card border-destructive rounded-lg p-4">
|
|
81
|
+
<div className="text-destructive font-semibold">Error</div>
|
|
82
|
+
<div className="text-foreground">Something went wrong</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
// Card with border
|
|
86
|
+
<div className="bg-card border-default rounded-lg p-6">
|
|
87
|
+
<div className="text-foreground">Card content</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
// Success indicator
|
|
91
|
+
<div className="border-thick-success rounded p-4">
|
|
92
|
+
<div className="text-success">Operation successful</div>
|
|
93
|
+
</div>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Custom Opacity Utilities
|
|
97
|
+
|
|
98
|
+
### Available Opacity Levels
|
|
99
|
+
|
|
100
|
+
**Opacity levels**: 80%, 60%, 40%, 20%
|
|
101
|
+
|
|
102
|
+
**Pattern**: `{property}-{color}-{opacity}`
|
|
103
|
+
|
|
104
|
+
### Text Opacity
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
// ✅ CORRECT: Use custom opacity utilities
|
|
108
|
+
<div className="text-foreground-80">Subheading (80% opacity)</div>
|
|
109
|
+
<div className="text-foreground-60">Description (60% opacity)</div>
|
|
110
|
+
<div className="text-muted-foreground-40">Hint (40% opacity)</div>
|
|
111
|
+
<div className="text-primary-80">Primary text with opacity</div>
|
|
112
|
+
|
|
113
|
+
// ❌ WRONG: Don't use Tailwind opacity syntax
|
|
114
|
+
<div className="text-foreground/80">Doesn't work</div>
|
|
115
|
+
<div className="text-primary/60">Doesn't work</div>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Background Opacity
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
// ✅ CORRECT: Background with opacity
|
|
122
|
+
<div className="bg-primary-20">Subtle primary background</div>
|
|
123
|
+
<div className="bg-destructive-40">Warning background</div>
|
|
124
|
+
<div className="bg-success-60">Success background</div>
|
|
125
|
+
|
|
126
|
+
// ❌ WRONG: Tailwind opacity syntax
|
|
127
|
+
<div className="bg-primary/20">Doesn't work</div>
|
|
128
|
+
<div className="bg-destructive/40">Doesn't work</div>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Border Opacity
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
// ✅ CORRECT: Border with opacity
|
|
135
|
+
<div className="border border-destructive-40">Subtle error border</div>
|
|
136
|
+
<div className="border border-primary-60">Primary border with opacity</div>
|
|
137
|
+
|
|
138
|
+
// ❌ WRONG: Tailwind opacity syntax
|
|
139
|
+
<div className="border border-destructive/40">Doesn't work</div>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Available Color + Opacity Combinations
|
|
143
|
+
|
|
144
|
+
**Text opacity**:
|
|
145
|
+
- `text-foreground-80`, `text-foreground-60`, `text-foreground-40`, `text-foreground-20`
|
|
146
|
+
- `text-muted-foreground-80`, `text-muted-foreground-60`, etc.
|
|
147
|
+
- `text-primary-80`, `text-primary-60`, `text-primary-40`, `text-primary-20`
|
|
148
|
+
- `text-secondary-80`, `text-secondary-60`, etc.
|
|
149
|
+
- `text-destructive-80`, `text-destructive-60`, etc.
|
|
150
|
+
- `text-warning-80`, `text-warning-60`, etc.
|
|
151
|
+
- `text-success-80`, `text-success-60`, etc.
|
|
152
|
+
|
|
153
|
+
**Background opacity**:
|
|
154
|
+
- `bg-foreground-80`, `bg-foreground-60`, `bg-foreground-40`, `bg-foreground-20`
|
|
155
|
+
- `bg-primary-80`, `bg-primary-60`, `bg-primary-40`, `bg-primary-20`
|
|
156
|
+
- Same pattern for: `secondary`, `destructive`, `warning`, `success`, `muted`
|
|
157
|
+
|
|
158
|
+
**Border opacity**:
|
|
159
|
+
- `border-destructive-80`, `border-destructive-60`, etc.
|
|
160
|
+
- Same pattern for all border colors
|
|
161
|
+
|
|
162
|
+
## Complete Styling Examples
|
|
163
|
+
|
|
164
|
+
### Alert Component
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
// ✅ CORRECT: Theme-aware alert
|
|
168
|
+
<div className="bg-card border-destructive rounded-lg p-4">
|
|
169
|
+
<div className="flex items-center gap-2">
|
|
170
|
+
<i className="modus-icons text-destructive">warning</i>
|
|
171
|
+
<div className="text-destructive font-semibold">Error</div>
|
|
172
|
+
</div>
|
|
173
|
+
<div className="text-foreground-80 mt-2">Error message details</div>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
// ❌ WRONG: Hardcoded colors
|
|
177
|
+
<div className="bg-white border border-red-500 rounded-lg p-4">
|
|
178
|
+
<div className="text-red-500">Error</div>
|
|
179
|
+
<div className="text-gray-600/80">Details</div>
|
|
180
|
+
</div>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Card Component
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
// ✅ CORRECT: Theme-aware card
|
|
187
|
+
<div className="bg-card border-default rounded-lg p-6 shadow-sm">
|
|
188
|
+
<div className="text-foreground text-xl font-semibold mb-2">Card Title</div>
|
|
189
|
+
<div className="text-foreground-60">Card description with muted text</div>
|
|
190
|
+
<div className="mt-4 flex gap-2">
|
|
191
|
+
<ModusButton color="primary">Primary Action</ModusButton>
|
|
192
|
+
<ModusButton variant="borderless">Secondary</ModusButton>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Form Input with Feedback
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
// ✅ CORRECT: Form input styling
|
|
201
|
+
<div>
|
|
202
|
+
<ModusInputLabel label="Email" required />
|
|
203
|
+
<ModusTextInput
|
|
204
|
+
value={email}
|
|
205
|
+
onInputChange={handleEmailChange}
|
|
206
|
+
customClass={errors.email ? "border-destructive" : "border-default"}
|
|
207
|
+
/>
|
|
208
|
+
{errors.email && (
|
|
209
|
+
<ModusInputFeedback
|
|
210
|
+
message={errors.email}
|
|
211
|
+
type="error"
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
214
|
+
</div>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Button States
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
// ✅ CORRECT: Button with hover states
|
|
221
|
+
<button className="
|
|
222
|
+
bg-primary text-primary-foreground
|
|
223
|
+
hover:bg-primary-80
|
|
224
|
+
border-primary
|
|
225
|
+
rounded-lg px-4 py-2
|
|
226
|
+
transition-colors
|
|
227
|
+
">
|
|
228
|
+
Click me
|
|
229
|
+
</button>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Text Hierarchy
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
// ✅ CORRECT: Text hierarchy with opacity
|
|
236
|
+
<div className="space-y-2">
|
|
237
|
+
<div className="text-foreground text-2xl font-bold">Main Heading</div>
|
|
238
|
+
<div className="text-foreground-80 text-lg">Subheading</div>
|
|
239
|
+
<div className="text-foreground-60 text-base">Body text</div>
|
|
240
|
+
<div className="text-muted-foreground-60 text-sm">Caption</div>
|
|
241
|
+
</div>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Common Mistakes to Avoid
|
|
245
|
+
|
|
246
|
+
### Mistake 1: Using Tailwind Color Classes
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
// ❌ WRONG: Hardcoded Tailwind colors
|
|
250
|
+
<div className="border border-red-500">Error</div>
|
|
251
|
+
<div className="text-blue-600">Info</div>
|
|
252
|
+
<div className="bg-green-100">Success</div>
|
|
253
|
+
|
|
254
|
+
// ✅ CORRECT: Design system colors
|
|
255
|
+
<div className="border-destructive">Error</div>
|
|
256
|
+
<div className="text-primary">Info</div>
|
|
257
|
+
<div className="bg-success-20">Success</div>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Mistake 2: Using Tailwind Opacity Syntax
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
// ❌ WRONG: Tailwind opacity syntax doesn't work
|
|
264
|
+
<div className="text-foreground/80">Text</div>
|
|
265
|
+
<div className="bg-primary/60">Background</div>
|
|
266
|
+
<div className="border border-destructive/40">Border</div>
|
|
267
|
+
|
|
268
|
+
// ✅ CORRECT: Custom opacity utilities
|
|
269
|
+
<div className="text-foreground-80">Text</div>
|
|
270
|
+
<div className="bg-primary-60">Background</div>
|
|
271
|
+
<div className="border border-destructive-40">Border</div>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Mistake 3: Mixing Tailwind and Custom Utilities
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
// ❌ WRONG: Mixing incompatible patterns
|
|
278
|
+
<div className="border border-destructive/80">Mixed patterns</div>
|
|
279
|
+
|
|
280
|
+
// ✅ CORRECT: Use custom utilities consistently
|
|
281
|
+
<div className="border border-destructive-80">Consistent pattern</div>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Mistake 4: Using Inline Styles
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
// ❌ WRONG: Inline styles bypass design system
|
|
288
|
+
<div style={{ border: "1px solid var(--modus-wc-color-error)" }}>Error</div>
|
|
289
|
+
<div style={{ color: "rgba(0, 0, 0, 0.8)" }}>Text</div>
|
|
290
|
+
|
|
291
|
+
// ✅ CORRECT: Use utility classes
|
|
292
|
+
<div className="border-destructive">Error</div>
|
|
293
|
+
<div className="text-foreground-80">Text</div>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Migration Patterns
|
|
297
|
+
|
|
298
|
+
### From Tailwind Default Borders
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
// Before: Tailwind defaults
|
|
302
|
+
<div className="border border-red-500">Error</div>
|
|
303
|
+
<div className="border-2 border-green-500">Success</div>
|
|
304
|
+
|
|
305
|
+
// After: Custom utilities
|
|
306
|
+
<div className="border-destructive">Error</div>
|
|
307
|
+
<div className="border-thick-success">Success</div>
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### From Tailwind Opacity Modifiers
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// Before: Tailwind opacity (doesn't work)
|
|
314
|
+
<div className="text-foreground/80">Text</div>
|
|
315
|
+
<div className="bg-primary/60">Background</div>
|
|
316
|
+
|
|
317
|
+
// After: Custom opacity utilities
|
|
318
|
+
<div className="text-foreground-80">Text</div>
|
|
319
|
+
<div className="bg-primary-60">Background</div>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### From Inline Styles
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
// Before: Inline styles
|
|
326
|
+
<div style={{
|
|
327
|
+
border: "1px solid var(--modus-wc-color-error)",
|
|
328
|
+
color: "rgba(0, 0, 0, 0.8)"
|
|
329
|
+
}}>Content</div>
|
|
330
|
+
|
|
331
|
+
// After: Utility classes
|
|
332
|
+
<div className="border-destructive text-foreground-80">Content</div>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Theme Compatibility
|
|
336
|
+
|
|
337
|
+
All custom utilities work with **all 6 Modus themes**:
|
|
338
|
+
|
|
339
|
+
- ✅ Classic Light
|
|
340
|
+
- ✅ Classic Dark
|
|
341
|
+
- ✅ Modern Light
|
|
342
|
+
- ✅ Modern Dark
|
|
343
|
+
- ✅ Connect Light
|
|
344
|
+
- ✅ Connect Dark
|
|
345
|
+
|
|
346
|
+
Colors automatically adapt when themes change - no code changes needed.
|
|
347
|
+
|
|
348
|
+
## Implementation Location
|
|
349
|
+
|
|
350
|
+
Custom utilities are defined in:
|
|
351
|
+
- **`src/index.css`** - All border and opacity utilities
|
|
352
|
+
|
|
353
|
+
## Testing Checklist
|
|
354
|
+
|
|
355
|
+
- [ ] Components use custom border utilities (not Tailwind colors)
|
|
356
|
+
- [ ] Opacity uses custom utilities (not `/80` syntax)
|
|
357
|
+
- [ ] No hardcoded colors (hex, RGB, Tailwind defaults)
|
|
358
|
+
- [ ] Components work in all 6 themes
|
|
359
|
+
- [ ] Colors adapt when theme switches
|
|
360
|
+
- [ ] No inline styles for colors/borders
|
|
361
|
+
|
|
362
|
+
## Related Files
|
|
363
|
+
|
|
364
|
+
- `docs/tailwind-css-variables-problem.md` - Detailed technical explanation
|
|
365
|
+
- `src/index.css` - Custom utility definitions
|
|
366
|
+
- `.cursor/rules/border-usage-guidelines.mdc` - Border usage rules
|
|
367
|
+
- `.cursor/rules/modus-opacity-utilities-react.mdc` - Opacity utilities rules
|
|
368
|
+
- `.cursor/rules/modus-color-usage-react.mdc` - Color usage rules
|
|
369
|
+
|
|
370
|
+
## Quick Reference
|
|
371
|
+
|
|
372
|
+
### Borders
|
|
373
|
+
- Use: `border-destructive`, `border-success`, `border-warning`, `border-primary`
|
|
374
|
+
- Don't use: `border-red-500`, `border-green-500`, `border border-destructive`
|
|
375
|
+
|
|
376
|
+
### Opacity
|
|
377
|
+
- Use: `text-foreground-80`, `bg-primary-60`, `border-destructive-40`
|
|
378
|
+
- Don't use: `text-foreground/80`, `bg-primary/60`, `border-destructive/40`
|
|
379
|
+
|
|
380
|
+
### Colors
|
|
381
|
+
- Use: `text-foreground`, `bg-primary`, `text-destructive`
|
|
382
|
+
- Don't use: `text-gray-900`, `bg-blue-500`, `text-red-600`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Default owners
|
|
2
|
+
* @julianoczkowski
|
|
3
|
+
|
|
4
|
+
# Documentation
|
|
5
|
+
*.md @julianoczkowski
|
|
6
|
+
README.md @julianoczkowski
|
|
7
|
+
|
|
8
|
+
# Application code
|
|
9
|
+
src/ @julianoczkowski
|
|
10
|
+
types/ @julianoczkowski
|
|
11
|
+
|
|
12
|
+
# Tooling and configuration
|
|
13
|
+
.github/ @julianoczkowski
|
|
14
|
+
scripts/ @julianoczkowski
|
|
15
|
+
package.json @julianoczkowski
|
|
16
|
+
tsconfig.json @julianoczkowski
|
|
17
|
+
tsconfig.app.json @julianoczkowski
|
|
18
|
+
tsconfig.node.json @julianoczkowski
|
|
19
|
+
vite.config.ts @julianoczkowski
|
|
20
|
+
postcss.config.js @julianoczkowski
|
|
21
|
+
eslint.config.js @julianoczkowski
|
|
22
|
+
tailwind.config.js @julianoczkowski
|
|
23
|
+
|
|
24
|
+
# Custom rules
|
|
25
|
+
.cursor/rules/ @julianoczkowski
|
|
26
|
+
|
|
27
|
+
# Scripts
|
|
28
|
+
scripts/ @julianoczkowski
|