Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: matching rules by name #66

Open
4 tasks done
lubomirblazekcz opened this issue Dec 6, 2023 · 21 comments
Open
4 tasks done

[Feature Request]: matching rules by name #66

lubomirblazekcz opened this issue Dec 6, 2023 · 21 comments

Comments

@lubomirblazekcz
Copy link

lubomirblazekcz commented Dec 6, 2023

Describe the problem 🧐

Currently it's possible to define rules only by path, I think this is kind of tricky for lang mutations or url can be changed via cms etc.

Describe the propsed solution 😎

Definition by data attributes to match name of the rule, eg. data-swup-route-name="my-route" for routes, or data-swup-fragment-name="my-fragment-rule" for fragments

Alternatives considered 🤔

I am already using this via link:click hook for the RouteNamePlugin, but I don't think it's possible to do similiar to fragments, or am I wrong?

    if (event.target.dataset.swupRoute) {
        visit.to.route = event.target.dataset.swupRoute
    }

How important is this feature to you? 🧭

Nice to have

Checked all these? 📚

@daun
Copy link
Member

daun commented Dec 6, 2023

Right, that can get tricky. In current projects, I'm handling this by sharing those routes between the backend and frontend. Note that this is just the final output as they're actually auto-generated from the current slugs of pages as defined in the backend.

<script>
    window.__routes__ = {
      'home': ['/de', '/en', '/fr'],
      'project-list': ['de/projects', 'en/projects', 'fr/projects'],
      'project': ['de/project/:slug', 'en/project/:slug', 'fr/project/:slug']
    };
</script>

Your solution should work for the route name plugin, yes, but indeed the fragment plugin currently requires actual route definitions to work properly. There was a discussion about other ways of selecting fragment rules, but routes came out on top 🤠

@daun
Copy link
Member

daun commented Dec 6, 2023

@hirasso Do you remember the actual reasoning behind going for routes-only for the fragments instead of dom attributes? I remember our first trials were with dom attributes but I don't remember where exactly that approach broke down...

@lubomirblazekcz
Copy link
Author

@daun yeah your solution came in mind too, but I found the data-swup-route attribute much easier to use for my use case (I am using it to append skeleton animations before loading the new page).

I figured that fragments would be trickier, but current solution adds a lot overhead to configuring if the route name is dynamic.

My idea was that upon navigation with data-swup-fragment-name="my-fragment-rule" or similiar swup detects if that fragment with that rule name is on the page, and if so it would apply it on the rule containers.

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

Yes, at first we tried to use dom attributes - similar to what hotwire/turbo is doing with frames. But that proved to be problematic for history and programmatic navigation using swup.navigate(). During these visits, it's unclear what fragment rules should be applied, as the visit wouldn't be triggered by a link (or form).

@lubomirblazekcz
Copy link
Author

I see. Can the fragment name be saved into state object in history? And programmatic navigation would have to be necessary manually as an option to work. I think the best solution would be have both approaches possible, and it would depend on the situation what would be more suitable to use.

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

We are very open to contributions and additional brain power to improve fragment plugin! I'm personally a bit limited in resources these days, but would happily review and test-drive a PR for this feature @lubomirblazekcz .

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

I'm starting to remember more problems with the attribute-based approach. If you go to the fragment plugin demo site, then execute the following navigation:

  1. Navigate to "Characters":

CleanShot 2023-12-06 at 14 05 21@2x

  1. click on one of the filters, for example "Princesses":

CleanShot 2023-12-06 at 14 05 58@2x

  1. click on one of the characters, for example "Princess Daisy":

CleanShot 2023-12-06 at 14 07 01@2x

  1. On the overlay, there are links back to the filters:

CleanShot 2023-12-06 at 14 01 16@2x

  • If you click on "Princesses", only the overlay will be replaced, since the overlayed list already displays the princesses
  • If you click on any of the other filter links, both the overlay and the list will be replaced.

Something like this would be impossible to control using attributes, as on the server there is no way of knowing in what context the overlay would be rendered.

@lubomirblazekcz
Copy link
Author

lubomirblazekcz commented Dec 6, 2023

@hirasso right now I am limited too, but once I have more time I could take a look at this and do a PR. 👍

Regarding your example, I think it could be possible - I would add an attribute to links in filter with a close-character name (only if the filers are in modal, otherwise it would be characters-list), that would match the correct rule and replace the containers. But that's my simplified version, I might be missing something.

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

Actually, that sounds very interesting! Looking forward to what you come up with!

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

Another thing to keep in mind would be multiple history steps at once. You know, when you right-click on the browser's back button and jump multiple visits back in history.

@daun
Copy link
Member

daun commented Dec 6, 2023

@hirasso Right, I remember now. That was our nemesis -- history visits which skip intermediate history entries.

@lubomirblazekcz Swup (and fragment plugin) by default start the out animation while the new page is still loading, mainly for perceived performance. Awaiting the new page html to determine the type of visit should work, but at the cost of user experience. Unless such a feature was optional, of course.

Looking forward to what you come up with! Let us know if you need a helping hand along the way.

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

Actually, I never thought of the idea to define rules with names beforehand, and then reference these rules in dom attributes. Combined with a mechanism to store the matched rule (if any) in the history state this all sounds quite promising to me.

@lubomirblazekcz
Copy link
Author

lubomirblazekcz commented Dec 6, 2023

@daun I don't think it's needed to wait for new page load, you know beforehand which rules to apply and which containers to replace from the name in the attribute

@hirasso yeah that's the idea

@daun
Copy link
Member

daun commented Dec 6, 2023

@lubomirblazekcz Even better then. Looks like I misread one of your previous comments to that effect.

@daun
Copy link
Member

daun commented Dec 6, 2023

@lubomirblazekcz Just making sure — could the first of your scenarious be covered by swup's built-in animation attribute? Adding data-swup-animation to a link will add a class name to the html element with that value. You can use that to act as a route name:

<a href="/" data-swup-animation="my-route">

Will produce these classnames during the animation:

<html class="is-changing is-animating to-my-route">

@hirasso
Copy link
Member

hirasso commented Dec 6, 2023

One more consideration why we went with routes for fragment rules: on larger websites you might not always be fully in control of your link's markup (think content from WYSIWYG editors, for example). With attributes, there could be considerable overhead be involved in making sure every last link has the necessary attributes. Not unsolvable of course, but a bit tricky.

@lubomirblazekcz
Copy link
Author

lubomirblazekcz commented Dec 6, 2023

@daun that sounds good, but the name is not included in visit.to, but if it would that would work great

Here is an example how am I handling the loading skeletons, I might do a plugin out of this at some time. I'm doing a php eshop project now with Swup and it looks really cool, just like SPA. Swup got really powerful in these last versions, so great work guys!

const routeSkeleton = async name => (await import('../Utils/skeletons.js'))[name]

LibSwup.hooks.on('animation:out:end', async (visit) => {
    const { route } = visit.to
    const fragments = visit?.fragmentVisit?.containers

    if (fragments) {
        for (const container in fragments) {
            const skeleton = await routeSkeleton(fragments[container].replace('#swup-', ''))

            if (skeleton) {
                document.querySelector(fragments[container]).innerHTML = skeleton
                document.querySelector(fragments[container]).style.opacity = '1'
            }
        }
    }

    if (document.documentElement.classList.contains('is-leaving')) {
        document.getElementById('l-main').innerHTML = await routeSkeleton(route ?? 'any')
        document.getElementById('l-main').style.opacity = '1'
    }

    if (!window.location.hash && visit.scroll.reset && !fragments) {
        document.documentElement.scroll({ top: 0, behavior: 'instant' })
    }
})

@hirasso yeah true, that make sense

@daun
Copy link
Member

daun commented Dec 6, 2023

@lubomirblazekcz You'll find the animation name in visit.animation.name :)

Your use case is super fascinating! i would love to see a plugin for that kind of thing. These things always seemed a bit far off in Vue and React land, but you're right that with swup 4 there's a lot more to customize and extend.

@lubomirblazekcz
Copy link
Author

@daun great, that's it thanks!

@lubomirblazekcz
Copy link
Author

Here is a quick example of the skeletons in action, so yeah definitely doing a plugin when I got the time! There is a longer delay for testing purposes, the idea though is to show the skeleton only if the navigation is slow, if it's fast swup replaces the content and normal animation is shown.

Zaznam.obrazovky.2023-12-06.v.19.15.08.mp4

@daun
Copy link
Member

daun commented Dec 8, 2023

I'll move this request to the Fragment Plugin as it looks like the first use case is solved by visit.animation.name.

@daun daun transferred this issue from swup/swup Dec 8, 2023
@daun daun changed the title [Feature Request]: FragmentPlugin, RouteNamePlugin - matching rules by name [Feature Request]: matching rules by name Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants