@pythoughts/vue-skills-mcp 0.1.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 (208) hide show
  1. package/README.md +63 -0
  2. package/index.mjs +139 -0
  3. package/package.json +34 -0
  4. package/skills/create-adaptable-composable/SKILL.md +76 -0
  5. package/skills/vue-best-practices/SKILL.md +154 -0
  6. package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
  7. package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
  8. package/skills/vue-best-practices/references/component-async.md +97 -0
  9. package/skills/vue-best-practices/references/component-data-flow.md +350 -0
  10. package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
  11. package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
  12. package/skills/vue-best-practices/references/component-slots.md +216 -0
  13. package/skills/vue-best-practices/references/component-suspense.md +228 -0
  14. package/skills/vue-best-practices/references/component-teleport.md +108 -0
  15. package/skills/vue-best-practices/references/component-transition-group.md +128 -0
  16. package/skills/vue-best-practices/references/component-transition.md +125 -0
  17. package/skills/vue-best-practices/references/composables.md +290 -0
  18. package/skills/vue-best-practices/references/directives.md +162 -0
  19. package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
  20. package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
  21. package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
  22. package/skills/vue-best-practices/references/plugins.md +166 -0
  23. package/skills/vue-best-practices/references/reactivity.md +346 -0
  24. package/skills/vue-best-practices/references/render-functions.md +201 -0
  25. package/skills/vue-best-practices/references/sfc.md +310 -0
  26. package/skills/vue-best-practices/references/state-management.md +135 -0
  27. package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
  28. package/skills/vue-debug-guides/SKILL.md +205 -0
  29. package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
  30. package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
  31. package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
  32. package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
  33. package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
  34. package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
  35. package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
  36. package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
  37. package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
  38. package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
  39. package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
  40. package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
  41. package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
  42. package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
  43. package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
  44. package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
  45. package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
  46. package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
  47. package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
  48. package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
  49. package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
  50. package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
  51. package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
  52. package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
  53. package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
  54. package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
  55. package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
  56. package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
  57. package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
  58. package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
  59. package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
  60. package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
  61. package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
  62. package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
  63. package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
  64. package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
  65. package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
  66. package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
  67. package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
  68. package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
  69. package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
  70. package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
  71. package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
  72. package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
  73. package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
  74. package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
  75. package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
  76. package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
  77. package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
  78. package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
  79. package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
  80. package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
  81. package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
  82. package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
  83. package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
  84. package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
  85. package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
  86. package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
  87. package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
  88. package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
  89. package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
  90. package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
  91. package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
  92. package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
  93. package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
  94. package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
  95. package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
  96. package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
  97. package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
  98. package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
  99. package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
  100. package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
  101. package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
  102. package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
  103. package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
  104. package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
  105. package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
  106. package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
  107. package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
  108. package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
  109. package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
  110. package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
  111. package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
  112. package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
  113. package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
  114. package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
  115. package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
  116. package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
  117. package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
  118. package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
  119. package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
  120. package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
  121. package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
  122. package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
  123. package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
  124. package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
  125. package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
  126. package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
  127. package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
  128. package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
  129. package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
  130. package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
  131. package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
  132. package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
  133. package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
  134. package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
  135. package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
  136. package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
  137. package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
  138. package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
  139. package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
  140. package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
  141. package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
  142. package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
  143. package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
  144. package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
  145. package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
  146. package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
  147. package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
  148. package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
  149. package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
  150. package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
  151. package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
  152. package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
  153. package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
  154. package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
  155. package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
  156. package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
  157. package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
  158. package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
  159. package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
  160. package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
  161. package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
  162. package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
  163. package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
  164. package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
  165. package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
  166. package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
  167. package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
  168. package/skills/vue-jsx-best-practices/SKILL.md +12 -0
  169. package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
  170. package/skills/vue-options-api-best-practices/SKILL.md +23 -0
  171. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
  172. package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
  173. package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
  174. package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
  175. package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
  176. package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
  177. package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
  178. package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
  179. package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
  180. package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
  181. package/skills/vue-pinia-best-practices/SKILL.md +21 -0
  182. package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
  183. package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
  184. package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
  185. package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
  186. package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
  187. package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
  188. package/skills/vue-router-best-practices/SKILL.md +23 -0
  189. package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
  190. package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
  191. package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
  192. package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
  193. package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
  194. package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
  195. package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
  196. package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
  197. package/skills/vue-testing-best-practices/SKILL.md +29 -0
  198. package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
  199. package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
  200. package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
  201. package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
  202. package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
  203. package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
  204. package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
  205. package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
  206. package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
  207. package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
  208. package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
@@ -0,0 +1,172 @@
1
+ ---
2
+ title: Specify Transition Type When Mixing CSS Transitions and Animations
3
+ impact: MEDIUM
4
+ impactDescription: Vue may detect the wrong transition end event when both CSS transitions and animations are applied, causing timing issues
5
+ type: gotcha
6
+ tags: [vue3, transition, animation, css, type, timing]
7
+ ---
8
+
9
+ # Specify Transition Type When Mixing CSS Transitions and Animations
10
+
11
+ **Impact: MEDIUM** - When you have both CSS transitions and CSS animations applied to the same element (for example, a Vue-triggered animation combined with a hover transition effect), Vue cannot automatically determine which end event to listen for. You must explicitly tell Vue which type to prioritize using the `type` attribute with a value of either `"animation"` or `"transition"`.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Check if your element has both `transition` and `animation` CSS properties
16
+ - [ ] Determine which timing should control when Vue considers the transition complete
17
+ - [ ] Add `type="animation"` or `type="transition"` to the `<Transition>` component
18
+ - [ ] The type should match whichever animation/transition is longer or more important
19
+
20
+ **Problematic Code:**
21
+ ```vue
22
+ <template>
23
+ <!-- BAD: Both transition and animation present, Vue might pick wrong end event -->
24
+ <Transition name="bounce">
25
+ <div v-if="show" class="box">
26
+ Hover me for additional effect
27
+ </div>
28
+ </Transition>
29
+ </template>
30
+
31
+ <style>
32
+ /* Vue-triggered CSS animation */
33
+ .bounce-enter-active {
34
+ animation: bounce-in 0.5s;
35
+ }
36
+
37
+ .bounce-leave-active {
38
+ animation: bounce-out 0.3s;
39
+ }
40
+
41
+ @keyframes bounce-in {
42
+ 0% { transform: scale(0); }
43
+ 50% { transform: scale(1.2); }
44
+ 100% { transform: scale(1); }
45
+ }
46
+
47
+ @keyframes bounce-out {
48
+ 0% { transform: scale(1); }
49
+ 100% { transform: scale(0); }
50
+ }
51
+
52
+ /* Additional hover transition on same element */
53
+ .box {
54
+ transition: background-color 0.2s ease, box-shadow 0.2s ease;
55
+ }
56
+
57
+ .box:hover {
58
+ background-color: #f0f0f0;
59
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
60
+ }
61
+ </style>
62
+ ```
63
+
64
+ **Correct Code:**
65
+ ```vue
66
+ <template>
67
+ <!-- GOOD: Explicitly specify that animation controls timing -->
68
+ <Transition name="bounce" type="animation">
69
+ <div v-if="show" class="box">
70
+ Hover me for additional effect
71
+ </div>
72
+ </Transition>
73
+ </template>
74
+
75
+ <style>
76
+ /* Vue-triggered CSS animation - this is what we care about */
77
+ .bounce-enter-active {
78
+ animation: bounce-in 0.5s;
79
+ }
80
+
81
+ .bounce-leave-active {
82
+ animation: bounce-out 0.3s;
83
+ }
84
+
85
+ @keyframes bounce-in {
86
+ 0% { transform: scale(0); }
87
+ 50% { transform: scale(1.2); }
88
+ 100% { transform: scale(1); }
89
+ }
90
+
91
+ @keyframes bounce-out {
92
+ 0% { transform: scale(1); }
93
+ 100% { transform: scale(0); }
94
+ }
95
+
96
+ /* Additional hover transition - unrelated to Vue transition timing */
97
+ .box {
98
+ transition: background-color 0.2s ease, box-shadow 0.2s ease;
99
+ }
100
+
101
+ .box:hover {
102
+ background-color: #f0f0f0;
103
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
104
+ }
105
+ </style>
106
+ ```
107
+
108
+ ## When to Use Each Type
109
+
110
+ ### Use `type="animation"` when:
111
+ - Your enter/leave effects use `@keyframes` animations
112
+ - The animation is longer than any transitions
113
+ - You want precise control over multi-step animations
114
+
115
+ ```vue
116
+ <Transition name="fancy" type="animation">
117
+ <div v-if="show" class="animated-element" />
118
+ </Transition>
119
+
120
+ <style>
121
+ .fancy-enter-active {
122
+ animation: fancy-entrance 1s ease-out;
123
+ }
124
+
125
+ .animated-element {
126
+ /* This shorter transition should not affect timing */
127
+ transition: color 0.2s;
128
+ }
129
+ </style>
130
+ ```
131
+
132
+ ### Use `type="transition"` when:
133
+ - Your enter/leave effects use CSS `transition` property
134
+ - You have decorative animations that shouldn't affect timing
135
+
136
+ ```vue
137
+ <Transition name="slide" type="transition">
138
+ <div v-if="show" class="sliding-element" />
139
+ </Transition>
140
+
141
+ <style>
142
+ .slide-enter-active,
143
+ .slide-leave-active {
144
+ transition: transform 0.3s ease;
145
+ }
146
+
147
+ .slide-enter-from,
148
+ .slide-leave-to {
149
+ transform: translateX(-100%);
150
+ }
151
+
152
+ /* Decorative infinite animation should not affect timing */
153
+ .sliding-element {
154
+ animation: pulse 2s infinite;
155
+ }
156
+
157
+ @keyframes pulse {
158
+ 0%, 100% { opacity: 1; }
159
+ 50% { opacity: 0.8; }
160
+ }
161
+ </style>
162
+ ```
163
+
164
+ ## Common Symptoms Without Type Specification
165
+
166
+ 1. Transition ends too early (element snaps to final position)
167
+ 2. Transition hangs or takes too long to complete
168
+ 3. Element disappears before animation finishes
169
+ 4. CSS classes remain applied after transition should be complete
170
+
171
+ ## Reference
172
+ - [Vue.js Transition Documentation](https://vuejs.org/guide/built-ins/transition.html#css-based-transitions)
@@ -0,0 +1,149 @@
1
+ ---
2
+ title: Unmount Hooks May Not Fire Inside Transitions During Fast Replacement
3
+ impact: MEDIUM
4
+ impactDescription: Components inside transitions can be destroyed without unmount hooks firing under race conditions
5
+ type: gotcha
6
+ tags: [vue3, lifecycle, transition, onUnmounted, unmounted, cleanup, race-condition]
7
+ ---
8
+
9
+ # Unmount Hooks May Not Fire Inside Transitions During Fast Replacement
10
+
11
+ **Impact: MEDIUM** - When a component inside a `<transition>` is replaced by another component during the transition's loading phase, the unmount hooks (`onBeforeUnmount`, `onUnmounted`) may not be called even though the component is removed from the DOM. This can cause memory leaks and resource leaks from unclean side effects.
12
+
13
+ This is a known edge case that occurs when the timing is specific - if a parent component with a child inside a transition is replaced while the child is still mounting. The child's mount hooks fire, but unmount hooks never do.
14
+
15
+ ## Task Checklist
16
+
17
+ - [ ] Be aware that unmount hooks are not 100% guaranteed inside transitions
18
+ - [ ] For critical cleanup, consider alternative cleanup strategies
19
+ - [ ] Use `mode="out-in"` on transitions to ensure old component fully unmounts before new mounts
20
+ - [ ] For essential resources, consider cleanup at parent component level
21
+ - [ ] Test component replacement scenarios during development
22
+
23
+ **Problematic Scenario:**
24
+ ```vue
25
+ <!-- Parent component with lazy-loaded child in transition -->
26
+ <template>
27
+ <transition>
28
+ <Suspense>
29
+ <component :is="currentComponent" />
30
+ </Suspense>
31
+ </transition>
32
+ </template>
33
+ ```
34
+
35
+ ```javascript
36
+ // Child component - unmount hooks may not fire if parent changes quickly
37
+ export default {
38
+ setup() {
39
+ const socket = new WebSocket('wss://example.com')
40
+
41
+ onMounted(() => {
42
+ console.log('Mounted - this will run')
43
+ socket.connect()
44
+ })
45
+
46
+ onUnmounted(() => {
47
+ // WARNING: This may NOT run if component is inside transition
48
+ // and parent navigates away during mounting phase!
49
+ console.log('Unmounted - might not run')
50
+ socket.close()
51
+ })
52
+ }
53
+ }
54
+ ```
55
+
56
+ **Safer Patterns:**
57
+ ```vue
58
+ <!-- SAFER: Use out-in mode to ensure proper sequencing -->
59
+ <template>
60
+ <transition mode="out-in">
61
+ <component :is="currentComponent" :key="currentKey" />
62
+ </transition>
63
+ </template>
64
+ ```
65
+
66
+ ```javascript
67
+ // SAFER: Cleanup at parent level for critical resources
68
+ // Parent component
69
+ export default {
70
+ setup() {
71
+ const childSocket = ref(null)
72
+
73
+ // Parent controls resource lifecycle
74
+ provide('registerSocket', (socket) => {
75
+ childSocket.value = socket
76
+ })
77
+
78
+ onUnmounted(() => {
79
+ // Parent ensures cleanup even if child unmount hook doesn't fire
80
+ childSocket.value?.close()
81
+ })
82
+ }
83
+ }
84
+
85
+ // Child component
86
+ export default {
87
+ setup() {
88
+ const registerSocket = inject('registerSocket')
89
+ const socket = new WebSocket('wss://example.com')
90
+
91
+ // Register with parent for backup cleanup
92
+ registerSocket(socket)
93
+
94
+ onMounted(() => {
95
+ socket.connect()
96
+ })
97
+
98
+ onUnmounted(() => {
99
+ socket.close() // Still attempt cleanup here
100
+ })
101
+ }
102
+ }
103
+ ```
104
+
105
+ ```javascript
106
+ // SAFER: Use AbortController pattern for cancellable operations
107
+ export default {
108
+ setup() {
109
+ const abortController = new AbortController()
110
+
111
+ onMounted(() => {
112
+ fetch('/api/data', { signal: abortController.signal })
113
+ .then(handleData)
114
+ .catch(err => {
115
+ if (err.name !== 'AbortError') {
116
+ handleError(err)
117
+ }
118
+ })
119
+ })
120
+
121
+ onUnmounted(() => {
122
+ // If this doesn't fire, request continues but response is ignored
123
+ // Not a memory leak - just potentially wasted network call
124
+ abortController.abort()
125
+ })
126
+ }
127
+ }
128
+ ```
129
+
130
+ ## Testing for This Issue
131
+
132
+ ```javascript
133
+ // Test by rapidly switching components during async loading
134
+ async function testUnmountHooks() {
135
+ // Mount component A (has async setup)
136
+ await mountComponent('A')
137
+
138
+ // Immediately switch to B before A finishes mounting
139
+ await mountComponent('B')
140
+
141
+ // Check if A's unmount hooks fired
142
+ // They may not have!
143
+ }
144
+ ```
145
+
146
+ ## Reference
147
+ - [Vue.js GitHub Issue #6260](https://github.com/vuejs/core/issues/6260)
148
+ - [Vue.js Transition](https://vuejs.org/guide/built-ins/transition.html)
149
+ - [Vue.js Lifecycle Hooks](https://vuejs.org/guide/essentials/lifecycle.html)
@@ -0,0 +1,225 @@
1
+ ---
2
+ title: Boolean Props Default to false, Not undefined
3
+ impact: MEDIUM
4
+ impactDescription: TypeScript expects optional boolean to be undefined but Vue defaults it to false, causing type confusion
5
+ type: gotcha
6
+ tags: [vue3, typescript, props, boolean, defineProps]
7
+ ---
8
+
9
+ # Boolean Props Default to false, Not undefined
10
+
11
+ **Impact: MEDIUM** - When using type-based `defineProps`, optional boolean props (marked with `?`) behave differently than TypeScript expects. Vue treats boolean props specially: an absent boolean prop defaults to `false`, not `undefined`. This can cause confusion when TypeScript thinks the type is `boolean | undefined`.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Understand that Vue's boolean casting makes absent booleans `false`
16
+ - [ ] Use `withDefaults()` to be explicit about boolean defaults
17
+ - [ ] Consider using non-boolean types if `undefined` is a meaningful state
18
+ - [ ] Document this Vue-specific behavior for your team
19
+
20
+ ## The Gotcha
21
+
22
+ ```vue
23
+ <script setup lang="ts">
24
+ interface Props {
25
+ disabled?: boolean // TypeScript sees: boolean | undefined
26
+ }
27
+
28
+ const props = defineProps<Props>()
29
+
30
+ // TypeScript thinks props.disabled could be undefined
31
+ if (props.disabled === undefined) {
32
+ console.log('This will NEVER run!')
33
+ // Vue's boolean casting means disabled is false, not undefined
34
+ }
35
+ </script>
36
+
37
+ <template>
38
+ <!-- When used without the prop -->
39
+ <MyComponent />
40
+ <!-- disabled is false, NOT undefined -->
41
+ </template>
42
+ ```
43
+
44
+ ## Why This Happens
45
+
46
+ Vue has special "boolean casting" behavior inherited from HTML boolean attributes:
47
+
48
+ ```vue
49
+ <!-- All of these make disabled = true -->
50
+ <MyComponent disabled />
51
+ <MyComponent :disabled="true" />
52
+ <MyComponent disabled="" />
53
+
54
+ <!-- This makes disabled = false (NOT undefined) -->
55
+ <MyComponent />
56
+
57
+ <!-- Explicit false -->
58
+ <MyComponent :disabled="false" />
59
+ ```
60
+
61
+ This is by design to match how HTML works:
62
+ ```html
63
+ <!-- HTML: presence means true, absence means false -->
64
+ <button disabled>Can't click</button>
65
+ <button>Can click</button>
66
+ ```
67
+
68
+ ## Solutions
69
+
70
+ ### Solution 1: Be Explicit with withDefaults
71
+
72
+ Make your intention clear:
73
+
74
+ ```vue
75
+ <script setup lang="ts">
76
+ interface Props {
77
+ disabled?: boolean
78
+ }
79
+
80
+ // Explicitly document the default
81
+ const props = withDefaults(defineProps<Props>(), {
82
+ disabled: false // Now it's clear this defaults to false
83
+ })
84
+ </script>
85
+ ```
86
+
87
+ ### Solution 2: Use a Three-State Type
88
+
89
+ If you actually need to distinguish "not set" from "explicitly false":
90
+
91
+ ```vue
92
+ <script setup lang="ts">
93
+ interface Props {
94
+ // Use a union type instead of optional boolean
95
+ state?: 'enabled' | 'disabled' | undefined
96
+
97
+ // Or use undefined explicitly
98
+ toggleState?: boolean | undefined
99
+ }
100
+
101
+ const props = withDefaults(defineProps<Props>(), {
102
+ state: undefined, // Can actually be undefined
103
+ toggleState: undefined
104
+ })
105
+
106
+ // Now you can check for undefined
107
+ if (props.state === undefined) {
108
+ // Use parent's state
109
+ } else if (props.state === 'disabled') {
110
+ // Explicitly disabled
111
+ }
112
+ </script>
113
+ ```
114
+
115
+ ### Solution 3: Use null for "Not Set"
116
+
117
+ ```vue
118
+ <script setup lang="ts">
119
+ interface Props {
120
+ // null = not set, false = explicitly off, true = explicitly on
121
+ selected: boolean | null
122
+ }
123
+
124
+ const props = withDefaults(defineProps<Props>(), {
125
+ selected: null
126
+ })
127
+
128
+ // Three distinct states
129
+ if (props.selected === null) {
130
+ console.log('Selection not specified')
131
+ } else if (props.selected) {
132
+ console.log('Selected')
133
+ } else {
134
+ console.log('Explicitly not selected')
135
+ }
136
+ </script>
137
+ ```
138
+
139
+ ## Boolean Casting Order
140
+
141
+ Vue also has special behavior when Boolean and String are both valid:
142
+
143
+ ```typescript
144
+ // Order matters in runtime declaration!
145
+ defineProps({
146
+ // Boolean first: empty string becomes true
147
+ disabled: [Boolean, String]
148
+ })
149
+
150
+ // <MyComponent disabled /> → disabled = true
151
+ // <MyComponent disabled="" /> → disabled = true
152
+ ```
153
+
154
+ ```typescript
155
+ defineProps({
156
+ // String first: empty string stays as string
157
+ disabled: [String, Boolean]
158
+ })
159
+
160
+ // <MyComponent disabled /> → disabled = ''
161
+ // <MyComponent disabled="" /> → disabled = ''
162
+ ```
163
+
164
+ With type-based declaration, Boolean always takes priority for absent props.
165
+
166
+ ## Common Bug Pattern
167
+
168
+ ```vue
169
+ <!-- Parent.vue -->
170
+ <script setup lang="ts">
171
+ const userPreferences = ref({
172
+ darkMode: undefined as boolean | undefined
173
+ })
174
+
175
+ // Fetch preferences...
176
+ onMounted(async () => {
177
+ userPreferences.value = await fetchPreferences()
178
+ })
179
+ </script>
180
+
181
+ <template>
182
+ <!-- Bug: undefined becomes false, not "inherit system preference" -->
183
+ <ThemeToggle :darkMode="userPreferences.darkMode" />
184
+ </template>
185
+ ```
186
+
187
+ **Fix:**
188
+
189
+ ```vue
190
+ <script setup lang="ts">
191
+ const userPreferences = ref<{
192
+ darkMode: boolean | null
193
+ }>({
194
+ darkMode: null // Use null for "not yet loaded"
195
+ })
196
+ </script>
197
+
198
+ <template>
199
+ <!-- Now ThemeToggle can distinguish between null and false -->
200
+ <ThemeToggle :darkMode="userPreferences.darkMode" />
201
+ </template>
202
+ ```
203
+
204
+ ## TypeScript Type Accuracy
205
+
206
+ The Vue type system handles this, but it can be confusing:
207
+
208
+ ```typescript
209
+ interface Props {
210
+ disabled?: boolean
211
+ }
212
+
213
+ const props = defineProps<Props>()
214
+
215
+ // At compile time: boolean | undefined
216
+ // At runtime: boolean (never undefined due to Vue's boolean casting)
217
+
218
+ // TypeScript is technically "wrong" here, but the withDefaults usage
219
+ // or explicit false default can help align expectations
220
+ ```
221
+
222
+ ## Reference
223
+ - [Vue.js Props - Boolean Casting](https://vuejs.org/guide/components/props.html#boolean-casting)
224
+ - [GitHub Issue: Boolean props default to false](https://github.com/vuejs/core/issues/8576)
225
+ - [TypeScript Vue 3 Props](https://madewithlove.com/blog/typescript-vue-3-and-strongly-typed-props/)