diff --git a/lib/atomic_web/components/activity.ex b/lib/atomic_web/components/activity.ex index 84ee53e61..9680000b1 100644 --- a/lib/atomic_web/components/activity.ex +++ b/lib/atomic_web/components/activity.ex @@ -4,7 +4,7 @@ defmodule AtomicWeb.Components.Activity do """ use AtomicWeb, :component - import AtomicWeb.Components.Avatar + import AtomicWeb.Components.{Avatar, Popover} alias Atomic.Activities.Activity @@ -13,22 +13,28 @@ defmodule AtomicWeb.Components.Activity do def activity(assigns) do ~H"""
-
+
- <.avatar name={@activity.organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@activity.organization.logo, @activity.organization}, :original)} /> + <.popover type={:organization} organization={@activity.organization} position={:left}> + <:wrapper> + <.avatar name={@activity.organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@activity.organization.logo, @activity.organization}, :original)} /> + +
-
- - <.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @activity.organization.id)}> - - <%= @activity.organization.name %> - - - -

- Published on - -

+
+
+ + <.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @activity.organization.id)}> + + <%= @activity.organization.name %> + + + +

+ Published on + +

+

<%= @activity.title %>

diff --git a/lib/atomic_web/components/announcement.ex b/lib/atomic_web/components/announcement.ex index 78569fe90..46031a6a3 100644 --- a/lib/atomic_web/components/announcement.ex +++ b/lib/atomic_web/components/announcement.ex @@ -4,29 +4,35 @@ defmodule AtomicWeb.Components.Announcement do """ use AtomicWeb, :component - import AtomicWeb.Components.Avatar + import AtomicWeb.Components.{Avatar, Popover} attr :announcement, :map, required: true, doc: "The announcement to render." def announcement(assigns) do ~H"""
-
+
- <.avatar name={@announcement.organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@announcement.organization.logo, @announcement.organization}, :original)} /> + <.popover type={:organization} organization={@announcement.organization} position={:bottom}> + <:wrapper> + <.avatar name={@announcement.organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@announcement.organization.logo, @announcement.organization}, :original)} /> + +
-
- - <.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @announcement.organization.id)} class="hover:underline focus:outline-none"> -

- <%= @announcement.organization.name %> -

- -
-

- Published on - -

+
+
+ + <.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @announcement.organization.id)} class="hover:underline focus:outline-none"> +

+ <%= @announcement.organization.name %> +

+ +
+

+ Published on + +

+

<%= @announcement.title %>

diff --git a/lib/atomic_web/components/avatar.ex b/lib/atomic_web/components/avatar.ex index 7331b1821..cb2695cec 100644 --- a/lib/atomic_web/components/avatar.ex +++ b/lib/atomic_web/components/avatar.ex @@ -40,7 +40,7 @@ defmodule AtomicWeb.Components.Avatar do ~H""" <%= if @src do %> - + <% else %> <%= extract_initials(@name) %> <% end %> diff --git a/lib/atomic_web/components/popover.ex b/lib/atomic_web/components/popover.ex new file mode 100644 index 000000000..79dcfaf02 --- /dev/null +++ b/lib/atomic_web/components/popover.ex @@ -0,0 +1,111 @@ +defmodule AtomicWeb.Components.Popover do + @moduledoc """ + Renders a popover. + """ + + use AtomicWeb, :component + + import AtomicWeb.Components.Avatar + + attr :type, :atom, + values: [:user, :organization, :button], + default: :user, + doc: "The type of entity associated with the avatar." + + attr :position, :atom, + values: [:top, :right, :bottom, :left], + required: true, + doc: "The position of the popover." + + attr :organization, :map, default: %{}, doc: "The organization to render." + attr :user, :map, default: %{}, doc: "The user to render." + attr :button, :map, default: %{}, doc: "The button to render." + + slot :wrapper, + required: true, + doc: "Slot to be rendered as a wrapper of the popover. For example, a avatar." + + def popover(assigns) do + ~H""" +
+ <%= render_slot(@wrapper) %> +
+
+ <%= render_popover(assigns, type: @type) %> +
+
+
+ """ + end + + def triangle_class(position: :bottom) do + "before:border-l-[10px] before:border-b-[10px] before:border-r-[10px] before:absolute before:mx-3 before:mb-8 before:border-r-transparent before:border-b-gray-200 before:border-l-transparent" + end + + def triangle_class(position: :top) do + "before:bottom-full before:border-l-[10px] before:border-t-[10px] before:border-r-[10px] before:absolute before:mx-3 before:mt-8 before:border-r-transparent before:border-b-gray-200 before:border-l-transparent" + end + + def triangle_class(position: :left) do + "before:right-full before:bottom-0 before:border-t-[10px] before:border-l-[10px] before:border-b-[10px] before:absolute before:mt-9 before:border-t-transparent before:border-l-gray-200 before:border-b-transparent" + end + + def triangle_class(position: :right) do + "before:left-full before:bottom-0 before:border-t-[10px] before:border-r-[10px] before:border-b-[10px] before:absolute before:mt-9 before:border-t-transparent before:border-r-gray-200 before:border-b-transparent" + end + + def popover_position(position: :bottom) do + "mt-2" + end + + def popover_position(position: :top) do + "bottom-full mb-2" + end + + def popover_position(position: :right) do + "left-full mx-2 top-0" + end + + def popover_position(position: :left) do + "right-full mx-2 top-0" + end + + def render_popover(assigns, type: :organization) do + ~H""" +
+
+ <.avatar name={@organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@organization.logo, @organization}, :original)} /> +
+

+ <.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @organization.id)}> + <%= @organization.name %> + +

+

+ <%= @organization.description %> +

+
+ """ + end + + def render_popover(assigns, type: :button) do + ~H""" +
+
+

+ <%= @button.name %> +

+

+ <%= @button.description %> +

+
+
+ """ + end +end diff --git a/lib/atomic_web/templates/layout/live.html.heex b/lib/atomic_web/templates/layout/live.html.heex index 5e421b890..340bd600d 100644 --- a/lib/atomic_web/templates/layout/live.html.heex +++ b/lib/atomic_web/templates/layout/live.html.heex @@ -8,7 +8,7 @@
-
+
<%= render("_live_navbar.html", assigns) %>
diff --git a/storybook/components/popover.story.exs b/storybook/components/popover.story.exs new file mode 100644 index 000000000..c53c46908 --- /dev/null +++ b/storybook/components/popover.story.exs @@ -0,0 +1,108 @@ +defmodule AtomicWeb.Storybook.Components.Popover do + use PhoenixStorybook.Story, :component + + alias AtomicWeb.Components.Popover + + def function, do: &Popover.popover/1 + + def variations do + [ + %Variation{ + id: :default, + attributes: %{ + type: :button, + position: :bottom, + button: %{ + name: "Button", + description: "This is a button." + } + }, + slots: [ + """ + <:wrapper> + + + """ + ] + }, + %VariationGroup{ + id: :Positon, + description: "Position", + variations: [ + %Variation{ + id: :bottom, + attributes: %{ + type: :button, + position: :bottom, + button: %{ + name: "Button", + description: "The popover is positioned at the bottom." + } + }, + slots: [ + """ + <:wrapper> + + + """ + ] + }, + %Variation{ + id: :top, + attributes: %{ + type: :button, + position: :top, + button: %{ + name: "Button", + description: "The popover is positioned at the top." + } + }, + slots: [ + """ + <:wrapper> + + + """ + ] + }, + %Variation{ + id: :right, + attributes: %{ + type: :button, + position: :right, + button: %{ + name: "Button", + description: "The popover is positioned at the right." + } + }, + slots: [ + """ + <:wrapper> + + + """ + ] + }, + %Variation{ + id: :left, + attributes: %{ + type: :button, + position: :left, + button: %{ + name: "Button", + description: "The popover is positioned at the left." + } + }, + slots: [ + """ + <:wrapper> + + + """ + ] + } + ] + } + ] + end +end