Skip to content

Commit

Permalink
Add button link attribute
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
SteffenDE committed May 21, 2024
1 parent 0b865d6 commit 0c5af43
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 28 deletions.
33 changes: 25 additions & 8 deletions installer/templates/phx_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -215,28 +215,45 @@ defmodule <%= @web_namespace %>.CoreComponents do
@doc """
Renders a button.
If `link` is passed as an attribute, the button will render as an HTML link.
## Examples
<.button>Send!</.button>
<.button phx-click="go" class="ml-2">Send!</.button>
<.button link={%{patch: ~p"/page"}}>Go to page</.button>
"""
attr :type, :string, default: nil
attr :link, :map, default: nil, doc: "attributes passed to `Phoenix.Component.link/1`"
attr :class, :string, default: nil
attr :rest, :global, include: ~w(disabled form name value)

slot :inner_block, required: true

def button(assigns) do
~H"""
<button
type={@type}
class={[
assigns =
assigns
|> assign(:classes, [
"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}
>
assigns.class
])

button_base(assigns)
end

def button_base(%{link: link} = assigns) when not is_nil(link) do
~H"""
<.link class={@classes} {@link} {@rest}>
<%%= render_slot(@inner_block) %>
</.link>
"""
end

def button_base(assigns) do
~H"""
<button type={@type} class={@classes} {@rest}>
<%%= render_slot(@inner_block) %>
</button>
"""
Expand Down
4 changes: 1 addition & 3 deletions priv/templates/phx.gen.html/index.html.heex
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<.header>
Listing <%= schema.human_plural %>
<:actions>
<.link href={~p"<%= schema.route_prefix %>/new"}>
<.button>New <%= schema.human_singular %></.button>
</.link>
<.button link={%{href: ~p"<%= schema.route_prefix %>/new"}}>New <%= schema.human_singular %></.button>
</:actions>
</.header>

Expand Down
4 changes: 1 addition & 3 deletions priv/templates/phx.gen.html/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
<%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
<:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
<:actions>
<.link href={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/edit"}>
<.button>Edit <%= schema.singular %></.button>
</.link>
<.button link={%{href: ~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/edit"}}>Edit <%= schema.singular %></.button>
</:actions>
</.header>

Expand Down
33 changes: 25 additions & 8 deletions priv/templates/phx.gen.live/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -215,28 +215,45 @@ defmodule <%= @web_namespace %>.CoreComponents do
@doc """
Renders a button.
If `link` is passed as an attribute, the button will render as an HTML link.
## Examples
<.button>Send!</.button>
<.button phx-click="go" class="ml-2">Send!</.button>
<.button link={%{patch: ~p"/page"}}>Go to page</.button>
"""
attr :type, :string, default: nil
attr :link, :map, default: nil, doc: "attributes passed to `Phoenix.Component.link/1`"
attr :class, :string, default: nil
attr :rest, :global, include: ~w(disabled form name value)

slot :inner_block, required: true

def button(assigns) do
~H"""
<button
type={@type}
class={[
assigns =
assigns
|> assign(:classes, [
"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}
>
assigns.class
])

button_base(assigns)
end

def button_base(%{link: link} = assigns) when not is_nil(link) do
~H"""
<.link class={@classes} {@link} {@rest}>
<%%= render_slot(@inner_block) %>
</.link>
"""
end

def button_base(assigns) do
~H"""
<button type={@type} class={@classes} {@rest}>
<%%= render_slot(@inner_block) %>
</button>
"""
Expand Down
4 changes: 1 addition & 3 deletions priv/templates/phx.gen.live/index.html.heex
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<.header>
Listing <%= schema.human_plural %>
<:actions>
<.link patch={~p"<%= schema.route_prefix %>/new"}>
<.button>New <%= schema.human_singular %></.button>
</.link>
<.button link={%{patch: ~p"<%= schema.route_prefix %>/new"}}>New <%= schema.human_singular %></.button>
</:actions>
</.header>

Expand Down
6 changes: 3 additions & 3 deletions priv/templates/phx.gen.live/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
<:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
<:actions>
<.link patch={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/show/edit"} phx-click={JS.push_focus()}>
<.button>Edit <%= schema.singular %></.button>
</.link>
<.button link={%{patch: ~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}/show/edit"}} phx-click={JS.push_focus()}>
Edit <%= schema.singular %>
</.button>
</:actions>
</.header>

Expand Down

0 comments on commit 0c5af43

Please sign in to comment.