Coder Social home page Coder Social logo

Comments (10)

far-fetched avatar far-fetched commented on May 25, 2024

Super glad to see this. I already started scouring react / vue code.
How to you prefer implement 'wait' mechanism for end of transition ? Basing of events or like in react repo with setTimeout - they already left comment that it can be improved. I was wondering about general idea...

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

This is a work-in-progress and I'm not ready to make a PR yet, but I took the general idea of the React/Vue implementation and adapted it for use with Ember

https://github.com/alexlafroscia/ember-headlessui/blob/82addef1b9235b023b715bb3628ce2aa5e6338a8/addon/utils/transition.js#L4-L34

The idea is the same; read the transition duration and delay and resolve a promise after that much time has passed. They have a lot of stuff in the React implementation, at least (since that's what I have been using as my frame of reference; I'm better at reading React code that Vue code) around disposables that are not relevant for the Ember implementation, as Ember Concurrency tasks will be used to handle all the asynchrony and they will handle cancellation for us out-of-the-box.

This utility got it's own tests, so I feel pretty confident that it works correctly

https://github.com/alexlafroscia/ember-headlessui/blob/82addef1b9235b023b715bb3628ce2aa5e6338a8/tests/unit/utils/transition-test.js#L42-L133

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

What's tricky for me right now, which I'm working out how I want to approach, is the difference between the @show argument and some internal concept of "the component should be mounted right now". It's not exactly 1:1 -- if you transition from false to true then the component should become mounted. If you transition from true to false, though, you should actually do the following:

  1. Apply the leave-from classes
  2. Wait for the transition duration
  3. Apply the leave-to classes
  4. Then actually unmount the component

So there's a whole process that needs to happen as a side-effect of a property changing, which is not really something that Ember has a great API around these days. We can use the did-update modifier but it's kind of awkward in this case. We also run into a problem when using did-update, where you don't have an element to bind the did-update modifier to when the component is unmounted, because there's nothing being rendered!

A Resource is probably the right abstraction here, but that would require another external dependency on ember-could-get-used-to-this. I know @achambers would prefer we avoid dependencies, and I am not a fan of depending on a package like that which is speculating on the API that may or may not someday become mainstream. (P.S. Please don't take that as a shot at you @achambers -- avoiding dependencies is a good practice to follow and I agree we should try to adhere to it! It's unfortunate that the Observer API is no longer recommended without a good replacement being part of the public API).

I'm currently iterating on different concepts of what might work here, since there's some subtlety around getting the sequence of events correct!

from ember-headlessui.

far-fetched avatar far-fetched commented on May 25, 2024
1. Apply the `leave-from` classes

2. Wait for the transition duration

3. Apply the `leave-to` classes

4. _Then_ actually unmount the component

Are you sure that is correct ? I was thinking rather:

  1. apply leave and leave-from
  2. apply leave-to, remove leave-from
  3. now wait for transition duration
  4. unmount component

Am I missing something ? 🤔

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

I might have written it out wrong here, but I think the implementation is correct

This Ember Concurrency task here

https://github.com/alexlafroscia/ember-headlessui/blob/82addef1b9235b023b715bb3628ce2aa5e6338a8/addon/components/transition.js#L63-L78

maps to the React utility function here

https://github.com/tailwindlabs/headlessui/blob/b961a189d57fa24af2a0bd0a6d73fa44e1d34529/packages/%40headlessui-react/src/components/transitions/utils/transition.ts#L58-L95

And I call it with the appropriate sets of classes based whether we're transition to/from being shown

https://github.com/alexlafroscia/ember-headlessui/blob/82addef1b9235b023b715bb3628ce2aa5e6338a8/addon/components/transition.js#L80-L111

from ember-headlessui.

achambers avatar achambers commented on May 25, 2024

Oh, this discussion excites me. Thanks for taking this on @alexlafroscia .

Don't worry Alex, not shots fired here ;) It's just a general preference I think it'd be useful to have in this repo but it's by no means cut and dry and we should be pragmatic about each situation. I have full confidence that if you think there is a a good reason to introduce something then it's the right thing to do.

ember-could-get-used-to-this certainly is a funny one where that's concerned though I suppose due to it's experimental nature. 🤷‍♀️

One question that came to mind when reading through this thread is - is there any inspiration we can take from https://github.com/peec/ember-css-transitions around how we do some of this stuff?

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

That's interesting @achambers! I've never seen that repo before; it looks really similar to the nature of the Transition component!

I have Transition like... 60% implemented at this point on my branch. All of the tests are passing for the Transition component itself; I just need to push through the Transition::Child tests as well, but I think that should be pretty easy.

For now, the implementation depends on a Resource from ember-could-get-used-to-this; I needed some way to "listen" for updated to this.args.show without using the did-update modifier (since we always need to respond to changes to the property but the DOM node rendered by Transition is not always actually mounted). The usage looks like this

https://github.com/alexlafroscia/ember-headlessui/blob/e3f8be46b2caa973b811687963ddd8d67f87c4fc/addon/components/transition.js#L31-L34

The resource itself then manages the little state machine to get the component mounting correct

https://github.com/alexlafroscia/ember-headlessui/blob/e3f8be46b2caa973b811687963ddd8d67f87c4fc/addon/resources/transition.js

The logic is basically

  • If this.args.show is transitioning false -> true
    • Immediately mount the component
  • If this.args.show is transitioning true -> false
    • Wait for the transition duration/delay to pass
    • Then un-mount the component

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

Whew! After a morning of refactoring, I was able to remove the dependency on ember-could-get-used-to-this. We still depend on tracked-maps-and-sets, but it's small, tree-shakeable and intended to be a low-level primitive. I'm feeling better about my approach now that I don't need to introduce that dependency!

The key was to turn each Resource into a Helper instead, which is called using invokeHelper. This is all public API as of Ember 3.25, which is the minimum version for this addon anyway 💯

from ember-headlessui.

far-fetched avatar far-fetched commented on May 25, 2024

That's huge! Actually, I was concern about the fact that we use the concept of '@resource' for that. I felt that main intention of it was rather loading data ? (Correct me if I am wrong). Invoke helper it is more primitive and seems like a more adequate solution in our case, so well done. Can't wait to see it in action 🍰

from ember-headlessui.

alexlafroscia avatar alexlafroscia commented on May 25, 2024

I felt that main intention of it was rather loading data ?

My take is that, rather than the intention being “data loading”, it’s more about things that produce a value with a distinct lifecycle. Data loading is a specific example of that; there are some inputs that might change, a request to perform that introduces a loading state, error handling, success handling… Resources can be a way to model that.

The class string for the Transition component is also a value with a distinct lifecycle, though; we need to apply certain classes when entering, then change them after a timeout. Same with leaving; different classes, but also dependent on component state and time. From this perspective, I don’t know that a Resource is the wrong abstraction, but the reality is that we can also use a Helper to do this (even if it’s more awkward) and I don’t like the idea of committing to use of an API that hasn’t really solidified yet.

from ember-headlessui.

Related Issues (20)

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.