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: Update variants in Button and IconButton, incl additional changes [MDS-683] #715

Merged
merged 5 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/moon/design/alert/close.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule Moon.Design.Alert.Close do
size="xs"
variant="ghost"
class={merge(["absolute top:4 text-moon-16 text-bulma", @class])}
icon_only="controls_close"
icon="controls_close"
on_click={@on_click}
{=@id}
{=@testid}
Expand Down
2 changes: 1 addition & 1 deletion lib/moon/design/breadcrumb/collapsed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ defmodule Moon.Design.Breadcrumb.Collapsed do
>
<IconButton
variant="ghost"
icon_only={@collapsed_icon || "other3_dots_horizontal"}
icon={@collapsed_icon || "other3_dots_horizontal"}
size="xs"
on_click={JS.dispatch("moon:toggle-collapsed-breadcrumbs", detail: %{breacrumb_flyout_id: "#{@id}_flyout"})}
/>
Expand Down
145 changes: 91 additions & 54 deletions lib/moon/design/button.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,59 @@ defmodule Moon.Design.Button do
alias Moon.Icon
alias Moon.Design.Loader

@doc "Visual/Logical variant of button. Please use \"fill\", \"outline\", \"ghost\" instead of \"primary\", \"secondary\", \"tertiary\" "
prop(variant, :string,
values: ["primary", "secondary", "tertiary", "ghost"],
default: "primary"
values: ["fill", "outline", "ghost", "primary", "secondary", "tertiary"],
default: "fill"
)

@doc "Size of button"
prop(size, :string, values: ["xs", "sm", "md", "lg", "xl"], default: "md")
@doc "Rendered HTML element"
prop(as, :string, values!: ~w(a button), default: "button")
@doc "A href attribute when prop as=\"a\""
prop(href, :string)
@doc "Full width button"
prop(full_width, :boolean)
@doc "Disabled button"
prop(disabled, :boolean)
@doc "Animation of button"
prop(animation, :string, values: ~w(progress success error pulse))
@doc "Additional Tailwind classes"
prop(class, :css_class)
@doc "Additional Tailwind classes for hover background"
prop(hover_bg_class, :css_class)
@doc "Type attribute for DOM element"
prop(type, :string, default: "button")
@doc "Form attribute for DOM element"
prop(form, :string)
@doc "On click event"
prop(on_click, :event)
@doc "list of additional values to associate with the DOM element"
prop(values, :keyword, default: [])
@doc "Value attribute for DOM element"
prop(value, :string)
@doc "Left icon"
prop(left_icon, :string)
@doc "Right icon"
prop(right_icon, :string)
prop(button_gap, :css_class, default: "gap-2")
@doc "Id attribute for DOM element"
prop(id, :string)
@doc "Data-testid attribute for DOM element"
prop(testid, :string)
@doc "Additional attributes for DOM element"
prop(attrs, :keyword, default: [])
@doc "Aria label attribute for DOM element"
prop(aria_label, :string)

@doc "Target attribute for DOM element"
prop(target, :string)
@doc "Rel attribute for DOM element"
prop(rel, :string)

@doc "Inner content of the component"
slot(default)
@doc "Right icon slot"
slot(right_icon_slot)
@doc "Left icon slot"
slot(left_icon_slot)

def render(assigns) do
Expand All @@ -49,19 +71,19 @@ defmodule Moon.Design.Button do
{=@id}
class={merge([
[
"flex row justify-center items-center gap-2 relative overflow-hidden active:scale-90 transition-all duration-200 font-semibold group z-0",
"flex row justify-center items-center relative overflow-hidden active:scale-90 transition-all duration-200 font-semibold group z-0",
"whitespace-nowrap select-none",
Utils.get_button_size_classes(@size),
"#{Utils.get_no_icon_padding(@size)}": !@right_icon && !@left_icon,
"#{Utils.get_right_icon_paddings(@size)}": @right_icon && !@full_width,
"#{Utils.get_left_icon_paddings(@size)}": @left_icon && !@full_width,
"#{Utils.get_full_width_padding(@size)}": @full_width,
"text-goten bg-piccolo": @variant in ["primary"],
"w-full": @full_width,
"text-goten bg-piccolo": @variant in ["primary", "fill"],
"border border-solid bg-transparent text-bulma border-trunks hover:border-bulma":
@variant in ["secondary"],
@variant in ["secondary", "outline"],
"bg-hit text-goten": @variant in ["tertiary"],
"bg-none text-trunks hover:text-bulma": @variant in ["ghost"],
"w-full": @full_width,
"opacity-60 cursor-not-allowed active:transform-none": @disabled,
"anim-pulse animate-[pulse2_1.5s_infinite]": @animation == "pulse",
"bg-chichi text-goten animate-[error_0.82s_cubic-bezier(0.36,0.07,0.19,0.97)_1_both] anim-error":
Expand All @@ -83,52 +105,67 @@ defmodule Moon.Design.Button do
"data-size": @size
] ++ @attrs}
>
<span
:if={@animation in ["success", "progress"]}
class="flex absolute top-1/2 left-1/2 translate-y-[-50%] translate-x-[-50%] content-center justify-center"
>
{#if @animation == "progress"}
<Loader color="currentColor" size={if @size == "xs", do: "2xs", else: "xs"} />
{#elseif @animation == "success"}
<Icon name="generic_check_alternative" color="currentColor" class={Utils.icon_class(@size)} />
{/if}
</span>
<span class={
"flex justify-center items-center",
@button_gap,
"opacity-0": @animation in ["success", "progress"]
}>
{#if slot_assigned?(:left_icon_slot)}
<#slot {@left_icon_slot} />
{#else}
<Icon
name={@left_icon}
class={
Utils.icon_class(@size),
"#{Utils.left_icon_horizontal_position(@size)}": @full_width
}
:if={@left_icon}
/>
{/if}
<#slot />
{#if slot_assigned?(:right_icon_slot)}
<#slot {@right_icon_slot} />
{#else}
<Icon
name={@right_icon}
class={
Utils.icon_class(@size),
"#{Utils.right_icon_horizontal_position(@size)}": @full_width
}
:if={@right_icon}
/>
{/if}
</span>
<span class={merge([
"block absolute inset-0 pointer-events-none bg-transparent transition-[background-color_0.2s_ease-in-out z-[-1] group-hover:bg-heles",
@hover_bg_class
])} />
{#if @animation}
{animation_content(assigns)}
<span class={"flex gap-2 items-center", "opacity-0": @animation in ["success", "progress"]}>
{content(assigns)}
</span>
{#else}
{content(assigns)}
{/if}
<span class={merge(hover_overlay_classes() ++ [@hover_bg_class])} />
</AsComponent>
"""
end

defp animation_content(assigns) do
~F"""
<span
:if={@animation in ["success", "progress"]}
class="flex absolute top-1/2 left-1/2 translate-y-[-50%] translate-x-[-50%] content-center justify-center"
>
{#if @animation == "progress"}
<Loader color="currentColor" size={if @size == "xs", do: "2xs", else: "xs"} />
{#elseif @animation == "success"}
<Icon name="generic_check_alternative" color="currentColor" class={Utils.icon_class(@size)} />
{/if}
</span>
"""
end

defp content(assigns) do
~F"""
{#if slot_assigned?(:left_icon_slot)}
<#slot {@left_icon_slot} />
{#else}
<Icon
name={@left_icon}
class={
Utils.icon_class(@size),
"#{Utils.left_icon_horizontal_position(@size)}": @full_width
}
:if={@left_icon}
/>
{/if}
<#slot />
{#if slot_assigned?(:right_icon_slot)}
<#slot {@right_icon_slot} />
{#else}
<Icon
name={@right_icon}
class={
Utils.icon_class(@size),
"#{Utils.right_icon_horizontal_position(@size)}": @full_width
}
:if={@right_icon}
/>
{/if}
"""
end

defp hover_overlay_classes() do
[
"block absolute inset-0 pointer-events-none bg-transparent transition-[background-color_0.2s_ease-in-out z-[-1] group-hover:bg-heles"
]
end
end
111 changes: 77 additions & 34 deletions lib/moon/design/button/icon_button.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,54 @@ defmodule Moon.Design.Button.IconButton do
alias Moon.Design.Loader
alias Moon.Design.Button.Utils

@doc "Visual/Logical variant of button. Please use \"fill\", \"outline\", \"ghost\" instead of \"primary\", \"secondary\", \"tertiary\" "
prop(variant, :string,
values: ["primary", "secondary", "tertiary", "ghost"],
default: "primary"
values: ["fill", "outline", "ghost", "primary", "secondary", "tertiary"],
default: "fill"
)

@doc "Size of button"
prop(size, :string, values: ["xs", "sm", "md", "lg", "xl"], default: "md")
@doc "Rendered HTML element"
prop(as, :string, values!: ~w(a button), default: "button")
@doc "A href attribute when prop as=\"a\""
prop(href, :string)
prop(size, :string, values: ["xs", "sm", "md", "lg", "xl"], default: "md")
@doc "Disabled button"
prop(disabled, :boolean)
@doc "Animation of button"
prop(animation, :string, values: ~w(progress success error pulse))
@doc "Additional Tailwind classes"
prop(class, :css_class)

@doc "Icon. To be deprecated. Use prop \"icon\" instead."
prop(icon_only, :string)

@doc "Icon"
prop(icon, :string)
@doc "Additional Tailwind classes for hover background"
prop(hover_bg_class, :css_class)
@doc "Type attribute for DOM element"
prop(type, :string, default: "button")
@doc "Form attribute for DOM element"
prop(form, :string)
@doc "On click event"
prop(on_click, :event)
@doc "list of additional values to associate with the DOM element"
prop(values, :keyword, default: [])
@doc "Value attribute for DOM element"
prop(value, :string)
@doc "Id attribute for DOM element"
prop(id, :string)
@doc "Data-testid attribute for DOM element"
prop(testid, :string)
@doc "Additional attributes for DOM element"
prop(attrs, :keyword, default: [])
@doc "Aria label attribute for DOM element"
prop(aria_label, :string)

@doc "Target attribute for DOM element"
prop(target, :string)
@doc "Rel attribute for DOM element"
prop(rel, :string)

prop(id, :string)
prop(testid, :string)
@doc "Slot for customizations"
slot(default)

def render(assigns) do
~F"""
Expand All @@ -45,9 +67,9 @@ defmodule Moon.Design.Button.IconButton do
[
"flex row justify-center items-center gap-2 relative overflow-hidden active:scale-90 transition-all duration-200 select-none font-semibold group z-0",
get_icon_button_size_classes(@size),
"text-goten bg-piccolo": @variant in ["primary"],
"text-goten bg-piccolo": @variant in ["primary", "fill"],
"border border-solid bg-transparent text-bulma border-trunks hover:border-bulma":
@variant in ["secondary"],
@variant in ["secondary", "outline"],
"bg-hit text-goten": @variant in ["tertiary"],
"bg-none text-trunks hover:text-bulma": @variant in ["ghost"],
"opacity-60 cursor-not-allowed active:transform-none": @disabled,
Expand All @@ -64,41 +86,62 @@ defmodule Moon.Design.Button.IconButton do
{=@value}
{=@target}
{=@rel}
attrs={
attrs={[
disabled: @disabled,
type: @type,
form: @form,
"data-size": @size
}
] ++ @attrs}
>
<span
:if={@animation in ["success", "progress"]}
class="flex absolute top-1/2 left-1/2 translate-y-[-50%] translate-x-[-50%] content-center justify-center"
>
{#if @animation == "progress"}
<Loader color="currentColor" size={if @size == "xs", do: "2xs", else: "xs"} />
{#elseif @animation == "success"}
<Icon name="generic_check_alternative" color="currentColor" class={Utils.icon_class(@size)} />
{#if @animation}
{animation_content(assigns)}
<span class={"flex justify-center items-center", "opacity-0": @animation in ["success", "progress"]}>
{#if @icon_only || @icon}
<Icon name={@icon_only || @icon} class={Utils.icon_class(@size)} />
{#else}
<#slot />
{/if}
</span>
{#else}
{#if @icon_only || @icon}
<Icon name={@icon_only || @icon} class={Utils.icon_class(@size)} />
{#else}
<#slot />
{/if}
</span>
<span class={
"flex justify-center items-center",
"opacity-0": @animation in ["success", "progress"]
}>
<Icon name={@icon_only} class={Utils.icon_class(@size)} />
</span>
<span class="block absolute inset-0 pointer-events-none bg-transparent transition-[background-color_0.2s_ease-in-out z-[-1] group-hover:bg-heles" />
{/if}
<span class={merge(hover_overlay_classes() ++ [@hover_bg_class])} />
</AsComponent>
"""
end

def get_icon_button_size_classes(size) do
case size do
"xs" -> "text-moon-12 rounded-moon-s-xs h-6 p-1"
"sm" -> "text-moon-14 rounded-moon-s-sm h-8 p-1"
"md" -> "text-moon-14 rounded-moon-s-sm h-10 p-2"
"lg" -> "text-moon-16 rounded-moon-s-sm h-12 p-3"
"xl" -> "text-moon-16 rounded-moon-s-md h-14 p-4"
"xs" -> "text-moon-12 rounded-moon-s-xs h-6 w-6 p-1"
"sm" -> "text-moon-14 rounded-moon-s-sm h-8 w-8 p-1"
"md" -> "text-moon-14 rounded-moon-s-sm h-10 w-10 p-2"
"lg" -> "text-moon-16 rounded-moon-s-sm h-12 w-12 p-3"
"xl" -> "text-moon-16 rounded-moon-s-md h-14 w-14 p-4"
end
end

defp animation_content(assigns) do
~F"""
<span
:if={@animation in ["success", "progress"]}
class="flex absolute top-1/2 left-1/2 translate-y-[-50%] translate-x-[-50%] content-center justify-center"
>
{#if @animation == "progress"}
<Loader color="currentColor" size={if @size == "xs", do: "2xs", else: "xs"} />
{#elseif @animation == "success"}
<Icon name="generic_check_alternative" color="currentColor" class={Utils.icon_class(@size)} />
{/if}
</span>
"""
end

defp hover_overlay_classes() do
[
"block absolute inset-0 pointer-events-none bg-transparent transition-[background-color_0.2s_ease-in-out z-[-1] group-hover:bg-heles"
]
end
end
10 changes: 5 additions & 5 deletions lib/moon/design/button/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ defmodule Moon.Design.Button.Utils do

def get_button_size_classes(size) do
case size do
"xs" -> "text-moon-12 rounded-moon-s-xs h-6"
"sm" -> "text-moon-14 rounded-moon-s-sm h-8"
"md" -> "text-moon-14 rounded-moon-s-sm h-10"
"lg" -> "text-moon-16 rounded-moon-s-sm h-12"
"xl" -> "text-moon-16 rounded-moon-s-md h-14"
"xs" -> "text-moon-12 rounded-moon-s-xs h-6 gap-1"
"sm" -> "text-moon-14 rounded-moon-s-sm h-8 gap-1"
"md" -> "text-moon-14 rounded-moon-s-sm h-10 gap-2"
"lg" -> "text-moon-16 rounded-moon-s-sm h-12 gap-2"
"xl" -> "text-moon-16 rounded-moon-s-md h-14 gap-2"
end
end

Expand Down
Loading