Skip to content
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

feat: popover component #495

Draft
wants to merge 11 commits into
base: develop
Choose a base branch
from
36 changes: 21 additions & 15 deletions lib/atomic_web/components/activity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -13,22 +13,28 @@ defmodule AtomicWeb.Components.Activity do
def activity(assigns) do
~H"""
<div>
<div class="flex space-x-3">
<div class="flex">
<div class="my-auto flex-shrink-0">
<.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={:bottom}>
<: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)} />
</:wrapper>
</.popover>
</div>
<div class="min-w-0 flex-1">
<object>
<.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @activity.organization.id)}>
<span class="text-sm font-medium text-gray-900 hover:underline focus:outline-none">
<%= @activity.organization.name %>
</span>
</.link>
</object>
<p class="text-sm text-gray-500">
<span class="sr-only">Published on</span>
<time><%= relative_datetime(@activity.inserted_at) %></time>
</p>
<div class="ml-3">
<div class="min-w-0 flex-1">
<object>
<.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @activity.organization.id)}>
<span class="text-sm font-medium text-gray-900 hover:underline focus:outline-none">
<%= @activity.organization.name %>
</span>
</.link>
</object>
<p class="text-sm text-gray-500">
<span class="sr-only">Published on</span>
<time><%= relative_datetime(@activity.inserted_at) %></time>
</p>
</div>
</div>
</div>
<h2 class="mt-3 text-base font-semibold text-gray-900"><%= @activity.title %></h2>
Expand Down
36 changes: 21 additions & 15 deletions lib/atomic_web/components/announcement.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
<div>
<div class="flex space-x-3">
<div class="flex">
<div class="my-auto flex-shrink-0">
<.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)} />
</:wrapper>
</.popover>
</div>
<div class="min-w-0 flex-1">
<object>
<.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @announcement.organization.id)} class="hover:underline focus:outline-none">
<p class="text-sm font-medium text-gray-900">
<%= @announcement.organization.name %>
</p>
</.link>
</object>
<p class="text-sm text-gray-500">
<span class="sr-only">Published on</span>
<time><%= relative_datetime(@announcement.inserted_at) %></time>
</p>
<div class="ml-3">
<div class="min-w-0 flex-1">
<object>
<.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @announcement.organization.id)} class="hover:underline focus:outline-none">
<p class="text-sm font-medium text-gray-900">
<%= @announcement.organization.name %>
</p>
</.link>
</object>
<p class="text-sm text-gray-500">
<span class="sr-only">Published on</span>
<time><%= relative_datetime(@announcement.inserted_at) %></time>
</p>
</div>
</div>
</div>
<h2 class="mt-3 text-base font-semibold text-gray-900"><%= @announcement.title %></h2>
Expand Down
96 changes: 96 additions & 0 deletions lib/atomic_web/components/popover.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
defmodule AtomicWeb.Components.Popover do
@moduledoc """
Renders a popover.
"""

use AtomicWeb, :component

import AtomicWeb.Components.Avatar

attr :type, :atom,
values: [:user, :organization],
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."

slot :wrapper,
required: true,
doc: "Slot to be rendered as a wrapper of the popover. For example, a avatar."

def popover(assigns) do
~H"""
<div class="group relative h-min">
<%= render_slot(@wrapper) %>
<div class={[
"hidden z-50 group-hover:block transition delay-700 duration-300 ease-in-out",
triangle_class(position: @position)
]}>
<div class={[
"absolute z-50 w-64 bg-slate-50 border border-gray-200 rounded-lg shadow-md hidden group-hover:block transition delay-700 duration-300 group-hover:ease-in-out",
popover_position(position: @position)
]}>
<%= render_popover(assigns, type: @type) %>
</div>
</div>
</div>
"""
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"""
<div class="relative p-3">
<div class="mb-2 mb-4 flex items-center justify-between">
<.avatar name={@organization.name} color={:light_gray} class="!h-10 !w-10" size={:xs} type={:organization} src={Uploaders.Logo.url({@organization.logo, @organization}, :original)} />
</div>
<p class="text-base font-semibold leading-none text-gray-900 dark:text-white">
<.link navigate={Routes.organization_show_path(AtomicWeb.Endpoint, :show, @organization.id)}>
<%= @organization.name %>
</.link>
</p>
<p class="text-sm text-gray-500 dark:text-gray-400">
<%= @organization.description %>
</p>
</div>
<div data-popper-arrow></div>
"""
end
end
2 changes: 1 addition & 1 deletion lib/atomic_web/templates/layout/live.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<div class="flex relative flex-col min-h-screen">
<div class="flex flex-col mx-auto w-full lg:flex-row xl:px-8 max-w-[1380px]">
<!-- Navbar -->
<div class="relative flex-shrink-0 lg:w-72 lg:flex lg:max-w-[400px]">
<div class="relative flex-shrink-0 z-0 lg:w-72 lg:flex lg:max-w-[400px]">
<%= render("_live_navbar.html", assigns) %>
</div>
<!-- Central content -->
Expand Down
Loading