Current section
Files
Jump to
Current section
Files
lib/components/tabs.ex
defmodule SigmaKit.Components.Tabs do
use Phoenix.LiveComponent
import SigmaKit.Components.Icons, only: [icon: 1]
import SigmaKit.Components.Buttons, only: [dropdown: 1]
@doc """
Renders a tab style navigation bar.
This component does not handle content control, it is meant to be used for
navigation, or with LiveView logic.
"""
attr :id, :string, required: true, doc: "A unique identifier for the tab bar"
attr :event, :string, default: nil, doc: "The event to emit when a tab item is selected"
attr :target, :any, default: nil, doc: "The target for the event"
attr :class, :any, default: nil, doc: "Additional classes to apply to the tab bar"
slot :tab, doc: "Tab items that are always visible on the tab bar" do
attr :icon, :string, doc: "An icon to display on the tab item"
attr :label, :string, doc: "The label of the tab item"
attr :event, :string, doc: "The phx-click event for the tab"
attr :target, :any, doc: "The phx-target for the tab"
attr :id, :any, doc: "the value to send when a tab item is selected"
attr :active, :boolean, doc: "If true the tab will be styled as active"
end
slot :action, doc: "overflow items presented as a dropdown menu" do
attr :label, :string, doc: "The label for the menu item"
attr :event, :string, doc: "The phx-click event for the menu item"
attr :target, :string, doc: "The phx-target for the menu item"
attr :id, :string, doc: "The value for the phx-click event"
attr :icon, :string, doc: "The icon for the menu item"
end
def tabs(assigns) do
~H"""
<div
id={@id}
class={[
"inline-flex gap-2 rounded md:border md:shadow-inner ps-1 md:bg-gray-50 select-none cursor-pointer font-medium text-sm overflow-hidden",
SigmaKit.Util.present?(@action) && "pe-0",
SigmaKit.Util.blank?(@action) && "pe-1",
@class
]}
>
<div class="flex md:hidden">
<.dropdown
id={"#{@id}-mobile"}
label={Map.get(Enum.find(@tab, &Map.get(&1, :active, false)) || %{}, :label, "Section")}
>
<:action
:for={tab <- @tab}
label={tab[:label]}
event={tab[:event] || @event}
target={tab[:target]}
value={tab[:id]}
/>
<:action :if={!Enum.empty?(@action)} divider />
<:action
:for={action <- @action}
label={action[:label]}
event={action[:event]}
target={action[:target]}
icon={action[:icon]}
value={action[:value]}
/>
</.dropdown>
</div>
<div class="hidden md:flex">
<button
:for={tab <- @tab}
type="button"
id={"#{@id}-#{tab[:id]}"}
phx-click={tab[:event] || @event}
phx-value-id={tab[:id]}
phx-target={tab[:target] || assigns[:target]}
class={[
"py-2 px-3 transition-all flex items-center duration-300 font-bold",
tab[:active] &&
"bg-gradient-to-t from-gray-100 to-20% to-white rounded shadow text-primary-600",
!tab[:active] && "hover:text-black text-zinc-600"
]}
>
<.icon :if={tab[:icon]} name={tab[:icon]} class="w-4 h-4 mr-2" />
{tab.label}
</button>
</div>
<.dropdown
:if={SigmaKit.Util.present?(@action)}
icon="hero-ellipsis-horizontal"
id={@id}
class="py-2 bg-white hidden md:block border-l"
>
<:action
:for={action <- @action}
label={action[:label]}
event={action[:event]}
target={action[:target]}
icon={action[:icon]}
value={action[:value]}
/>
</.dropdown>
</div>
"""
end
end