barbajs / barba

Create badass, fluid and smooth transitions between your website’s pages
https://barba.js.org/
MIT License
11.65k stars 473 forks source link

Proposal of a new code structure #117

Closed nicooprat closed 6 years ago

nicooprat commented 7 years ago

Continuing discussion from here: https://github.com/luruke/barba.js/issues/41

Here's an example of the code I'd like to be able to write: https://gist.github.com/nicooprat/ea184d51ba3c9ab131bf1d3400ef0ef0

Features

Actually all of this is already kinda doable with getTransition, but that could become very messy with a complex website. I think it should be done by the library by default (and only leave to the developer the possibility to overwrite/hook it maybe). I'd prefer a "config over code" behavior here. I tried to achieve this kind of behavior with v1, but the library is not structured for it, so it's really difficult. Here's what I think would be better:

Structure

So internally, Barba would do the following when a link is clicked (speaking of transitions, the rest of the library works fine), pretty similar to the fade transition in the docs does:

  1. Fire the current route out transition (with parameters: next route & a promise to be resolved (getting rid of this.done()) and loads the new URL contents
  2. When those 2 promises are resolved, fire the new route in transition (again with route & promise parameters)
  3. Trigger according events in each step
luruke commented 7 years ago

Thank you @nicooprat .

Basically with your proposal, there will be no more separation between a View and a Transition, everything will be incapsulated in this new object Route.

Also you introduce this new concept of in and out, while, currently the transitions are designed as "one way".

I actually like the separations of concern between the Views and the Transition, it makes the Transition:

Chaining the out transition and the in transition of two routes can work fine for simple transitions but it may sounds complicate for more advanced ones.

Even if the path it's optional, it assume a certain importance in the new structure, and it's something that can be hardly hardcoded in a CMS driven website.

Also the naming routes it may sounds a bit confusing for some users, since barba doesn't provide any real front-end routing, but keep all the routing duty to the server.

Routes can have methods like before(un)Loaded, after(un)Loaded, and so on, to trigger code (like creating a slider when coming on a page), getting rid of "global" Barba's events listeners

This is already possible with .onEnter, .onEnterCompleted, .onLeave, .onLeaveCompleted on the View, or you are thinking to something different?

In general I need some time to process and think about it, I'd also like some other opinion from someone else.

nicooprat commented 7 years ago

Basically with your proposal, there will be no more separation between a View and a Transition, everything will be incapsulated in this new object Route.

I agree that, in this case, reusing a transition would be difficult. In your experience, does it really happen often? I was thinking of a default in/out transition for all routes, and the possibility to specify for some.

We could either make routes extendable, or still have views/transitions appart, but it seemed simpler to me to merge these concepts.

Chaining the out transition and the in transition of two routes can work fine for simple transitions but it may sounds complicate for more advanced ones.

Could you elaborate on this? Do you mean that sometimes the two transitions merge, without having a "neutral" moment between them? In my proposal, the developer can resolve the promise whenever he/she needs, so there could be other effects even after the next route begins its own transition (are you following me? :D).

Even if the path it's optional, it assume a certain importance in the new structure, and it's something that can be hardly hardcoded in a CMS driven website.

Not really important, only a bonus I'd say. In my tests, I wanted a special transition when going to a specific page, and there's no "official" way to do that at the moment with Barba. We need to wait the new content to be loaded to get the new namespace from the API. So we've to either check the href from the clicked link (via a global var), or add something clearer like a data-attr to explicitly specify it. That's not really handy. This path property could help Barba guess the next route before having loaded it, at least for simple URLs (that's the case 90% of the time).

Also the naming routes it may sounds a bit confusing for some users, since barba doesn't provide any real front-end routing, but keep all the routing duty to the server.

Naming things are still the hardest :) I agree that the confusion that Barba is a "real" router could be made (well, it's not that far though, it's like a progressive router), but views are often referring to the native world... And one could also suppose you can have multiple views in a page. Speaking of this, that could be another feature request :)

This is already possible with .onEnter, .onEnterCompleted, .onLeave, .onLeaveCompleted on the View, or you are thinking to something different?

That's it, just wanted to note that it would be defined in route-level in my proposal.

In general I need some time to process and think about it, I'd also like some other opinion from someone else.

Wise words! Need more feedbacks :)

samburgers commented 7 years ago

not sure if i'm adding much to the discussion... but i've found that i can use essentially a single transition function (a modified version of the fade transition in the docs), and then manage all the different page transitions in the css. this has the additional upside of leveraging css for performant animations, and complexity within animations without any additional js.

let CommonTransition = Barba.BaseTransition.extend({

  start: function() {
    Promise
      .all([this.newContainerLoading, this.pageExit()])
      .then(this.pageEnter.bind(this));
  },

  pageExit: function() {
    return $(this.oldContainer).addClass('is-exiting').delay(300).promise();
  },

  pageEnter: function() {
    this.done();
    $(this.newContainer).addClass('is-entering').delay(300).queue(function(){
      $(this).removeClass('is-entering').dequeue();
    });
  },
});

Barba.Pjax.getTransition = function() {
  return CommonTransition;
};
magicspon commented 6 years ago

@nicooprat @luruke

Evening all...

I've managed to knock together some kinda of 'router' type thinger...

The route array:

export default [
    {
        path: '/',
        view: Home
    },
    {
        path: '/case-studies',
        view: CaseStudy,
        children: [
            {
                path: 'ted',
                view: CaseStudyTed
            },
            {
                path: 'helen',
                view: CaseStudyHelen,
                children: {
                    path: ':id',
                    view: Post
                }
            }
        ]
    },
    {
        path: '/blog',
        view: Blog,
        children: {
            path: ':id',
            view: Post
        }
    },
    {
        path: '*',
        view: Fallback
    }
]

Example view/transition thing:

export const Home = {
    onEnter({ from, to, next }) {
        document.body.style.backgroundColor = '#5ea'
        next()
    },

    onLeave({ from, to, next }) {
        next()
    }
}

example here: sponjs.surge.sh

I've not tested the crap out of this yet, but it seems to be working pretty well https://github.com/magicspon/spon/blob/master/src/js/core/Router.js

Keen to hear your thoughts...

(note, this is very much still in development!)

ta

nicooprat commented 6 years ago

@magicspon It's basically all I dreamt of! Very nice. Looks like for now it's written directly in your project though, do you plan to make it standalone? I'd like to give it a try :) I'm just about to work on a project to would need it actually!

magicspon commented 6 years ago

@nicooprat Evening...

Here is the router thinger without any of my framework crap in there.

https://github.com/magicspon/barba-router

clone the repo, npm install, npm start

Let me know how you get on?