Open lubomirblazekcz opened 8 months ago
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 🤠
@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...
@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.
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).
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.
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 .
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:
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.
@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.
Actually, that sounds very interesting! Looking forward to what you come up with!
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.
@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.
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.
@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
@lubomirblazekcz Even better then. Looks like I misread one of your previous comments to that effect.
@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">
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.
@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
@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.
@daun great, that's it thanks!
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.
https://github.com/swup/swup/assets/6872956/370c0623-551f-4e2e-bf1c-61b222064630
I'll move this request to the Fragment Plugin as it looks like the first use case is solved by visit.animation.name
.
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, ordata-swup-fragment-name="my-fragment-rule"
for fragmentsAlternatives 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?
How important is this feature to you? 🧭
Nice to have
Checked all these? 📚