Coder Social home page Coder Social logo

solidjs-community / solid-transition-group Goto Github PK

View Code? Open in Web Editor NEW
229.0 6.0 13.0 745 KB

SolidJS components for applying animations when children elements enter or leave the DOM.

Home Page: https://solid-transition-group.netlify.app

License: MIT License

TypeScript 90.89% CSS 5.38% Astro 3.08% JavaScript 0.65%
animation css solidjs transition

solid-transition-group's Introduction

Solid Transition Group

Solid Transition Group

pnpm version downloads

Components for applying animations when children elements enter or leave the DOM. Influenced by React Transition Group and Vue Transitions for the SolidJS library.

Installation

npm install solid-transition-group
# or
yarn add solid-transition-group
# or
pnpm add solid-transition-group

Transition

<Transition> serve as transition effects for single element/component. The <Transition> only applies the transition behavior to the wrapped content inside; it doesn't render an extra DOM element, or show up in the inspected component hierarchy.

All props besides children are optional.

Using with CSS

Usage with CSS is straightforward. Just add the name prop and the CSS classes will be automatically generated for you. The name prop is used as a prefix for the generated CSS classes. For example, if you use name="slide-fade", the generated CSS classes will be .slide-fade-enter, .slide-fade-enter-active, etc.

The exitting element will be removed from the DOM when the first transition ends. You can override this behavior by providing a done callback to the onExit prop.

import { Transition } from "solid-transition-group"

const [isVisible, setVisible] = createSignal(true)

<Transition name="slide-fade">
  <Show when={isVisible()}>
    <div>Hello</div>
  </Show>
</Transition>

setVisible(false) // triggers exit transition

Example CSS transition:

.slide-fade-enter-active,
.slide-fade-exit-active {
  transition: opacity 0.3s, transform 0.3s;
}
.slide-fade-enter,
.slide-fade-exit-to {
  transform: translateX(10px);
  opacity: 0;
}
.slide-fade-enter {
  transform: translateX(-10px);
}

Props for customizing the CSS classes applied by <Transition>:

Name Description
name Used to automatically generate transition CSS class names. e.g. name: 'fade' will auto expand to .fade-enter, .fade-enter-active, etc. Defaults to "s".
enterClass CSS class applied to the entering element at the start of the enter transition, and removed the frame after. Defaults to "s-enter".
enterToClass CSS class applied to the entering element after the enter transition starts. Defaults to "s-enter-to".
enterActiveClass CSS class applied to the entering element for the entire duration of the enter transition. Defaults to "s-enter-active".
exitClass CSS class applied to the exiting element at the start of the exit transition, and removed the frame after. Defaults to "s-exit".
exitToClass CSS class applied to the exiting element after the exit transition starts. Defaults to "s-exit-to".
exitActiveClass CSS class applied to the exiting element for the entire duration of the exit transition. Defaults to "s-exit-active".

Using with JavaScript

You can also use JavaScript to animate the transition. The <Transition> component provides several events that you can use to hook into the transition lifecycle. The onEnter and onExit events are called when the transition starts, and the onBeforeEnter and onBeforeExit events are called before the transition starts. The onAfterEnter and onAfterExit events are called after the transition ends.

<Transition
  onEnter={(el, done) => {
    const a = el.animate([{ opacity: 0 }, { opacity: 1 }], {
      duration: 600
    });
    a.finished.then(done);
  }}
  onExit={(el, done) => {
    const a = el.animate([{ opacity: 1 }, { opacity: 0 }], {
      duration: 600
    });
    a.finished.then(done);
  }}
>
  {show() && <div>Hello</div>}
</Transition>

Events proved by <Transition> for animating elements with JavaScript:

Name Parameters Description
onBeforeEnter element: Element Function called before the enter transition starts. The element is not yet rendered.
onEnter element: Element, done: () => void Function called when the enter transition starts. The element is rendered to the DOM. Call done to end the transition - removes the enter classes, and calls onAfterEnter. If the parameter for done is not provided, it will be called on transitionend or animationend.
onAfterEnter element: Element Function called after the enter transition ends. The element is removed from the DOM.
onBeforeExit element: Element Function called before the exit transition starts. The element is still rendered, exit classes are not yet applied.
onExit element: Element, done: () => void Function called when the exit transition starts, after the exit classes are applied (enterToClass and exitActiveClass). The element is still rendered. Call done to end the transition - removes exit classes, calls onAfterExit and removes the element from the DOM. If the parameter for done is not provided, it will be called on transitionend or animationend.
onAfterExit element: Element Function called after the exit transition ends. The element is removed from the DOM.

Changing Transition Mode

By default, <Transition> will apply the transition effect to both entering and exiting elements simultaneously. You can change this behavior by setting the mode prop to "outin" or "inout". The "outin" mode will wait for the exiting element to finish before applying the transition to the entering element. The "inout" mode will wait for the entering element to finish before applying the transition to the exiting element.

By default the transition won't be applied on initial render. You can change this behavior by setting the appear prop to true.

Warning: When using appear with SSR, the initial transition will be applied on the client-side, which might cause a flash of unstyled content. You need to handle applying the initial transition on the server-side yourself.

TransitionGroup

Props

  • moveClass - CSS class applied to the moving elements for the entire duration of the move transition. Defaults to "s-move".
  • exposes the same props as <Transition> except mode.

Usage

<TransitionGroup> serve as transition effects for multiple elements/components.

<TransitionGroup> supports moving transitions via CSS transform. When a child's position on screen has changed after an update, it will get applied a moving CSS class (auto generated from the name attribute or configured with the move-class attribute). If the CSS transform property is "transition-able" when the moving class is applied, the element will be smoothly animated to its destination using the FLIP technique.

<ul>
  <TransitionGroup name="slide">
    <For each={state.items}>{item => <li>{item.text}</li>}</For>
  </TransitionGroup>
</ul>

Demo

Kitchen sink demo: https://solid-transition-group.netlify.app/

Source code: https://github.com/solidjs-community/solid-transition-group/blob/main/dev/src/pages/kitchen-sink.tsx

FAQ

solid-transition-group's People

Contributors

davedbase avatar davidskuza avatar k4rakara avatar kirpalmakanga avatar marvin-j97 avatar mfrozenm avatar otonashixav avatar ryansolid avatar thetarnav avatar xstevenyung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

solid-transition-group's Issues

Invalid type of children property

Given the following code...

<Transition><div/></Transition>

...the TS compiler inside VSCode complains:

Type 'Element' is not assignable to type '(Element & (string | number | boolean | Node | ArrayElement | FunctionElement | null)) | undefined'.
  Type 'null' is not assignable to type '(Element & (string | number | boolean | Node | ArrayElement | FunctionElement | null)) | undefined'.ts(2322)
Transition.d.ts(16, 5): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & TransitionProps & { children?: Element; }'

Looking at the Transition.d.ts I found it accepting an Element rather than JSX.Element. Is this correct? When I change the TransitionProps as follows the error goes away:

-    children?: Element;
+    children?: JSX.Element;

Transition not working in tests

Hi!

I ran into an issue where I tried to write tests for a component that uses the <Transition> component, but it doesn't seem like it works in tests (using Vitest with solid-testing-library).

I also reproduced it in Stackblitz here: https://stackblitz.com/edit/vitest-dev-vitest-fhrobg?file=test/Hello.test.jsx (see the Hello.jsx component and its tests). The tests can be run with npm run test. Removing the wrapping Transition component seems to make the tests pass.

From my brief debugging, it seems like the createComputed watcher here: https://github.com/solidjs/solid-transition-group/blob/main/src/Transition.ts#L119 does not get triggered after clicking the button in tests (but it does seem to be triggered in the browser). I tried to reproduce that with the Children component, but it does seem to work there, so I'm not really sure what to do next.

Is it possible that there's some issue with this in the Node environment? Also, maybe an example somewhere of how to write a test for a component that uses Transition would be nice?

is this maintained?

just curious, It has no commits for 5 months and have no notice about maintain status

How to work with `<Dynamic>`

I use Dynamic in Transition, but transition not work.

<Transition name="slide-fade" mode="inout">
  <Dynamic component={ () => ... />}
</Transition>

Simultaneously transitioning mismatching current element and previously

Hi there,

I have the following code (with Routes being two routes from useRoutes, nothing special just a div and p):

export function UI(props) {
  const Routes   = props.routes, 
        duration = (el) => parseFloat(
          window.getComputedStyle(el).animationDuration
        ) * 1000

  return (
    <Router url={props.url} out={{}}>
      <Transition 
        onEnter={(el, done) => {
          setTimeout(() => console.log('DONE'), duration(el) || duration(document.body));
          console.log('go');
        }}
        onExit={(el, done)  => setTimeout(done, duration(el) || duration(document.body)) }
        >
        <Routes/>
      </Transition>
    </Router>
  );
}

When toggling the routes sometimes it works, sometimes prev and el are wrong in this function:
File: solid-transition-group.js

createComputed(prev => {
  el = resolved();

  while (typeof el === "function") el = el();

  return untrack(() => {
    if (el && el !== prev) {
      if (props.mode !== "outin") enterTransition(el, prev);else if (first) set1(el);
    }

    if (prev && prev !== el && props.mode !== "inout") exitTransition(el, prev);
    first = false;
    return el;
  });
});

In this case exitTransition() is called in the same function call, so enterTransition() and exitTransition() is called with the same parameters, so the "target" of the transition is the same element for enter and exit.

Leading to this in the DOM:
image

Then right after that the elements are swapped immediately with no transition whatsoever. 'go' is printed to the console. Then after 5 seconds 'DONE', but this had no effect.

The problem is, it seems like the first case works moving from '/a' to '/b' but then never again.
I have no ideas so far. Does anyone has an idea?

Caveat: When using mode: 'outin' it will work.

TransitionGroup animates keyed shows before Suspense-Transition is done

Is: Currently if a keyed <Show> is used inside of a <TransitionGroup>, and the Show value is suspense-transitioned with startTransition, the exit and enter animations will already run with old state before the Suspense-Transition is even done.

Should: Ideally the animations should only run after the Suspense-Transition.

Video:

Bildschirmaufzeichnung.vom.2023-07-13.19-18-20.mp4

Playground: https://stackblitz.com/edit/github-324i4c-ubu1bo?file=src%2FApp.tsx

Versions:
"solid-js": "^1.7.8",
"solid-transition-group": "0.2.2"

feature request: better documentation

Thank you for creating this library! I have used it many times and it's really nice.
That being said I think the documentation could use a bit of work. I still don't understand the order of classNames applied and when to use which. I usually stick to onEnter/ onExit... methods, but it's also unclear what "done" method does. When I get it working, it takes a ton of trial and error

Based on my experience when "done' is called in the onExit phase, that's when the exiting element is actually removed, unless "done" from the onEnter phase called first (race condition of animations), then "done" from onEnter phase is what removes exiting element

It would be nice if the lib had some JSDOC comments for ease of reference.
In fact, I think most of solid libraries could use JSDOC and I think there even might be a way to generate frontend documentation from JSDOC comments to keep then in sync

Element flashes before animation starts running.

Before animation runs, content appears unstyled for a brief moment.

const onEnter = (element: Element, done: () => void) => {
   // At this point element shouldn't be visible but it is.
   element.animate({
      opacity: [0, 1],
    }, {
      duration: 100,
    }).finished.then(done)
}

Reproducible example some other person made:
https://codesandbox.io/s/cool-bogdan-j8b37?file=/package.json

One possible fix is to use 'onBeforeEnter' event but that only complicates things, especially with complex animations.
An actual fix would be to replace all 'setTimeout' uses with 'queueMicrotask', for example here:
https://github.com/ryansolid/solid-transition-group/blob/0f1d5253531246e51ea549adf8a002c7020ec5ad/src/Transition.ts#L63-L71
I have briefly tested it working locally with both native function and polyfill https://github.com/feross/queue-microtask

Loss of styles on exit transition when used with @suid

When this library is being used together with https://suid.io/, all material styles are lost on exit transition, because the <style> element in the <head> gets removed when the exit transition starts. Seems like SUID is cleaning house when it thinks the styled element is no longer in the dom (while it still is because of the ongoing transition).

Here's an example snippet. The described behavior happens when removing a message, which triggers the exit animation:

    <TransitionGroup name="slide-fade">
      <For each={messages()}>
        {(message) =>
          <Paper onClick={() => messageClicked(message)}>
            <Typography>{message.text}</Typography>
          </Paper>
        }
      </For>
    </TransitionGroup>

Clarification on show()

I am having a difficult time understanding exactly what this show() is and there seems to be a lack of proper documentation on it. I have search and found nothing.

Trying to use some of the examples provided just yields an error:
Could not find name show

Would someone be able to clarify this?

`ReferenceError: Element is not defined`: SSR breaks when using `solid-transition-group` on cloudflare workers

Here's the reproduction url:

https://github.com/Odas0R/solid-group-transition-bug

Everything you need to do is on the URL to throw the error. I'm using wrangler cli which emulates a worker environment. Code also breaks in production.

This is the code that breaks:

import { createSignal } from "solid-js"
import { Transition } from "solid-transition-group"

export const SolidTransition = () => {
  const [isOpen, setOpen] = createSignal(false)

  return (
    <div>
      <Transition>{isOpen() && <div>hello</div>}</Transition>
    </div>
  )
}

On the astro page:

---
import Layout from '../../layouts/Layout.astro';
import { SolidTransition } from '../../components/SolidTransition.tsx';

export const prerender = false;
---

<Layout title="Welcome to Astro.">
	<main>
		<h1>SSR</h1>
		<SolidTransition client:load />
	</main>
</Layout>

The error:

[mf:wrn] Service bindings are experimental. There may be breaking changes in the future.
[mf:inf] Worker reloaded! (171.47KiB)
[mf:inf] Listening on 0.0.0.0:3000
[mf:inf] - http://127.0.0.1:3000
[mf:inf] - http://192.168.31.106:3000
[mf:inf] - http://172.17.0.1:3000
[mf:inf] Updated `Request.cf` object cache!
GET /preview/lol 404 Not Found (6.99ms)
[mf:err] GET /ssr: ReferenceError: Element is not defined
    at Ui (/tmp/astro-test/wow/dist/_worker.js:60:23785)
    at tn (/tmp/astro-test/wow/dist/_worker.js:60:23813)
    at Object.fn (/tmp/astro-test/wow/dist/_worker.js:60:24004)
    at Bi (/tmp/astro-test/wow/dist/_worker.js:60:19150)
    at Te (/tmp/astro-test/wow/dist/_worker.js:60:18936)
    at Z (/tmp/astro-test/wow/dist/_worker.js:60:17075)
    at qi (/tmp/astro-test/wow/dist/_worker.js:60:23998)
    at Wi (/tmp/astro-test/wow/dist/_worker.js:60:25730)
    at an (/tmp/astro-test/wow/dist/_worker.js:60:26836)
    at ra (/tmp/astro-test/wow/dist/_worker.js:71:164)
GET /ssr 200 OK (173.41ms)
GET /_astro/index.12c5fa68.css 304 Not Modified (5.66ms)

Transition not working

hi this is my democode
https://github.com/kulame/solid-demo/blob/master/src/Search.tsx

<Transition
        enterClass="transition ease-in-out duration-1000"
        exitToClass="opacity-100 translate-y-0"
      >
        <Show when={modalOpen()} fallback={<></>}>
   </Show>
</Transition>

Why doesn't the window still not disappear after I clicked outside ?

In addition, the animation effect of Transition never appears after I click. Is it because I am using it incorrectly?

Animation examples don't seem to work on the solid JS website

Hopefully I haven't missed something obvious. If so, I apologize in advance. The css animations example on the Solid JS website don't seem to work. It looks like maybe the solid-transition-group library isn't accessible:
https://www.solidjs.com/examples/cssanimations

I love the idea of the library so I tried to get it working in a code sandbox but the description that it functions much like the FLIP technique isn't something I'm able to accomplish:
https://codesandbox.io/s/lucid-nobel-6hy9kb?file=/src/main.tsx:230-242

If there's an obvious step being missed here it might be nice to mention it in the docs. Thanks in advance for your time!

How to use with <Outlet />

Hi, I have a common layout and subrouters show in <Outlet />. It worked fine, but I wanted to add some slide animation when I route between pages. So I surround it with <Transition>, it became broken. I didn't find any animation effects. Besides, if I click the go back button on Chrome, both routers' content showed at the same time.

jsx:

<Transition name="slide" appear={true}>
  <Outlet />
</Transition>

css:

.slide-leave-active,
.slide-enter-active {
  transition: all 1s ease;
}
.slide-enter-from {
  transform: translateX(100%);
}
.slide-leave-to {
  transform: translateX(-100%);
}

Sorry to ask this dumb question. But can you show me a simple example about this?

The return type of the <Transition> element doesn't appear to be valid JSX

src/Schematic/Schematic.tsx(143,10): error TS2786: 'Transition' cannot be used as a JSX component. 
    Its return type '(() => unknown)[]' is not a valid JSX element. 
        Type '(() => unknown)[]' is not assignable to type 'ArrayElement'.

It looks like ArrayElement doesn't allow FunctionElement children in solid-js/types/rendering/jsx.d.ts. Does it seem reasonable to add that?

`transform-origin` takes no effect for exit classes

I've added transform-origin: bottom center to all classes of exitXXXClass, but it has no effect.

However, If I add the style to the static class of the element or to the enterActiveClass, it has effect.

String classes props ignored

Since the PR #18, the string classes enterActiveClass, enterClass, etc. passed as props are now ignored.

These classes are instead always computed from the name props:
https://github.com/solidjs/solid-transition-group/blob/main/src/Transition.ts#L40

Which makes it impossible to use code like this (with TailwindCSS):

<Transition
  enterActiveClass="transition duration-200"
  enterClass="opacity-0"
  enterToClass="opacity-100"
>
    ...
</Transition>

Whereas the documentation/readme says it's supported, as it should.

Using @solidjs/router lazy components with mode="outin"

Then I try to add transition mode="outin" to lazy-loaded components in @solidjs/router I get an error.

Outlet:

<Transition mode="outin">
  <Outlet />
</Transition>

Lazy-loaded components:

lazy(async () => import('./example/path'));

Error then trying to navigate:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'classList')
    at enterTransition (solid-transition-group.js:41:10)
    at endTransition (solid-transition-group.js:100:37)
    at solid-transition-group.js:85:34

Passing a class to the adhoc container element

Hello, is it possible that we could just pass a static, non-transition related class to the container element which gets to contain the children passed to Transition component and rendered as a parent element?

onMount called before elements are connected in outin mode

I have a 3rd party component that relies on a document.getElementById call to find a DOM node in my components onMount function.

Works great with the normal transition, until I switch to an outIn transition, then my components onMount fires, but the DOM node doesn't exist yet, so the 3rd party component blows up.

I don't know exactly how it would look, but it would be great if there was a way to detect if the onMount was actually mounted and the DOM was ready, or if the component is floating around outside of the DOM in the transitions pretend onMount.

Basic issue: trying the first example

Hi, I'm trying to use solid-transition-group lib to manage the state of a component, because it's a difficult task for me.

I give it a shot with the first example from the README, but I cannot toggle the show/hide of my component. You can find my reproducible example there:
https://stackblitz.com/github/frozar/solid-transition-group-issue?file=src%2FApp.tsx

And the repository of this example:
https://github.com/frozar/solid-transition-group-issue

What am I doing wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.