@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,182 @@
1
+ ---
2
+ title: Specify Explicit Duration for Nested Transitions
3
+ impact: MEDIUM
4
+ impactDescription: Nested transitions with different timings may end prematurely when Vue detects only the root element's transition end
5
+ type: gotcha
6
+ tags: [vue3, transition, animation, duration, nested, timing]
7
+ ---
8
+
9
+ # Specify Explicit Duration for Nested Transitions
10
+
11
+ **Impact: MEDIUM** - When transitioning elements that contain nested child elements with different animation timings, Vue by default listens only for the first `transitionend` or `animationend` event on the **root** transition element. This means if inner elements have longer or delayed animations, they may be cut off when the root element's transition completes.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Identify if your transition contains nested elements with different animation durations
16
+ - [ ] Use the `:duration` prop to specify the total time Vue should wait
17
+ - [ ] Consider using separate enter and leave durations if they differ
18
+ - [ ] Test animations to ensure nested elements complete fully
19
+
20
+ **Problematic Code:**
21
+ ```vue
22
+ <template>
23
+ <!-- BAD: Inner element has longer animation that gets cut off -->
24
+ <Transition name="nested">
25
+ <div v-if="show" class="outer">
26
+ <div class="inner">Hello</div>
27
+ </div>
28
+ </Transition>
29
+ </template>
30
+
31
+ <style>
32
+ .nested-enter-active .outer,
33
+ .nested-leave-active .outer {
34
+ transition: opacity 0.3s ease;
35
+ }
36
+
37
+ .nested-enter-active .inner,
38
+ .nested-leave-active .inner {
39
+ /* This 0.5s animation gets cut off at 0.3s when outer finishes! */
40
+ transition: transform 0.5s ease 0.2s; /* 0.2s delay + 0.5s = 0.7s total */
41
+ }
42
+
43
+ .nested-enter-from .outer,
44
+ .nested-leave-to .outer {
45
+ opacity: 0;
46
+ }
47
+
48
+ .nested-enter-from .inner,
49
+ .nested-leave-to .inner {
50
+ transform: translateX(-30px);
51
+ }
52
+ </style>
53
+ ```
54
+
55
+ **Correct Code:**
56
+ ```vue
57
+ <template>
58
+ <!-- GOOD: Explicit duration ensures all nested animations complete -->
59
+ <Transition name="nested" :duration="700">
60
+ <div v-if="show" class="outer">
61
+ <div class="inner">Hello</div>
62
+ </div>
63
+ </Transition>
64
+ </template>
65
+
66
+ <style>
67
+ .nested-enter-active .outer,
68
+ .nested-leave-active .outer {
69
+ transition: opacity 0.3s ease;
70
+ }
71
+
72
+ .nested-enter-active .inner,
73
+ .nested-leave-active .inner {
74
+ /* Now this animation completes fully */
75
+ transition: transform 0.5s ease 0.2s;
76
+ }
77
+
78
+ .nested-enter-from .outer,
79
+ .nested-leave-to .outer {
80
+ opacity: 0;
81
+ }
82
+
83
+ .nested-enter-from .inner,
84
+ .nested-leave-to .inner {
85
+ transform: translateX(-30px);
86
+ }
87
+ </style>
88
+ ```
89
+
90
+ ## Different Enter and Leave Durations
91
+
92
+ ```vue
93
+ <template>
94
+ <!-- GOOD: Separate durations for enter and leave -->
95
+ <Transition
96
+ name="complex"
97
+ :duration="{ enter: 500, leave: 800 }"
98
+ >
99
+ <div v-if="show" class="container">
100
+ <h1 class="title">Title</h1>
101
+ <p class="content">Content with staggered animation</p>
102
+ </div>
103
+ </Transition>
104
+ </template>
105
+
106
+ <style>
107
+ /* Enter: title first, then content */
108
+ .complex-enter-active .title {
109
+ transition: opacity 0.3s ease, transform 0.3s ease;
110
+ }
111
+
112
+ .complex-enter-active .content {
113
+ transition: opacity 0.3s ease 0.2s, transform 0.3s ease 0.2s;
114
+ }
115
+
116
+ /* Leave: content first, then title (reverse order) */
117
+ .complex-leave-active .content {
118
+ transition: opacity 0.3s ease, transform 0.3s ease;
119
+ }
120
+
121
+ .complex-leave-active .title {
122
+ transition: opacity 0.5s ease 0.3s, transform 0.5s ease 0.3s;
123
+ }
124
+
125
+ .complex-enter-from .title,
126
+ .complex-enter-from .content,
127
+ .complex-leave-to .title,
128
+ .complex-leave-to .content {
129
+ opacity: 0;
130
+ transform: translateY(20px);
131
+ }
132
+ </style>
133
+ ```
134
+
135
+ ## Choreographed Staggered Animations
136
+
137
+ ```vue
138
+ <template>
139
+ <Transition name="stagger" :duration="800">
140
+ <div v-if="show" class="card">
141
+ <img class="card-image" src="..." />
142
+ <h2 class="card-title">Title</h2>
143
+ <p class="card-body">Body text...</p>
144
+ <button class="card-action">Action</button>
145
+ </div>
146
+ </Transition>
147
+ </template>
148
+
149
+ <style>
150
+ /* Staggered entrance: image -> title -> body -> action */
151
+ .stagger-enter-active .card-image { transition: all 0.3s ease; }
152
+ .stagger-enter-active .card-title { transition: all 0.3s ease 0.1s; }
153
+ .stagger-enter-active .card-body { transition: all 0.3s ease 0.2s; }
154
+ .stagger-enter-active .card-action { transition: all 0.3s ease 0.3s; }
155
+ /* Total: 0.3s delay + 0.3s animation = 0.6s, but use 800ms for safety */
156
+
157
+ .stagger-enter-from .card-image,
158
+ .stagger-enter-from .card-title,
159
+ .stagger-enter-from .card-body,
160
+ .stagger-enter-from .card-action {
161
+ opacity: 0;
162
+ transform: translateY(10px);
163
+ }
164
+ </style>
165
+ ```
166
+
167
+ ## Calculating Duration
168
+
169
+ Use this formula to calculate the correct duration:
170
+ ```
171
+ duration = max(delay + animation_duration) for all nested elements
172
+ ```
173
+
174
+ Example:
175
+ - Element A: no delay, 300ms duration = 300ms total
176
+ - Element B: 100ms delay, 300ms duration = 400ms total
177
+ - Element C: 200ms delay, 500ms duration = 700ms total
178
+
179
+ **Required `:duration`**: 700 (or slightly higher for safety margin)
180
+
181
+ ## Reference
182
+ - [Vue.js Transition - Nested Transitions](https://vuejs.org/guide/built-ins/transition.html#nested-transitions-and-explicit-transition-durations)
@@ -0,0 +1,245 @@
1
+ ---
2
+ title: Avoid Scoped Styles in Reusable Transition Components
3
+ impact: MEDIUM
4
+ impactDescription: Scoped styles in transition wrapper components won't apply to slotted content, breaking the transition animation
5
+ type: gotcha
6
+ tags: [vue3, transition, scoped-css, slot, reusable-component]
7
+ ---
8
+
9
+ # Avoid Scoped Styles in Reusable Transition Components
10
+
11
+ **Impact: MEDIUM** - When creating reusable transition wrapper components, using `<style scoped>` will prevent the transition CSS classes from applying to slotted content. Scoped styles only affect elements directly in the component's template, not content passed through slots. Your transition animations will silently fail.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] In reusable transition components, use `<style>` without `scoped`
16
+ - [ ] Alternatively, use unique class name prefixes to avoid global conflicts
17
+ - [ ] Or use CSS modules with `:global()` for transition classes
18
+ - [ ] Test that transitions work when component is used in different contexts
19
+
20
+ **Problematic Code:**
21
+ ```vue
22
+ <!-- MyFadeTransition.vue -->
23
+ <template>
24
+ <Transition name="my-fade">
25
+ <slot />
26
+ </Transition>
27
+ </template>
28
+
29
+ <!-- BAD: Scoped styles won't apply to slot content! -->
30
+ <style scoped>
31
+ .my-fade-enter-active,
32
+ .my-fade-leave-active {
33
+ transition: opacity 0.3s ease;
34
+ }
35
+
36
+ .my-fade-enter-from,
37
+ .my-fade-leave-to {
38
+ opacity: 0;
39
+ }
40
+ </style>
41
+ ```
42
+
43
+ ```vue
44
+ <!-- Parent component using the transition -->
45
+ <template>
46
+ <MyFadeTransition>
47
+ <div v-if="show">This won't animate!</div>
48
+ </MyFadeTransition>
49
+ </template>
50
+
51
+ <!--
52
+ The <div> is slotted content, so .my-fade-* classes
53
+ applied by Vue won't match the scoped CSS selectors
54
+ -->
55
+ ```
56
+
57
+ **Correct Code:**
58
+ ```vue
59
+ <!-- MyFadeTransition.vue -->
60
+ <template>
61
+ <Transition name="my-fade">
62
+ <slot />
63
+ </Transition>
64
+ </template>
65
+
66
+ <!-- GOOD: Unscoped styles apply to any element -->
67
+ <style>
68
+ .my-fade-enter-active,
69
+ .my-fade-leave-active {
70
+ transition: opacity 0.3s ease;
71
+ }
72
+
73
+ .my-fade-enter-from,
74
+ .my-fade-leave-to {
75
+ opacity: 0;
76
+ }
77
+ </style>
78
+ ```
79
+
80
+ ## Alternative: Use Unique Prefixed Class Names
81
+
82
+ To avoid global style conflicts, use distinctive prefixes:
83
+
84
+ ```vue
85
+ <!-- FadeTransition.vue -->
86
+ <template>
87
+ <Transition name="v-fade-transition">
88
+ <slot />
89
+ </Transition>
90
+ </template>
91
+
92
+ <style>
93
+ /* Unique prefix reduces collision risk */
94
+ .v-fade-transition-enter-active,
95
+ .v-fade-transition-leave-active {
96
+ transition: opacity 0.3s ease;
97
+ }
98
+
99
+ .v-fade-transition-enter-from,
100
+ .v-fade-transition-leave-to {
101
+ opacity: 0;
102
+ }
103
+ </style>
104
+ ```
105
+
106
+ ## Alternative: CSS Modules with :global()
107
+
108
+ ```vue
109
+ <!-- FadeTransition.vue -->
110
+ <template>
111
+ <Transition name="fade">
112
+ <slot />
113
+ </Transition>
114
+ </template>
115
+
116
+ <style module>
117
+ /* Use :global() for transition classes */
118
+ :global(.fade-enter-active),
119
+ :global(.fade-leave-active) {
120
+ transition: opacity 0.3s ease;
121
+ }
122
+
123
+ :global(.fade-enter-from),
124
+ :global(.fade-leave-to) {
125
+ opacity: 0;
126
+ }
127
+ </style>
128
+ ```
129
+
130
+ ## Alternative: Custom Transition Classes
131
+
132
+ Use the custom class props to apply scoped classes:
133
+
134
+ ```vue
135
+ <!-- FadeTransition.vue -->
136
+ <template>
137
+ <Transition
138
+ :enter-active-class="$style.enterActive"
139
+ :leave-active-class="$style.leaveActive"
140
+ :enter-from-class="$style.enterFrom"
141
+ :leave-to-class="$style.leaveTo"
142
+ >
143
+ <slot />
144
+ </Transition>
145
+ </template>
146
+
147
+ <style module>
148
+ .enterActive,
149
+ .leaveActive {
150
+ transition: opacity 0.3s ease;
151
+ }
152
+
153
+ .enterFrom,
154
+ .leaveTo {
155
+ opacity: 0;
156
+ }
157
+ </style>
158
+ ```
159
+
160
+ ## Complete Reusable Transition Component Example
161
+
162
+ ```vue
163
+ <!-- transitions/SlideTransition.vue -->
164
+ <template>
165
+ <Transition
166
+ name="slide"
167
+ :mode="mode"
168
+ :appear="appear"
169
+ @before-enter="$emit('before-enter', $event)"
170
+ @enter="$emit('enter', $event)"
171
+ @after-enter="$emit('after-enter', $event)"
172
+ @before-leave="$emit('before-leave', $event)"
173
+ @leave="$emit('leave', $event)"
174
+ @after-leave="$emit('after-leave', $event)"
175
+ >
176
+ <slot />
177
+ </Transition>
178
+ </template>
179
+
180
+ <script setup>
181
+ defineProps({
182
+ mode: {
183
+ type: String,
184
+ default: 'out-in',
185
+ validator: (v) => ['out-in', 'in-out', ''].includes(v)
186
+ },
187
+ appear: {
188
+ type: Boolean,
189
+ default: false
190
+ }
191
+ })
192
+
193
+ defineEmits([
194
+ 'before-enter', 'enter', 'after-enter',
195
+ 'before-leave', 'leave', 'after-leave'
196
+ ])
197
+ </script>
198
+
199
+ <!-- Unscoped so styles apply to slotted content -->
200
+ <style>
201
+ .slide-enter-active,
202
+ .slide-leave-active {
203
+ transition: transform 0.3s ease, opacity 0.3s ease;
204
+ }
205
+
206
+ .slide-enter-from {
207
+ opacity: 0;
208
+ transform: translateX(-20px);
209
+ }
210
+
211
+ .slide-leave-to {
212
+ opacity: 0;
213
+ transform: translateX(20px);
214
+ }
215
+ </style>
216
+ ```
217
+
218
+ Usage:
219
+ ```vue
220
+ <template>
221
+ <SlideTransition>
222
+ <div v-if="show" class="content">
223
+ This will properly animate!
224
+ </div>
225
+ </SlideTransition>
226
+ </template>
227
+ ```
228
+
229
+ ## Why This Happens
230
+
231
+ Vue's scoped styles work by adding a unique data attribute (e.g., `data-v-7ba5bd90`) to elements and selectors:
232
+
233
+ ```css
234
+ /* What you write */
235
+ .my-fade-enter-active { ... }
236
+
237
+ /* What Vue generates (scoped) */
238
+ .my-fade-enter-active[data-v-7ba5bd90] { ... }
239
+ ```
240
+
241
+ Slotted content comes from the parent component and gets the parent's data attribute, not the transition component's attribute. So the selectors never match.
242
+
243
+ ## Reference
244
+ - [Vue.js Reusable Transitions](https://vuejs.org/guide/built-ins/transition.html#reusable-transitions)
245
+ - [Vue.js Scoped CSS](https://vuejs.org/api/sfc-css-features.html#scoped-css)
@@ -0,0 +1,193 @@
1
+ ---
2
+ title: RouterView Transitions Always Apply Despite Missing appear Prop
3
+ impact: LOW
4
+ impactDescription: Initial page load with RouterView triggers transition animation even without the appear prop due to async navigation
5
+ type: gotcha
6
+ tags: [vue3, transition, vue-router, appear, initial-load, navigation]
7
+ ---
8
+
9
+ # RouterView Transitions Always Apply Despite Missing appear Prop
10
+
11
+ **Impact: LOW** - When using `<Transition>` with Vue Router's `<RouterView>`, the enter transition animation runs on initial page load even if you haven't added the `appear` prop. This differs from normal Transition behavior where `appear` is required for initial render animations. This happens because Vue Router's navigations are asynchronous, causing the component to mount after the initial render.
12
+
13
+ ## Task Checklist
14
+
15
+ - [ ] Be aware that RouterView transitions always animate on initial load
16
+ - [ ] If you want NO animation on initial load, you need to handle this explicitly
17
+ - [ ] Don't add `appear` prop expecting it to change behavior - it's already effectively enabled
18
+ - [ ] Consider whether initial animation is desired for your UX
19
+
20
+ **Expected Behavior (Normal Transition):**
21
+ ```vue
22
+ <template>
23
+ <!-- Without appear: No animation on initial render -->
24
+ <Transition name="fade">
25
+ <div v-if="show">Content</div>
26
+ </Transition>
27
+
28
+ <!-- With appear: Animates on initial render -->
29
+ <Transition name="fade" appear>
30
+ <div v-if="show">Content</div>
31
+ </Transition>
32
+ </template>
33
+ ```
34
+
35
+ **RouterView Behavior (Different!):**
36
+ ```vue
37
+ <template>
38
+ <!-- RouterView transitions ALWAYS animate on initial load -->
39
+ <!-- The appear prop has no effect here -->
40
+ <RouterView v-slot="{ Component }">
41
+ <Transition name="fade">
42
+ <component :is="Component" />
43
+ </Transition>
44
+ </RouterView>
45
+ </template>
46
+
47
+ <!--
48
+ On initial page load:
49
+ 1. Vue renders the app
50
+ 2. Router resolves the route (async)
51
+ 3. Component mounts AFTER initial render
52
+ 4. Enter transition triggers (as if toggled from v-if="false" to v-if="true")
53
+ -->
54
+ ```
55
+
56
+ ## Why This Happens
57
+
58
+ Vue Router navigations are asynchronous. The sequence is:
59
+
60
+ 1. Vue application mounts with empty RouterView
61
+ 2. Router resolves the initial route
62
+ 3. Route component is inserted into RouterView
63
+ 4. This insertion triggers the enter transition
64
+
65
+ Since the component wasn't present in the initial render and is "inserted" afterward, Vue treats it as a normal enter transition, not an initial render.
66
+
67
+ ## If You Want to Disable Initial Animation
68
+
69
+ ```vue
70
+ <template>
71
+ <RouterView v-slot="{ Component }">
72
+ <Transition :name="isInitialLoad ? '' : 'fade'" mode="out-in">
73
+ <component :is="Component" />
74
+ </Transition>
75
+ </RouterView>
76
+ </template>
77
+
78
+ <script setup>
79
+ import { ref, onMounted } from 'vue'
80
+ import { useRouter } from 'vue-router'
81
+
82
+ const isInitialLoad = ref(true)
83
+ const router = useRouter()
84
+
85
+ // After first navigation completes, enable transitions
86
+ router.isReady().then(() => {
87
+ // Small delay to ensure initial render is complete
88
+ setTimeout(() => {
89
+ isInitialLoad.value = false
90
+ }, 0)
91
+ })
92
+ </script>
93
+ ```
94
+
95
+ ## Alternative: Use CSS to Skip First Animation
96
+
97
+ ```vue
98
+ <template>
99
+ <RouterView v-slot="{ Component }">
100
+ <Transition name="fade" mode="out-in">
101
+ <component :is="Component" :class="{ 'skip-initial': isInitialLoad }" />
102
+ </Transition>
103
+ </RouterView>
104
+ </template>
105
+
106
+ <script setup>
107
+ import { ref } from 'vue'
108
+ import { useRouter } from 'vue-router'
109
+
110
+ const isInitialLoad = ref(true)
111
+ const router = useRouter()
112
+
113
+ router.isReady().then(() => {
114
+ isInitialLoad.value = false
115
+ })
116
+ </script>
117
+
118
+ <style>
119
+ .fade-enter-active,
120
+ .fade-leave-active {
121
+ transition: opacity 0.3s ease;
122
+ }
123
+
124
+ .fade-enter-from,
125
+ .fade-leave-to {
126
+ opacity: 0;
127
+ }
128
+
129
+ /* Skip animation on initial load */
130
+ .skip-initial.fade-enter-active {
131
+ transition: none;
132
+ }
133
+ </style>
134
+ ```
135
+
136
+ ## Standard RouterView Transition Pattern
137
+
138
+ If you're fine with initial animation (often desired), use the standard pattern:
139
+
140
+ ```vue
141
+ <template>
142
+ <RouterView v-slot="{ Component, route }">
143
+ <Transition :name="route.meta.transition || 'fade'" mode="out-in">
144
+ <component :is="Component" :key="route.path" />
145
+ </Transition>
146
+ </RouterView>
147
+ </template>
148
+
149
+ <style>
150
+ .fade-enter-active,
151
+ .fade-leave-active {
152
+ transition: opacity 0.3s ease;
153
+ }
154
+
155
+ .fade-enter-from,
156
+ .fade-leave-to {
157
+ opacity: 0;
158
+ }
159
+
160
+ /* Route-specific transitions via meta */
161
+ .slide-enter-active,
162
+ .slide-leave-active {
163
+ transition: transform 0.3s ease;
164
+ }
165
+
166
+ .slide-enter-from {
167
+ transform: translateX(100%);
168
+ }
169
+
170
+ .slide-leave-to {
171
+ transform: translateX(-100%);
172
+ }
173
+ </style>
174
+ ```
175
+
176
+ ```javascript
177
+ // router.js
178
+ const routes = [
179
+ {
180
+ path: '/',
181
+ component: Home
182
+ },
183
+ {
184
+ path: '/about',
185
+ component: About,
186
+ meta: { transition: 'slide' } // Custom transition for this route
187
+ }
188
+ ]
189
+ ```
190
+
191
+ ## Reference
192
+ - [Vue Router Transitions](https://router.vuejs.org/guide/advanced/transitions.html)
193
+ - [Vue.js Transition appear](https://vuejs.org/guide/built-ins/transition.html#transition-on-appear)