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

[RFC]: Add support for fragments/anchors to routes functions #8069

Open
1 task done
cannikin opened this issue Apr 20, 2023 · 10 comments
Open
1 task done

[RFC]: Add support for fragments/anchors to routes functions #8069

cannikin opened this issue Apr 20, 2023 · 10 comments

Comments

@cannikin
Copy link
Member

cannikin commented Apr 20, 2023

Summary

A "fragment" is the HTML spec's name for the part of the URL after a # symbol:

https://redwoodjs.com/docs/deploy/baremetal#server-setup
                                            ^^^^^^^^^^^^  <- fragment

The default browser behavior is to scroll down to the first element in the DOM that has an id attribute matching that fragment:

<div id="server-setup">
  <!-- ... -->
</div>

Right now there's no way, using the standard routes helper functions, to construct a URL that includes a fragment. A workaround is to append it to the generated path:

<Link to={`${routes.post({ id: 123 })}#comments`}>See Comments</Link>

Motivation

Fragments are a standard part of URLs and part of the HTML spec, and we should be able to create those URLs using our recommended tools (the routes helpers). It's very common to want to redirect somewhere else and jump to a certain section of the page.

Note that depending on how the page is build, the required DOM element may not be present on the page, and so the browser will not actually be able to scroll down to it. I would like to support this behavior as well, but this Issue is specifically just about being able to create the URL.

Detailed proposal

I propose adding support for a fragment key to the named routes helpers, in some form or another. One possibility is:

routes.post({ id: 123, fragment: 'comments' })

This means that you could no longer create a query string variable named fragment, which would make this change backwards incompatible for anyone that was already using that name. (Today, if you wrote the above code, you'd get the path /post/123?fragment=comments

I'd also be open to prefixing this key with something, such as an underscore like _fragment, which indicates that it has special significance as far as Redwood is concerned. My only concern is that informally in the JS community, prefixing something with an underscore denotes it as "private" functionality that the end user generally shouldn't mess with.

Another option would be to have these helpers accept a second, optional argument:

routes.post({ id: 123}, { fragment: 'comments' })

This would be completely new functionality and thus not break existing route generation.

For what it's worth, in the Rails helpers this key is named anchor and that's just the way it is: you can't use anchor for a query string variable and it's fine.

It's possible we could use fragment but provide a codemod that searches through your codebase for any usage of routes.something({ fragment: '' }) and give you a warning? It would be nice to just pick something and go for it, rather than wring our hands that maybe someone used that word, and make the UX worse for everyone else for all time.

Are you interested in working on this?

  • I'm interested in working on this
@cannikin cannikin changed the title [RFC]: Add support for fragments to routes function [RFC]: Add support for fragments to routes functions Apr 20, 2023
@ageddesi
Copy link
Contributor

Happy to look into fixing this

@cannikin
Copy link
Member Author

It's all yours! :)

@cannikin
Copy link
Member Author

Updated the post with more rationale about going with just a key named fragment...

@Tobbe
Copy link
Member

Tobbe commented Apr 30, 2023

The default browser behavior is to scroll down to the first element in the DOM that has an id attribute matching that fragment:

TIL! I thought you still did <a name="server-setup"> to define in-page anchor targets. But apparently that's deprecated now.

routes.post({ id: 123, fragment: 'comments' })

I'm not a big fan of mixing special meaning keys with user defined keys in the same namespace. Doing that has already come back to bite us so many times! A recent example is here: #7024 but it's also been when we inject props into pages etc

If you're still not convinced it's a bad idea, maybe we could consider naming the key '#' instead of fragment. Feels like less likely to conflict with what someone might already be using or want to use. Plus it stands out more, signaling that something special's going on

routes.post({ id: 123, '#': 'comments' })

FWIW I don't think this is too bad...

<Link to={routes.post({ id: 123 }) + '#comments'}>See Comments</Link>

Why introduce new syntax for something that's already possible to do?

@cannikin
Copy link
Member Author

cannikin commented May 1, 2023

Hmm, I do find that '#': 'comments' version intriguing...makes it extremely clear what you're setting, as opposed to knowing that the the real name for that part of the URL is the "fragment" and not the "hash" (which is what it's called in the DOM! location.hash).

Why introduce new syntax for something that's already possible to do?

That's a slippery slope argument where you end up talking yourself out of every feature we've created for the framework! "It's already all possible, why use Redwood?"

For me, I think if the routes helpers are for creating URLs then they should support everything a real URL supports, including the fragment. Technically routes don't care about query string variables, but we don't make you add them like routes.post() + '?foo=bar'. There's lots of stuff that's possible to do without helpers, but we want to make it more better! :)

@Tobbe
Copy link
Member

Tobbe commented May 2, 2023

For me, I think if the routes helpers are for creating URLs then they should support everything a real URL supports

Great! So remind me again how you use the routes helpers to set the scheme? :trollface:

@cannikin
Copy link
Member Author

cannikin commented May 2, 2023

WELL, the routes are only for internal routing, right? So no need to set the scheme (or domain, or port). But hey I'm up for adding it if you are. ;)

@ageddesi
Copy link
Contributor

ageddesi commented May 3, 2023

The '#': 'comments' is where I will be heading in my attempt. Just got to find a little bit of time.

@ageddesi
Copy link
Contributor

I have seen a few PRs related to this route subject. Is this now done or do I still need to look into this ticket?

@Tobbe
Copy link
Member

Tobbe commented Jun 20, 2023

A PR for this would still be very much appreciated 🙂

@Tobbe Tobbe changed the title [RFC]: Add support for fragments to routes functions [RFC]: Add support for fragments/anchors to routes functions Nov 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants