-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(staggered-fade-and-slide): use Vue native staggered transition
- Loading branch information
1 parent
f1f5c07
commit 9d634f1
Showing
7 changed files
with
290 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
packages/_vue3-migration-test/src/components/animations/test-staggered-fade-and-slide.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<template> | ||
<h1>Dinamic content:</h1> | ||
<button @click="insert">Insert at random index</button> | ||
<button @click="reset">Reset</button> | ||
|
||
<Vue3StaggeredFadeAndSlide :stagger="500"> | ||
<li v-for="item in items" :key="item.id"> | ||
{{ item.id }} - {{ item.name }} | ||
<button @click="remove(item)">x</button> | ||
</li> | ||
</Vue3StaggeredFadeAndSlide> | ||
|
||
<br /> | ||
<h1>Animation as prop</h1> | ||
<BaseSuggestions :suggestions="suggestions" :animation="Vue3StaggeredFadeAndSlide" :stagger="50"> | ||
<template #default="{ suggestion }"> | ||
<span>{{ suggestion.query }}</span> | ||
</template> | ||
</BaseSuggestions> | ||
|
||
<br /> | ||
<h1>Static content:</h1> | ||
<Vue3StaggeredFadeAndSlide :stagger="50"> | ||
<li key="1">Element to animate</li> | ||
<li key="2">Element to animate</li> | ||
<li key="3">Element to animate</li> | ||
</Vue3StaggeredFadeAndSlide> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref } from 'vue'; | ||
import Vue3StaggeredFadeAndSlide from '../../../../x-components/src/components/animations/vue3-staggered-fade-and-slide.vue'; | ||
import BaseSuggestions from '../../../../x-components/src/components/suggestions/base-suggestions.vue'; | ||
import { | ||
getQuerySuggestionsStub, | ||
createResultStub, | ||
getResultsStub | ||
} from '../../../../x-components/src/__stubs__'; | ||
const suggestions = getQuerySuggestionsStub('chip', 5); | ||
const getInitialItems = () => getResultsStub(5); | ||
const items = ref(getInitialItems()); | ||
let id = items.value.length + 1; | ||
/** | ||
* Insert a new item at a random index. | ||
*/ | ||
function insert() { | ||
const i = Math.round(Math.random() * items.value.length); | ||
items.value.splice(i, 0, createResultStub(`Product ${id++}`)); | ||
} | ||
/** | ||
* Reset the list of items. | ||
*/ | ||
function reset() { | ||
items.value = getInitialItems(); | ||
id = items.value.length + 1; | ||
} | ||
/** | ||
* Remove an item from the list. | ||
* | ||
* @param item - The item to remove. | ||
*/ | ||
function remove(item: any) { | ||
const i = items.value.indexOf(item); | ||
if (i > -1) { | ||
items.value.splice(i, 1); | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
172 changes: 172 additions & 0 deletions
172
packages/x-components/src/components/animations/vue3-staggered-fade-and-slide.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<template> | ||
<!-- eslint-disable vue/attributes-order --> | ||
<TransitionGroup | ||
v-bind="$attrs" | ||
v-on="$listeners" | ||
@enter="enter" | ||
@after-enter="afterEnter" | ||
:appear="appear" | ||
:name="name" | ||
:tag="tag" | ||
> | ||
<slot /> | ||
</TransitionGroup> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, ref } from 'vue'; | ||
import { useDisableAnimation } from './use-disable-animation'; | ||
/** | ||
* Renders a transition group wrapping the elements passed in the default slot and animating | ||
* them with a staggered fade and slide animation. | ||
* | ||
* @public | ||
*/ | ||
export default defineComponent({ | ||
name: 'StaggeredFadeAndSlide', | ||
inheritAttrs: false, | ||
props: { | ||
/** | ||
* Indicates if the transition must be applied on the initial render of the node. | ||
*/ | ||
appear: { | ||
type: Boolean, | ||
default: true | ||
}, | ||
/** | ||
* The tag of the node to render to the DOM. | ||
*/ | ||
tag: { | ||
type: String, | ||
default: 'div' | ||
}, | ||
/** | ||
* The time in ms to stagger each item. | ||
*/ | ||
stagger: { | ||
type: Number, | ||
default: 25 | ||
} | ||
}, | ||
setup(props) { | ||
/** | ||
* The duration of the transition in ms. | ||
*/ | ||
const transitionDuration = 250; | ||
/** | ||
* The counter to keep track of the staggered delay. | ||
*/ | ||
const staggerCounter = ref(0); | ||
/** | ||
* The counter to keep track of the animations. | ||
*/ | ||
const animationList = ref<HTMLElement[]>([]); | ||
/** | ||
* The name of the animation. | ||
*/ | ||
const animationName = ref('x-staggered-fade-and-slide'); | ||
/** | ||
* The name of the animation. | ||
*/ | ||
const { name } = useDisableAnimation(animationName.value); | ||
/** | ||
* Calculate the delay for the next element. | ||
* | ||
* @returns The delay in ms. | ||
*/ | ||
function getNextTransitionDelay(): number { | ||
return staggerCounter.value++ * props.stagger; | ||
} | ||
/** | ||
* The enter transition. | ||
* | ||
* @param el | ||
* @param done | ||
*/ | ||
function enter(el: HTMLElement, done: () => void) { | ||
animationList.value.push(el); | ||
const delay = getNextTransitionDelay(); | ||
el.style.transitionDelay = `${delay}ms`; | ||
setTimeout(() => { | ||
el.style.transitionDelay = '0ms'; | ||
done(); | ||
}, transitionDuration + delay); | ||
} | ||
/** | ||
* The after enter transition. | ||
* | ||
* @param el | ||
*/ | ||
function afterEnter(el: HTMLElement) { | ||
animationList.value = animationList.value.filter(item => item !== el); | ||
if (animationList.value.length === 0) { | ||
staggerCounter.value = 0; | ||
} | ||
} | ||
return { | ||
name, | ||
enter, | ||
afterEnter | ||
}; | ||
} | ||
}); | ||
</script> | ||
|
||
<style lang="scss"> | ||
$transition-duration: 0.25s; | ||
/* 1. Declare transitions */ | ||
.x-staggered-fade-and-slide-enter-active, | ||
.x-staggered-fade-and-slide-leave-active { | ||
transition: $transition-duration ease-out; | ||
transition-property: opacity, transform; | ||
} | ||
.x-staggered-fade-and-slide-move { | ||
transition: transform $transition-duration ease-out; | ||
} | ||
/* 2. declare enter from and leave to state */ | ||
.x-staggered-fade-and-slide-enter, | ||
.x-staggered-fade-and-slide-enter-from, | ||
.x-staggered-fade-and-slide-leave-to { | ||
opacity: 0; | ||
transform: translate3d(0, 50%, 0); | ||
} | ||
/* 3. ensure leaving items are taken out of layout flow so that moving | ||
animations can be calculated correctly. */ | ||
.x-staggered-fade-and-slide-leave-active { | ||
position: absolute; | ||
} | ||
</style> | ||
|
||
<docs lang="mdx"> | ||
The Staggered fade and slide components works as the normal fade and slide components, but it also | ||
adds a configurable delay to each transition. | ||
|
||
## Example | ||
|
||
### Used with animatable components | ||
|
||
```vue | ||
<AnimatableComponent :animation="StaggeredFadeAndSlide" /> | ||
``` | ||
|
||
### Used as a regular component: | ||
|
||
This components exposes all the props and events of the Staggering transition group, like the `tag` | ||
or the `stagger` props: | ||
|
||
```vue | ||
<StaggeredFadeAndSlide tag="ul" :stagger="50"> | ||
<li key="1">Element to animate</li> | ||
<li key="2">Element to animate</li> | ||
<li key="3">Element to animate</li> | ||
</StaggeredFadeAndSlide> | ||
``` | ||
</docs> |
Oops, something went wrong.