Skip to content

Commit

Permalink
feat(useGenericTransition): create 1-2-3 transitions
Browse files Browse the repository at this point in the history
add docs for transitions composables
  • Loading branch information
StevenJPx2 committed Jan 4, 2024
1 parent 7599b49 commit b59ff97
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 23 deletions.
2 changes: 1 addition & 1 deletion playground/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const onAfterEnter = async () => {
<h1
v-split-animate="{
splitBy: 'lines',
animationOptions: { translate: 'left' },
animationOptions: { translate: true },
splitOptions: {
wrapping: {
select: 'lines',
Expand Down
1 change: 0 additions & 1 deletion src/runtime/components/InfiniteMarquee.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import {
computed,
ref,
toRef,
tryOnMounted,
useElementSize,
useElementVisibility,
Expand Down
25 changes: 25 additions & 0 deletions src/runtime/composables/transitions/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
# `transitions/`

These are composables for kick-ass transitions. This could be used to transition between pages, hover effects, components, etc.

## Motivation
This emulates the way Vuejs handles transitions but completely in Javascript.

The `useConstructTransition` composable takes care of this entirely with callbacks for all the states that the transition can be in. This is used in all the other transition composables.

### Why not use native Vue.js transitions?
Well, I came across this issue myself, where I found that I needed to transition **content** but not any components themselves. `<Transition />` albeit being inheritly powerful and one of my favorite features of Vue, does not give any control on **when** the transition should start. It only performs a transition when a `v-if` or any kind of directive that deals with **replacing the DOM via reactivity** is run.

Because of this, this composable will be most useful for:
- Button effects
- Changing content *inside* a component

## Composables

### Low-level
`useConstructTransition` - As explained above, composable used in all the composables below. It gives the most control over every part of the transition.

### Mid-level
`useGenericTransition` - used for constructing simpler transitions. It gives animation control but abstracts away the nitty-gritty of the enter-exit strategy. Useful if you're making a transition with a 1-2-1 or 1-2-3 pattern. See [`useBakedTransition`](./baked) for usage of this composable.

### High-level
- `useBakedTransition` - implements [**baked**](../baked) animations in transitions. Allows you to easily stack premium animations with no effort.
- `useBendyWendyTransition` - implements a very opinionated transition that looks bendy-wendy.
- `useOffsetTransition` - implements an opinionated offset transition.
1 change: 1 addition & 0 deletions src/runtime/composables/transitions/baked.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function useBakedTransition(
} = options;
const { from, to } = generateAnimationTweens(animationOptions);
const output = useGenericTransition({
strategy: "from-to",
from: { ...from, duration: 0.4, ease: "power2" },
to: { ...to, duration: 0.6, ease: "expo.out" },
direction,
Expand Down
1 change: 0 additions & 1 deletion src/runtime/composables/transitions/construct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
unrefElement,
unref,
type Ref,
computed,
} from "#imports";
import type { ShallowRef } from "vue";
import type { MaybeComputedElementRef } from "@vueuse/core";
Expand Down
80 changes: 60 additions & 20 deletions src/runtime/composables/transitions/generic.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toRef, tryOnMounted, unref, unrefElement, watch } from "#imports";
import { toRef, unref, unrefElement, watch } from "#imports";
import type { Simplify } from "../../types";
import { type StrongTweenVars, useGsap } from "../use-gsap";
import {
Expand All @@ -8,7 +8,25 @@ import {
} from "./construct";

export type UseGenericTransitionOptions = Simplify<
{ from: StrongTweenVars; to: StrongTweenVars } & UseConstructTransitionOptions
(
| {
strategy: "from-to";
/** The initial state of the element */
from: StrongTweenVars;
/** The entered state of the element */
to: StrongTweenVars;
}
| {
strategy: "enter-set-exit";
/** The initial state of the element */
enter: StrongTweenVars;
/** The entered state of the element */
set: StrongTweenVars;
/** The exiting state of the element */
exit: StrongTweenVars;
}
) &
UseConstructTransitionOptions
>;
/**
* Composable to create generic transitions
Expand All @@ -22,29 +40,51 @@ export type UseGenericTransitionOptions = Simplify<
export function useGenericTransition(
options: UseGenericTransitionOptions,
): TransitionOutput {
const { from, to, ...constructOptions } = options;
const container = toRef(constructOptions.parentContainer);
const container = toRef(options.parentContainer);

const { set } = useGsap();
const { set: setGsap } = useGsap();

const { enterTl, leaveTl, ...output } =
useConstructTransition(constructOptions);
if (options.strategy === "from-to") {
const { from, to, ...constructOptions } = options;

tryOnMounted(() => {
set(container, from);
});
const { enterTl, leaveTl, ...output } =
useConstructTransition(constructOptions);

watch(
() => [unrefElement(container), unref(enterTl), unref(leaveTl)] as const,
([parent, eTl, lTl]) => {
if (!parent || !eTl || !lTl) return;
setGsap(container, from);

eTl.fromTo(parent, from, to);
watch(
() => [unrefElement(container), unref(enterTl), unref(leaveTl)] as const,
([parent, eTl, lTl]) => {
if (!parent || !eTl || !lTl) return;

lTl.fromTo(parent, to, from);
},
{ immediate: true, flush: "post" },
);
eTl.fromTo(parent, from, to);

return output;
lTl.fromTo(parent, to, from);
},
{ immediate: true, flush: "post" },
);

return output;
} else {
const { enter, set, exit, ...constructOptions } = options;

const { enterTl, leaveTl, ...output } =
useConstructTransition(constructOptions);

setGsap(container, enter);

watch(
() => [unrefElement(container), unref(enterTl), unref(leaveTl)] as const,
([parent, eTl, lTl]) => {
if (!parent || !eTl || !lTl) return;

eTl.fromTo(parent, enter, set);

lTl.fromTo(parent, set, exit);
},
{ immediate: true, flush: "post" },
);

return output;
}
}

0 comments on commit b59ff97

Please sign in to comment.