-
Notifications
You must be signed in to change notification settings - Fork 28
Anchor extensions #278
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
base: main
Are you sure you want to change the base?
Anchor extensions #278
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for showing us what this would look like!
I think what is most missing here is some evidence that this kind of functionality is something developers want. Especially for the more complex pieces. Is anyone creating experiences like these today using JavaScript? Can you find live examples, ideally on popular sites? Or even just StackOverflow questions of people asking how to do this sort of thing?
The `reload=""` attribute will reload the current entry. Note: the `href=""` attribute is ignored. | ||
```html | ||
<a reload>Refresh results</a> | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the benefits of this over <button onclick="location.reload()">
? It's unclear if reloading really fits the hyperlink paradigm well...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I'm not very sure either, I added it more for completeness sake. I did think it would be nice to have a "open in next tab" functionality for a refresh UI element which a <button>
would lack, which is why I still added it. Beyond content security policies blocking inline JS I don't see any problem with just using JS like in your example to achieve the same behaviour. If there isn't much interest in something like this I would drop it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do have a question though, what kind of navigation does <a href='.'>
trigger i.e. what should NavigateEvent.navigationType yield? I tried this in chrome a few times, sometimes it would be a push navigation and sometimes it would be a replace navigation. I ask because my initial intuition was this would have been a "reload" navigation but since that wasn't the case I felt motivated to add a keyword for it.
```html | ||
<a href="/login" replace>Logout</a> | ||
``` | ||
The `traverse=""` attibute allows `<a>`s to link to existing entries. When using the `traverse=""` navigation type modifier the `rel="next/prev"`, `key="..."` and `href="..."` attributes, become optional hints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar questions for the href-less versions here.
Additionally, to get key=""
s you need to use JavaScript. So I can't really understand when you would use this.
I can see a use case for <a href="/" rel="prev" traverse>
, however.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key="..."
attribute is merely a convenience instead of a Super Declarative™ API. This exists as a method for when you want to be super precise about which entry you navigate to unlike the href="..."
pattern matching feature. Additionally having an <a>
tag that navigates to a specific existing entry without clickjacking is essentially impossible without something like the NavigateEvent.sourceElement feature.
A solid use case for something like this that I thought of is implementing breadcrumbs, most sites currently implement such a feature using the basic push navigation behaviour of the <a>
which can lead to a messy history stack as a "previous" page now exists at the head of the history stack.
```html | ||
<a href=".." traverse>Tab 1</a> <!-- Given the current URL pathname is /parent/child this anchor navigates to an entry with /parent as the pathname. --> | ||
<a href="/" rel="prev" traverse>Go home</a> | ||
<a href="/posts" rel="next" traverse>Posts</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if there are no links in history with these hrefs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are no links in the history then it should fallback to the base navigate behaviour. The default base navigate behaviour for <a>
s as they exist now is "push", meaning if a link doesn't exist it simply becomes a push navigation. The proposal also adds the ability to modify this "base navigate behaviour" so for example a replace=""
boolean attribute would make the fallback instead be a replace navigation.
}; | ||
a.navigateinfo = { | ||
type: "push", | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this gets pretty messy.
The issues mostly come about with the interaction between the JS properties and the attributes.
- What does the attribute return, when the JS property is set to an object?
- What does the JS property return, when the attribute is set to a string?
- How does
el.setAttribute("navigatestate", el.getAttribute("navigatestate"))
behave? Does it change what state is sent? Does it change the value of the JS property? - How does
el.navigatestate = el.navigatestate
behave? Does it change what state is sent? Does it change the value of the attribute?
I would suggest leaving these as strings only and saying that if you want more complex objects, you need to use JavaScript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The getAttribute() would return the attribute as seen in HTML.
- The JS property at first would be the same as the HTML attribute. In other words the attribute would serve as a "default value".
- No, the attribute wouldn't change the value of the JS property. The JS property takes precedent in the state that is sent.
- No, the JS property wouldn't change the value of the attribute.
TLDR; the idea here is the navigatestate and navigateinfo properties/attributes would mirror the behaviour of the value attribute/property from the <input>
element. The attribute has no effect on the property beyond its use as a "default value".
This wasn't very clear in the demo and I apologise.
``` | ||
|
||
#### Additional Example | ||
Tabbed navigation could be implemented without JavaScript. By using `traverse=""` anchors will point to existing entries if they exist but fallback to a push navigation if a matching entry doesn't already exist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually a user experience that people want? Are there any sites today that are implementing this kind of user experience using JavaScript?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main tabs in Gmail are implemented using JavaScript, however like many implementations online these navigations aren't added to the history stack and it's not trivial to implement synchronisation with the history stack especially with the old history API.
This is also the case for Azure which is an SPA that uses hash based navigation but they still don't persist these navigations to the stack.
I couldn't find any example of tab navigation by history stack traversal via JS but from my experience a lot of the anxiety around doing things like that on the web comes from the fact that it's hard. Also the default navigation behaviour of an <a>
being push further encourages developers to use JavaScript based solutions that aren't synched to the browser history stack to avoid duplicate history entries polluting the stack (among other issues).
One problem with omitting tab navigation from the browser history is that users lose their position upon reloading the page, forcing them to manually restore their previous state. Additionally, tabs are not directly linkable, which can be frustrating if you wish to share or revisit a specific tab. To address this in the past, I have implemented a solution that synchronizes the tab state with the query parameters in the URL. This approach ensures that users can reload the page without losing their current tab selection while also making tabs linkable. At the same time, it avoids polluting the history stack with duplicate entries by updating the URL without pushing new history entries unnecessarily. By reading the initial tab state from window.location.search
, I could restore the current tab when the page loads. CodeSandbox implements file tabs like this.
Here's a SO post I came across once about using only an |
By any chance are there any channels you recommend I use to solicit this kind of feedback? |
This PR adds a proposal for extensions to the existing anchor (
<a>
) element. You can see the proposal in action in this demo written in Lit.