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

[MDS-342] Popover v2 #515

Merged
merged 17 commits into from
Feb 3, 2023
1 change: 1 addition & 0 deletions lib/moon/design/button.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ defmodule Moon.Design.Button do
prop(testid, :string)
prop(on_click, :event)
prop(values, :keyword, default: [])
prop(close, :event)

prop(left_icon, :string)
prop(right_icon, :string)
Expand Down
38 changes: 38 additions & 0 deletions lib/moon/design/popover.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule Moon.Design.Popover do
@moduledoc false

use Moon.StatefulComponent

prop(on_click, :event)
prop(is_open, :boolean, default: false)
prop(testid, :string)

slot(default, required: true)
slot(trigger, required: true)

def render(assigns) do
~F"""
<div class="relative" :on-click={@on_click || "toggle_open"} :on-click-away="close_panel">
<div role="button">
<#slot {@trigger} />
</div>
<div
aria-expanded={[if(@is_open == false, do: "false", else: "true")]}
class={"transition-opacity transition-200", hidden: @is_open == false}
data-testid={"#{@testid}-popover-panel"}
>
<#slot />
</div>
</div>
"""
end

def handle_event("toggle_open", _, socket) do
{:noreply, assign(socket, is_open: !socket.assigns.is_open)}
end

def handle_event("close_panel", _, socket) do
socket = assign(socket, is_open: false)
{:noreply, socket}
end
end
52 changes: 52 additions & 0 deletions lib/moon/design/popover/panel.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule Moon.Design.Popover.Panel do
@moduledoc false

use Moon.StatelessComponent, slot: "default"

prop(class, :css_class)

prop(position, :string,
values!: [
"top-start",
"top",
"top-end",
"bottom-start",
"bottom",
"bottom-end",
"right-start",
"right",
"right-end",
"left-start",
"left",
"left-end"
],
default: "top"
)

slot(default, required: true)

def render(assigns) do
~F"""
<div class={merge([
[
"absolute z-[9999999] overflow-y-auto rounded-moon-i-md box-border bg-gohan shadow-moon-lg",
"left-full top-1/2 ml-2 -translate-y-1/2": @position == "right",
"left-full top-0 ml-2": @position == "right-start",
"left-full bottom-0 ml-2": @position == "right-end",
"right-full top-1/2 mr-2 -translate-y-1/2": @position == "left",
"right-full top-0 mr-2": @position == "left-start",
"right-full bottom-0 mr-2": @position == "left-end",
"top-full left-1/2 mt-2 -translate-x-1/2": @position == "bottom",
"top-full left-0 mt-2": @position == "bottom-start",
"top-full right-0 mt-2": @position == "bottom-end",
"bottom-full left-1/2 mb-2 -translate-x-1/2": @position == "top",
"bottom-full left-0 mb-2": @position == "top-start",
"bottom-full right-0 mb-2": @position == "top-end"
],
@class
])}>
<#slot />
</div>
"""
end
end
5 changes: 5 additions & 0 deletions lib/moon/design/popover/trigger.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule Moon.Design.Popover.Trigger do
@moduledoc false

use Surface.Component, slot: "trigger"
end
2 changes: 1 addition & 1 deletion lib/moon_web/components/breadcrumbs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule MoonWeb.Components.Breadcrumbs do

use MoonWeb, :stateless_component

alias Moon.Components.Breadcrumb, as: BreadCrumbsComponent
alias Moon.Design.Breadcrumb, as: BreadCrumbsComponent

prop(breadcrumbs, :any)
prop(theme_name, :string, default: "lab-light")
Expand Down
13 changes: 13 additions & 0 deletions lib/moon_web/components/component_anatomy.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule MoonWeb.Components.ComponentAnatomy do
@moduledoc false

use MoonWeb, :stateless_component

slot(default)

def render(assigns) do
~F"""
<pre class="flex w-full p-4 bg-goku rounded-moon-s-sm overflow-scroll text-moon-14 text-bulma whitespace-pre-line"><code><#slot /></code></pre>
"""
end
end
2 changes: 1 addition & 1 deletion lib/moon_web/components/example_and_code.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule MoonWeb.Components.ExampleAndCode do
~F"""
<section class={"flex flex-col gap-6", @class}>
<PreviewCodeButton title={@title} selected_button={@selected_button} click="toggle" />
<div class="my-2 text-moon-14" :if={slot_assigned?(:note)}>
<div class="text-moon-16" :if={slot_assigned?(:note)}>
<p><#slot {@note} /></p>
</div>
Expand Down
23 changes: 23 additions & 0 deletions lib/moon_web/components/examples_list.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule MoonWeb.Components.ExamplesList do
@moduledoc false

use Moon.StatelessComponent

import Moon.Helpers.MoonRender

alias MoonWeb.Components.ExampleAndCode

prop(examples, :list, default: [])

def render(assigns) do
~F"""
{#for module <- @examples}
<ExampleAndCode title={"#{module}" |> String.split(".") |> Enum.at(-1)} id={"example-#{module}"}>
<:example><.moon {=module} /></:example>
<:code>{(Kernel.function_exported?(module, :code, 0) && module.code()) || ""}</:code>
<:note>{(Kernel.function_exported?(module, :note, 0) && module.note()) || ""}</:note>
</ExampleAndCode>
{/for}
"""
end
end
1 change: 1 addition & 0 deletions lib/moon_web/components/left_menu.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ defmodule MoonWeb.Components.LeftMenu do
<SidebarLink route={Pages.Design.LoaderPage}>Loader</SidebarLink>
<SidebarLink route={Pages.Design.MenuItemPage}>MenuItem</SidebarLink>
<SidebarLink route={Pages.Design.ModalPage}>Modal</SidebarLink>
<SidebarLink route={Pages.Design.PopoverPage}>Popover</SidebarLink>
<SidebarLink route={Pages.Design.TablePage}>Table</SidebarLink>
<SidebarLink route={Pages.Design.TabsPage}>Tabs</SidebarLink>
<SidebarLink route={Pages.Design.TooltipPage}>Tooltip</SidebarLink>
Expand Down
107 changes: 107 additions & 0 deletions lib/moon_web/examples/design/popover_example/default.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
defmodule MoonWeb.Examples.Design.PopoverExample.Default do
@moduledoc false

use Moon.StatelessComponent

alias Moon.Design.Popover
alias Moon.Design.Button
alias Moon.Design.MenuItem

alias Moon.Components.Lego

alias Moon.Icons.{
GenericTrophy,
MediaTuner,
MediaMegaphone
}

def render(assigns) do
~F"""
<Popover id="popover_id_1">
<Popover.Trigger>
<Button>Toggle Popover</Button>
</Popover.Trigger>
<Popover.Panel>
<div class="p-6 flex flex-col gap-6">
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center rounded-lg">
<GenericTrophy class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Tournaments">
Best tournaments with streamers
</Lego.MultiTitle>
</MenuItem>
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center">
<MediaMegaphone class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Promotions">
Your favourite games
</Lego.MultiTitle>
</MenuItem>
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center">
<MediaTuner class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Providers">
Your favourite games
</Lego.MultiTitle>
</MenuItem>
</div>
</Popover.Panel>
</Popover>
"""
end

def code() do
"""
alias Moon.Design.Popover
alias Moon.Design.Button
alias Moon.Design.MenuItem

alias Moon.Components.Lego

alias Moon.Icons.{
GenericTrophy,
MediaTuner,
MediaMegaphone
}

...

<Popover id="popover_id_1">
<Popover.Trigger>
<Button>Toggle Popover</Button>
</Popover.Trigger>
<Popover.Panel>
<div class="p-6 flex flex-col gap-6">
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center rounded-lg">
<GenericTrophy class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Tournaments">
Best tournaments with streamers
</Lego.MultiTitle>
</MenuItem>
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center">
<MediaMegaphone class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Promotions">
Your favourite games
</Lego.MultiTitle>
</MenuItem>
<MenuItem>
<span class="flex w-11 h-11 bg-goku items-center justify-center">
<MediaTuner class="text-bulma text-[1.5rem]" />
</span>
<Lego.MultiTitle title="Providers">
Your favourite games
</Lego.MultiTitle>
</MenuItem>
</div>
</Popover.Panel>
</Popover>
"""
end
end
85 changes: 85 additions & 0 deletions lib/moon_web/examples/design/popover_example/position.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule MoonWeb.Examples.Design.PopoverExample.Position do
@moduledoc false

use Moon.StatelessComponent

alias Moon.Design.Popover
alias Moon.Design.Button

import MoonWeb.Helpers.Lorem

prop(placemets, :list,
default: [
"top-start",
"top",
"top-end",
"bottom-start",
"bottom",
"bottom-end",
"right-start",
"right",
"right-end",
"left-start",
"left",
"left-end"
]
)

def render(assigns) do
~F"""
{#for placement <- @placemets}
<Popover id={"popover-ex-#{placement}"}>
<Popover.Trigger>
<Button variant="secondary">{placement}</Button>
</Popover.Trigger>
<Popover.Panel position={placement} class="w-[300px]">
<p class="p-4 text-moon-14">
I'm a {placement} popover
</p>
<p class="p-4 text-moon-14">{lorem()}</p>
</Popover.Panel>
</Popover>
{/for}
"""
end

def code() do
"""
alias Moon.Design.Popover
alias Moon.Design.Button

prop(placemets, :list, default: [
"top-start",
"top",
"top-end",
"bottom-start",
"bottom",
"bottom-end",
"right-start",
"right",
"right-end",
"left-start",
"left",
"left-end"
])

...

{#for placement <- @placemets}
<Popover id={"popover-ex-\#{placement}"}>
<Popover.Trigger>
<Button variant="secondary">{placement}</Button>
</Popover.Trigger>
<Popover.Panel position={placement} class="w-[300px]">
<p class="p-4 text-moon-14">
I'm a {placement} popover
</p>
<p class="p-4 text-moon-14">#{lorem()}</p>
</Popover.Panel>
</Popover>
{/for}
"""
end

def note(), do: "The complete list of all possible positions is in the props table below."
end
Loading