Skip to content

Commit

Permalink
feat: enhance dropdown component with link navigation options and tra…
Browse files Browse the repository at this point in the history
…nsitions (#523)
  • Loading branch information
nunom27 authored Aug 22, 2024
1 parent a69ab77 commit a78995c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 33 deletions.
4 changes: 2 additions & 2 deletions lib/atomic_web/components/calendar/calendar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ defmodule AtomicWeb.Components.Calendar do
id="calendar-dropdown"
orientation={:down}
items={[
%{name: gettext("Week view"), link: @current_week_path},
%{name: gettext("Month view"), link: @current_month_path}
%{name: gettext("Week view"), patch: @current_week_path},
%{name: gettext("Month view"), patch: @current_month_path}
]}
>
<:wrapper>
Expand Down
47 changes: 37 additions & 10 deletions lib/atomic_web/components/dropdown.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
defmodule AtomicWeb.Components.Dropdown do
@moduledoc false
@moduledoc """
A customizable dropdown component for displaying a list of items, with flexible styling and behavior options.
"""
use Phoenix.Component

import AtomicWeb.Components.Icon
Expand All @@ -25,17 +27,42 @@ defmodule AtomicWeb.Components.Dropdown do

def dropdown(assigns) do
~H"""
<div class="relative inline-block text-left" phx-click={JS.toggle(to: "##{@id}", in: "block", out: "hidden")} phx-click-away={JS.hide(to: "##{@id}")}>
<%= render_slot(@wrapper) %>
<div id={@id} class={"#{if @orientation == :down, do: "origin-top-right top-full", else: "origin-bottom-right bottom-full"} absolute right-0 z-10 mt-2 hidden w-56 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5"}>
<div class="relative inline-block text-left" phx-click-away={JS.hide(to: "##{@id}", transition: {"ease-in duration-75", "transform opacity-100 scale-100", "transform opacity-0 scale-95"})}>
<div phx-click={JS.toggle(to: "##{@id}", in: {"ease-out duration-100", "transform opacity-0 scale-95", "transform opacity-100 scale-100"}, out: {"ease-in duration-75", "transform opacity-100 scale-100", "transform opacity-0 scale-95"}, display: "block")}>
<%= render_slot(@wrapper) %>
</div>
<div id={@id} class={"#{if @orientation == :down, do: "origin-top-right top-full mt-3", else: "origin-bottom-right bottom-full mb-3"} absolute right-0 z-10 hidden w-56 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5"}>
<div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
<%= for item <- @items do %>
<.link href={item.link} class="block flex items-center gap-x-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" role="menuitem" method={Map.get(item, :method, "get")}>
<%= if item[:icon] do %>
<.icon solid={@icon_variant == :solid} mini={@icon_variant == :mini} name={item.icon} class="ml-2 inline-block h-5 w-5" />
<% end %>
<%= item.name %>
</.link>
<%= if item[:patch] || item[:navigate] || item[:href] || item[:phx_click] do %>
<.link
patch={item[:patch]}
navigate={item[:navigate]}
href={item[:href]}
phx-click={
if item[:phx_click] do
JS.push(item[:phx_click]) |> JS.hide(to: "##{@id}", transition: {"ease-in duration-75", "transform opacity-100 scale-100", "transform opacity-0 scale-95"})
else
JS.hide(to: "##{@id}", transition: {"ease-in duration-75", "transform opacity-100 scale-100", "transform opacity-0 scale-95"})
end
}
class={"#{item[:class]} flex items-center gap-x-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"}
role="menuitem"
method={Map.get(item, :method, "get")}
>
<%= if item[:icon] do %>
<.icon solid={@icon_variant == :solid} mini={@icon_variant == :mini} name={item.icon} class="ml-2 inline-block h-5 w-5" />
<% end %>
<%= item.name %>
</.link>
<% else %>
<div class={"#{item[:class]} flex items-center gap-x-2 px-4 py-2 text-sm text-gray-700"}>
<%= if item[:icon] do %>
<.icon solid={@icon_variant == :solid} mini={@icon_variant == :mini} name={item.icon} class="ml-2 inline-block h-5 w-5" />
<% end %>
<%= item.name %>
</div>
<% end %>
<% end %>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions lib/atomic_web/live/department_live/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
[
%{
name: gettext("Collaborators"),
link:
navigate:
Routes.department_show_path(
@socket,
:show,
Expand All @@ -67,7 +67,7 @@
}
] ++
if @has_permissions? || (@current_collaborator && @current_collaborator.accepted) do
[%{name: gettext("Edit"), link: Routes.department_edit_path(@socket, :edit, @organization, @department, @params), icon: :pencil}]
[%{name: gettext("Edit"), navigate: Routes.department_edit_path(@socket, :edit, @organization, @department, @params), icon: :pencil}]
else
[]
end
Expand Down
8 changes: 4 additions & 4 deletions lib/atomic_web/templates/layout/_live_navbar.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
<AtomicWeb.Components.Dropdown.dropdown
orientation={:top}
items={[
%{name: "Your profile", link: Routes.profile_show_path(@socket, :show, @current_user)},
%{name: "Sign out", link: Routes.user_session_path(@socket, :delete), method: "delete"}
%{name: "Your profile", navigate: Routes.profile_show_path(@socket, :show, @current_user)},
%{name: "Sign out", href: Routes.user_session_path(@socket, :delete), method: "delete"}
]}
id="user-menu-button"
>
Expand Down Expand Up @@ -185,8 +185,8 @@
<AtomicWeb.Components.Dropdown.dropdown
orientation={:down}
items={[
%{name: "Your profile", link: Routes.profile_show_path(@socket, :show, @current_user)},
%{name: "Sign out", link: Routes.user_session_path(@socket, :delete)}
%{name: "Your profile", navigate: Routes.profile_show_path(@socket, :show, @current_user)},
%{name: "Sign out", navigate: Routes.user_session_path(@socket, :delete)}
]}
id="user-dropdown-menu"
>
Expand Down
30 changes: 15 additions & 15 deletions storybook/components/dropdown.story.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ defmodule AtomicWeb.Storybook.Components.Dropdown do
attributes: %{
id: "dropdown",
items: [
%{name: "Profile", link: "#"},
%{name: "Settings", link: "#"},
%{name: "Logout", link: "#"}
%{name: "Profile", navigate: "#"},
%{name: "Settings", navigate: "#"},
%{name: "Logout", navigate: "#"}
],
orientation: :down
},
Expand All @@ -35,9 +35,9 @@ defmodule AtomicWeb.Storybook.Components.Dropdown do
attributes: %{
id: "dropdown-down",
items: [
%{name: "Profile", link: "#"},
%{name: "Settings", link: "#"},
%{name: "Logout", link: "#"}
%{name: "Profile", navigate: "#"},
%{name: "Settings", navigate: "#"},
%{name: "Logout", navigate: "#"}
],
orientation: :down
},
Expand All @@ -54,9 +54,9 @@ defmodule AtomicWeb.Storybook.Components.Dropdown do
attributes: %{
id: "dropdown-top",
items: [
%{name: "Profile", link: "#"},
%{name: "Settings", link: "#"},
%{name: "Logout", link: "#"}
%{name: "Profile", navigate: "#"},
%{name: "Settings", navigate: "#"},
%{name: "Logout", navigate: "#"}
],
orientation: :top
},
Expand All @@ -80,9 +80,9 @@ defmodule AtomicWeb.Storybook.Components.Dropdown do
id: "dropdown-solid-icons",
icon_variant: :solid,
items: [
%{name: "Profile", link: "#", icon: :user},
%{name: "Settings", link: "#", icon: :cog},
%{name: "Logout", link: "#", icon: :arrow_left_on_rectangle}
%{name: "Profile", navigate: "#", icon: :user},
%{name: "Settings", navigate: "#", icon: :cog},
%{name: "Logout", navigate: "#", icon: :arrow_left_on_rectangle}
],
orientation: :down
},
Expand All @@ -100,9 +100,9 @@ defmodule AtomicWeb.Storybook.Components.Dropdown do
id: "dropdown-outline-icons",
icon_variant: :outline,
items: [
%{name: "Profile", link: "#", icon: :user},
%{name: "Settings", link: "#", icon: :cog},
%{name: "Logout", link: "#", icon: :arrow_left_on_rectangle}
%{name: "Profile", navigate: "#", icon: :user},
%{name: "Settings", navigate: "#", icon: :cog},
%{name: "Logout", navigate: "#", icon: :arrow_left_on_rectangle}
],
orientation: :top
},
Expand Down

0 comments on commit a78995c

Please sign in to comment.