-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Prevent invalid markup in generators #5820
Conversation
89c76df
to
0c5af43
Compare
Good question! it doesn’t feel great if we have to mirror the .link API. |
I prefer allowing:
because it doesn't require the user to learn a new API. Another option I have used before is a |
LiveBeats (which predates core components) also implemented a button patch, so while mirroring link doens't feel great, I've been down this path and I guess that's my preference ¯_(ツ)_/¯ |
So if we mirror the link API, for full link support we'd need to add
If you feel like this is the way to go I'll adjust the PR. Definitely doesn't feel nice, especially as users could also write something like
so we'd probably want to have a runtime check that raises if some of these are used without href/patch/navigate? With all this considered I think I'd prefer either the @doc """
Renders a link, styled like a button.
For available options, see `Phoenix.Component.link/1`.
"""
attr :class, :string, default: ""
attr :rest, :global, include: ~w(href patch navigate replace method csrf_token download hreflang referrerpolicy rel target type)
def button_link(assigns) do
~H"""
<.link
class={[
"phx-submit-loading:opacity-75 rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3",
"text-sm font-semibold leading-6 text-white active:text-white/80",
@class
]}
{@rest}
>
<%= render_slot(@inner_block) %>
</.link>
"""
end which always renders as |
I am rethinking this discussion. Looking at the attributes:
It doesn't feels href/patch/navigate should really not be part of a button? Why are we navigating on button actions? I know some people use it for login/sign up buttons but 1. we don't have to do it by default 2. nor push people towards this direction by having this as a built-in? |
I think one reason why people often want to navigate using buttons is to keep state in the URL. One big footgun is deploying a LV app which sooner or later forces clients to reconnect and then lose state if it is not kept in the URL or a form (and more complex use cases). So at least from my experience, very often when clicking a non-submit button something in the URL will (or at least should) change, to have a good user experience. We could also just use So I do think that sooner or later complex applications that have styled buttons will be in the situation where they want a |
I like the idea of |
After some thoughts. I would just change the markup to use something else. We should aim towards making CoreComponents smaller, not larger. Many people already think it is quite intimidating. :) |
While Core Components give a great out-of-the-box start, I've felt at times that overriding the default classes is unexpectedly hard. A change I remember doing in a project was making it easier to override all classes for some components, Reading the present conversation, it seems to me that if it was easier to override the styles of each component a potential At present, when a component take a One way would be to make the default styles available (perhaps as functions), and have Reminds me that on occasion I have resorted to using Tailwind's |
Reading through other issues I ran into phoenixframework/phoenix_live_view#2590, which shows exactly what I was describing regarding overriding classes. |
I agree with this. The links also don't actually need to look the same as the button generated by |
@leejarvis we don't want to add Tailwind classes to the templates, see #5814 (comment). So I'm not sure what best to do. If we just use But I also don't like having a Ideally, we'd have a way to specify that a component wraps another one and accepts all of its attributes: include_attrs, from: {Phoenix.Component, :link}
include_slots, from: {Phoenix.Component, :link}
def styled_link(assigns) do
~H"""
<.link class="default-styles" {assigns} />
"""
end and still get all compile time validations if we write |
I agree that the button style looks a little nicer, but normal links are already used in other places (like show/edit/delete). I think the emphasis on this element being a "normal" link beats having custom styles or over-populating |
Another approach we could try to find is to find a style that works both for "Back to Posts" and "Edit posts". Then instead of introducing a new function, we replace |
45c2d67
to
8cf7ab7
Compare
I actually wanted to do this, but then I needed to mess with the margin included in the back component. For now, I updated the PR to use unstyled links. |
We could replace I support this change as it is though given that it fixes the invalid markup issue. |
Another option to prevent invalid HTML would be to just reverse the order of elements: ~H"""
<.button phx-click={JS.dispatch("click", to: "a", inner: true)}>
<.link navigate={~p"/posts/new"}>New Post</.link>
</.button>
""" You could also do this without the dispatch, but then clicking on the outer edge of the button would do nothing. This requires phoenixframework/phoenix_live_view#3396. |
It is not allowed to render a button inside an <a> tag: https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element Therefore, we invert the order of the elements and nest a link inside a button and forward any button clicks to the link. Fixes #5770. References #5814.
8cf7ab7
to
20a2638
Compare
@josevalim I inverted the order of elements and use the new element targeting syntax introduced in a recent LV RC. Wdyt? |
Nesting a button inside an anchor tag is not valid HTML. This change inverts the order of the elements and nests a link inside a button instead. We forward any button clicks to the link.
Fixes #5770.
References #5814.