Right now Inertia links are always rendered as anchor <a> elements. However, there are situations where it might make more sense to render a different element. I'm considering adding a new as attribute to support this behaviour.
<inertia-link href="/example" as="div">Example</inertia-link>
<!-- Renders as: -->
<div>Example</div>
Consider a non-GET link, such as a logout link. If you were to try and open this link in a new tab/window, you would get a 405 (Method Not Allowed) error. And that's because by opening it in a new tab/window, it gets handled like a regular GET request.
<inertia-link href="/logout" method="post">Logout</inertia-link>
From an accessibility perspective, it would be better to use a button in these cases, since you can't open a button in a new tab/window.
<inertia-link href="/logout" method="post" as="button" type="button">Logout</inertia-link>
<!-- Renders as a button (an a click event listener) -->
<button type="button">Logout</button>
Considering the accessibility issues that come with using anchor links for non-GET requests, I wonder if it would be wise to actually deprecate this behaviour. We could do this by showing a console warning if the method is set to something other than get, and the element is an anchor link.
if (props.method !== 'get' && props.as === 'a') {
console.warn('Creating post/put/patch/delete anchor links is discouraged as it causes "open in new tab/window" accessibility issues. Please specify a different element using the "as" option.')
}
An alternative approach is encouraging the use of directives instead. An inertia directive already exists in the Svelte adapter, and one has been started for the Vue adapter (#207). However, are directives even a thing in React?
It's worth noting that this feature has been intentionally avoided in React Router:
There have been multiple requests for it, but it just isn't something that the React Router team wants to encourage because using a non-anchor component for links begs for accessibility issues.
Ironically, the reason I want this feature is to fix accessibility issues caused by non-GET Inertia links.
What about tag instead of as to be consistent with the Vue Router? (https://router.vuejs.org/api/#tag)
@hivokas If you look up, you'll notice that I actually had tag at first, but change it to as. I changed it because:
as.as="MyComponent"), then tag doesn't really make sense.I actually had a chat with @adamwathan about this, because I know they had to make this decision on Headless UI, and those were the two reasons they decided to go with as.
Another idea would be to support slots / render functions. This is more verbose but does provide more flexibility. I think as is a good addition either way, just wanna share this because it solves similar problems.
Vue example:
<inertia-link href="/logout" method="POST" v-slot="{ visit }">
<button @click="visit">Log out<button>
</inertia-link>
React example:
<InertiaLink href="/logout" method="POST">
{({ visit }) => <button onClick="visit">Log out</button>}
</InertiaLink>
Also note that the current implementation of shouldIntercept is based on the a tag. I assume shift-clicking, etc. does need to be intercepted on a button, since shift-clicking a native button doesn't do anything.
Most helpful comment
Another idea would be to support slots / render functions. This is more verbose but does provide more flexibility. I think
asis a good addition either way, just wanna share this because it solves similar problems.Vue example:
React example:
Also note that the current implementation of
shouldInterceptis based on theatag. I assume shift-clicking, etc. does need to be intercepted on a button, since shift-clicking a native button doesn't do anything.