A lightweight transition library for solid-js.
npm i @otonashixav/solid-flip
yarn add @otonashixav/solid-flip
pnpm i @otonashixav/solid-flip
<TransitionGroup
enter={animateEnter()}
exit={animateExit()}
move={animateMove()}
>
<For each={list()}>{(item) => <span>{item}</span>}</For>
<Switch fallback={<span>Fallback Tab</span>}>
<Match when={number() === 1}>
<span>Tab 1</span>
</Match>
<Match when={number() === 2}>
<span>Tab 2</span>
</Match>
<Match when={number() === 3}>
<span>Tab 3</span>
</Match>
<Match when={number() === 4}>
<span>Tab 4</span>
</Match>
</Switch>
</TransitionGroup>
The TransitionGroup
component should wrap elements to be transitioned. Only Elements (not TextNodes or other non-Element Nodes) are supported.
These are callbacks which if provided, are used to animate child elements as they enter, exit and are reordered. You can either pass your own functions or use the provided integrations.
A callback called when elements enter. Accepts an array of entering elements. Used to transition entering elements. If initial
is defined on the function, it will be called when the TransitionGroup
component is created if there is no initial
prop passed in.
A callback called when elements exit. Accepts an array of exiting elements and a callback to remove one or all of them. Used to transition exiting elements.
A callback called when children elements are added, removed, or reordered. Accepts an array of all elements. Used to move elements using the FLIP technique.
A callback called initially when the TransitionGroup
component is first created. Accepts an array of all initally present elements. Used to apply initial styling. Also accepts a boolean; if true, calls enter
, and if false, stops enter.initial
from being called if present.
All of these integrations can be provided with either keyframes (as a string or callback) and options to be passed to element.animate
or a callback to manually animate an element.
These animation options are applied by default:
const DEFAULT_OPTIONS = {
duration: 300,
easing: "ease",
fill: "backwards",
};
function animateEnter(
animate:
| {
keyframes: KeyframeType | ((el: StylableElement) => KeyframeType);
options?: KeyframeAnimationOptions;
}
| ((el: StylableElement) => Promise<unknown>) = {}
): EnterIntegration;
animate
must return a Promise if provided with a callback. The elements will be removed once the Promise resolves.keyframes
defaults to a simple fade out animation.unabsolute
: SeeundetachEls
.reverseExit: true
causes the element to enter by reversing ongoing exit animations, identified byid: exit
, instead of entering with the provided animation.
function animateExit(
animate:
| {
keyframes: KeyframeType | ((el: StylableElement) => KeyframeType);
options?: KeyframeAnimationOptions;
}
| ((el: StylableElement) => Promise<unknown>) = {},
options: {
absolute?: boolean;
reverseEnter?: boolean;
separate?: boolean;
} = {}
): ExitIntegration;
animate
must return a Promise if provided with a callback. The elements will be removed once the Promise resolves.keyframes
defaults to a simple fade out animation.absolute
: SeedetachEls
.reverseEnter: true
causes the element to exit by reversing ongoing enter animations, identified byid: enter
, instead of exiting with the provided animation.
function animateMove(
animate:
| {
keyframes?: (el: StylableElement, x: number, y: number) => KeyframeType;
options?: KeyframeAnimationOptions;
}
| ((el: StylableElement, x: number, y: number) => void) = {}
): MoveIntegration;
keyframes
defaults to a simple straight line movement. If providing your own animation, it should move the element from (x, y)
to (0, 0)
.
These add and remove classes to transition elements. These accept a classes object with these properties:
name
- If provided, also adds an additional class to each of the other three props. For example, when provided to cssEnter, addsname-enter-from
,name-enter-active
andname-enter-to
to the classes.from
- Classes to add, then remove. This is the starting point for transitioning.active
- Classes that should be present during the transition. These usually provide css animations.to
- Classes that are added after thefrom
classes are removed, and persist after the transition ends.
function cssEnter(
classNames: {
name?: string;
from?: string;
active?: string;
to?: string;
},
options: {
unabsolute?: boolean;
type?: "animationend" | "transitionend" | "both";
} = {}
): EnterIntegration;
unabsolute
: See undetachEls
.
type
: Which event to listen to (defaults to both).
function cssExit(
classes: {
name?: string;
from?: string;
active?: string;
to?: string;
},
options: {
absolute?: boolean;
type?: "animationend" | "transitionend" | "both";
} = {}
): ExitIntegration;
absolute
: See detachEls
.
type
: Which event to listen to (defaults to both).
Helper functions for composing your own integrations.
Filters an array of elements to just those which have moved after the DOM updates. Returns an array which will contain these elements after the DOM updates.
Sets the position
, left
, top
, width
, height
and margin
properties such that the element is detached from the document flow with position: absolute
and left where it was when it began to exit. Uses an animation with id detach
.
Clears the position
, left
, top
, width
, height
and margin
properties. Clears an animation with id detach
.
Any callbacks run in an onMount
will run after entering elements have been mounted.
- Fix SSR.
- Use
createRenderEffect
instead ofcreateEffect
in fix in 0.10.3, so that the initial render isn't empty.
- Fix interaction with suspense #6.
- Improve detach by making it not set styles on the element.
- Avoid multiple instances of batching.
- Improve compatibility with Safari (?).
- Call
onEntered
andonExited
even when there are noenter
andexit
integrations.
- Added
onEntering
,onEntered
,onExiting
,onExited
listeners. Note that while these will be called with arrays,onEntered
is (currently) always called with single element arrays due to implementation details. - Made it possible to use already created elements in
TransitionGroup
, allowed exiting elements to be reentered and added other necessary changes to allow aborting exiting. - Made the move integration run before enter, instead of before enter and exit, and delayed the final step of it using nested
onMount
s. - Removed
separate
; everything is "separate" now, but exiting elements will be batched before exiting to try to reduce the performance impact of this change. - Simplified various types.
- Fix types for
removeEls
.
- Remove
onCommit
andonUpdate
. Instead, useonMount
for the same effect asonUpdate
.onCommit
has no new equivalent as there is no common use for it, thoughcreateRenderEffect
should always run beforeonMount
. - Added
readonly
toInitialIntegration
andMoveIntegration
els parameters, since the passed array should not be modified. This makes the interface less clean, but this is mostly preferable to cloning before passing. removeEls
onExitIntegration
now accepts an optional array of elements in addition to an optional single element.
- Redo scheduler again.
- Properly update the scheduler.
- Remove setTimeout inside removeEls.
- Use the scheduler when removing elements as well.
- Fix css integrations exiting before entering when they were exited within one frame, causing their event handlers to never trigger.
- Make transitions run asynchronously instead of within a computation, avoiding batching which may cause elements to not exit due to caching. This slightly changes how the scheduler works.
- Undo unnecessary fix in 0.7.7 (doesn't do anything).
- Fix initial case return value (returned undefined instead of the set of elements).
- Use computations instead of render effects to avoid batching, in order to hopefully fix elements rarely not exiting.
- Keep
TransitionGroup
uninitialized (i.e. delay running or not running initial) until at least one child exists to help with lazily loading children.
- Fix initial not being run with the scheduler.
- Fix checking removed elements against
currentTarget
instead oftarget
as intended.
- Simplify reverse enter implementation.
- Default keyframes now use computed styles instead of animating from/to
opacity: 1
, making them more compatible with default opacity other than 1, and when exiting halfway through the enter animation.
- Renamed
animateMove
'sgetKeyframes
tokeyframes
. - Removed
extraKeyframesList
as it is obsoleted by providing an array of keyframes with offsets. - Added the option to pass a callback to
keyframes
onanimateEnter
andanimateExit
.
- Helpers are now called integrations, inspired by
solid-app-router
. - Added scheduling to integrations to make it clearer what runs when.
animate
integrations now accept an object for animate parameters instead of taking two parameters for the keyframes and options. They can also accept a callback that animates the element.- Added
separate
as an option where applicable, separating removal of elements or classes per element instead of using the first element to remove all elements or classes. - Renamed
fixPosition
toabsolute
to make it clearer what it does. It also works on SVG elements now. - Renamed the
fixPositions
utility todetachEls
andfilterMoved
tofilterMovedEls
to make it clearer what they do. - Added
type
as an option on css integrations to prevent the wrong type of event from triggering the listener. - A custom event is now used to remove enter classes instead of hijacking the
animationend
listener. StylableElement
is nowElement & ElementCSSInlineStyle
instead ofElement
.- Allowed
initial
to be a callback, and allowed it to be provided viaenter
as well. - Added
reverseEnter
toanimateExit
, allowing enter animations to be reversed in causes where it looks cleaner to do so.
- Actually apply the fix in 0.6.1.
- Fixed playground link.
- Accidentally bumped the version number.
- Fixed a bug in
Transition
where removed children were not saved until they removed themselves. - Added prettier.
- Make
Transition
props reactive between transitions, fixing #2. MovedskipInitial
to a prop onTransition
,initial
, which specifies whether to enter the initial children.fixPosition
accepts onlytrue
now, since the default isfalse
and will remain so.
- Revert change in 0.5.6, as it had unintended side effects.
- Make
Transition
props reactive between transitions, fixing #2. Additionally swapped the project to spaces over tabs and double quotes over single quotes, following convention.
- Ignore
transitionend
andanimationend
events from elements other than the target element, fixing #1.
- Change default
fixPosition
to false as it is more often not used than used.
- Update dependencies
to
classes now remain on the element after entering/exiting, enabling some use cases. This should not break any existing cases as far as I am aware.
- Updated playground link
- Added support for
name
and css animations in css helpers, renamed the css helpers. Note that css animations are untested (because I'm unfamiliar with them), so feedback is appreciated
- Added better documentation
- Tried to get peerDependencies to work such that all versions of the solid playground would be compatible with the library, but couldn't do it. Will revisit.
- Fix firefox not applying enter styling on the first frame for whatever reason
- Replaced the
skipInitial
parameter inanimateEnter
with an options object; split thecssEnterExit
function into two,cssTransitionEnter
andcssTransitionExit
.
- Add a new helper,
cssEnterExit
that takes enter/exit class strings and returns an object containing theenter
andexit
props. See the playground link for an example.
- Apply the previous animation fix to all animations instead of just move where it is most apparent
- Fix animation jitteryness in firefox
- Fix opacity values (should not be inherit)
- Fix readme playground link
- A
Transition
component without props will no longer default to having all default transition handlers. Instead, they must now be created with theanimateEnter
,animateExit
, andanimateMove
functions, which implement the handlers using the web animations api. Calling them without parameters will use sensible defaults.
- Restore previous operation order to prevent items from sometimes jumping (will need to batch requestAnimationFrame to fix)
- Fix calling done multiple times in the default exit handler
- More optimizations
- Fix invalid keyframes in firefox
- Further optimizations, fixed an issue introduced in 0.2.6 that caused exiting elements to be incorrectly sized on exit
- Slight optimizations and preparations for further improvements
- Fix invalid keyframe values again
- Fixes the sizing of elements with percentage heights and/or margins after
defaultExit
- More optimizations, fix invalid keyframe values
- Slight optimizations and bug fixes
- Fix types
- Animation Handlers now take an array of elements instead of just one, so that multiple
requestAnimationFrame
calls do not need to be done, and to simplify some cases e.g. avoiding the entry animation for the initial render. - Split
lifecycle
intoenter
andexit
to avoid having an internal map of exit functions when it is not always needed. Managing the state of individual elements can be done externally when needed.