Skip to content

Commit 89c76df

Browse files
committed
Add button link attribute
Nesting a button inside an anchor tag is not valid HTML. This change introduces a new `link` attribute in the `button` core component that, when present, will render the button as an anchor tag instead. Fixes #5770. References #5814.
1 parent 0b865d6 commit 89c76df

File tree

6 files changed

+59
-28
lines changed

6 files changed

+59
-28
lines changed

installer/templates/phx_web/components/core_components.ex

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,28 +215,45 @@ defmodule <%= @web_namespace %>.CoreComponents do
215215
@doc """
216216
Renders a button.
217217
218+
If `link` is passed as an attribute, the button will render as an HTML link.
219+
218220
## Examples
219221
220222
<.button>Send!</.button>
221223
<.button phx-click="go" class="ml-2">Send!</.button>
224+
<.button link={%{patch: ~p"/page"}}>Go to page</.button>
225+
222226
"""
223227
attr :type, :string, default: nil
228+
attr :link, :map, default: nil, doc: "attributes passed to `Phoenix.Component.link/1`"
224229
attr :class, :string, default: nil
225230
attr :rest, :global, include: ~w(disabled form name value)
226231

227232
slot :inner_block, required: true
228233

229234
def button(assigns) do
230-
~H"""
231-
<button
232-
type={@type}
233-
class={[
235+
assigns =
236+
assigns
237+
|> assign(:classes, [
234238
"phx-submit-loading:opacity-75 rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3",
235239
"text-sm font-semibold leading-6 text-white active:text-white/80",
236-
@class
237-
]}
238-
{@rest}
239-
>
240+
assigns.class
241+
])
242+
243+
button_base(assigns)
244+
end
245+
246+
def button_base(%{link: link} = assigns) when not is_nil(link) do
247+
~H"""
248+
<.link class={@classes} {@link} {@rest}>
249+
<%%= render_slot(@inner_block) %>
250+
</.link>
251+
"""
252+
end
253+
254+
def button_base(assigns) do
255+
~H"""
256+
<button type={@type} class={@classes} {@rest}>
240257
<%%= render_slot(@inner_block) %>
241258
</button>
242259
"""

priv/templates/phx.gen.html/index.html.heex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<.header>
22
Listing <%= schema.human_plural %>
33
<:actions>
4-
<.link href={~p"<%= schema.route_prefix %>/new"}>
5-
<.button>New <%= schema.human_singular %></.button>
6-
</.link>
4+
<.button link={%{href: ~p"<%= schema.route_prefix %>/new"}}>New <%= schema.human_singular %></.button>
75
</:actions>
86
</.header>
97

priv/templates/phx.gen.html/show.html.heex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
<%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
33
<:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
44
<:actions>
5-
<.link href={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/edit"}>
6-
<.button>Edit <%= schema.singular %></.button>
7-
</.link>
5+
<.button link={%{href: ~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/edit"}}>Edit <%= schema.singular %></.button>
86
</:actions>
97
</.header>
108

priv/templates/phx.gen.live/core_components.ex

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,28 +215,45 @@ defmodule <%= @web_namespace %>.CoreComponents do
215215
@doc """
216216
Renders a button.
217217
218+
If `link` is passed as an attribute, the button will render as an HTML link.
219+
218220
## Examples
219221
220222
<.button>Send!</.button>
221223
<.button phx-click="go" class="ml-2">Send!</.button>
224+
<.button link={%{patch: ~p"/page"}}>Go to page</.button>
225+
222226
"""
223227
attr :type, :string, default: nil
228+
attr :link, :map, default: nil, doc: "attributes passed to `Phoenix.Component.link/1`"
224229
attr :class, :string, default: nil
225230
attr :rest, :global, include: ~w(disabled form name value)
226231

227232
slot :inner_block, required: true
228233

229234
def button(assigns) do
230-
~H"""
231-
<button
232-
type={@type}
233-
class={[
235+
assigns =
236+
assigns
237+
|> assign(:classes, [
234238
"phx-submit-loading:opacity-75 rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3",
235239
"text-sm font-semibold leading-6 text-white active:text-white/80",
236-
@class
237-
]}
238-
{@rest}
239-
>
240+
assigns.class
241+
])
242+
243+
button_base(assigns)
244+
end
245+
246+
def button_base(%{link: link} = assigns) when not is_nil(link) do
247+
~H"""
248+
<.link class={@classes} {@link} {@rest}>
249+
<%%= render_slot(@inner_block) %>
250+
</.link>
251+
"""
252+
end
253+
254+
def button_base(assigns) do
255+
~H"""
256+
<button type={@type} class={@classes} {@rest}>
240257
<%%= render_slot(@inner_block) %>
241258
</button>
242259
"""

priv/templates/phx.gen.live/index.html.heex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<.header>
22
Listing <%= schema.human_plural %>
33
<:actions>
4-
<.link patch={~p"<%= schema.route_prefix %>/new"}>
5-
<.button>New <%= schema.human_singular %></.button>
6-
</.link>
4+
<.button link={%{patch: ~p"<%= schema.route_prefix %>/new"}}>New <%= schema.human_singular %></.button>
75
</:actions>
86
</.header>
97

priv/templates/phx.gen.live/show.html.heex

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
<%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
33
<:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
44
<:actions>
5-
<.link patch={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/show/edit"} phx-click={JS.push_focus()}>
6-
<.button>Edit <%= schema.singular %></.button>
7-
</.link>
5+
<.button
6+
link={%{patch: ~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/show/edit"}}
7+
phx-click={JS.push_focus()}
8+
>
9+
Edit <%= schema.singular %>
10+
</.button>
811
</:actions>
912
</.header>
1013

0 commit comments

Comments
 (0)