defmodule ClaperWeb.Component.Tabs do
@moduledoc """
DaisyUI-inspired Tabs component for Claper.
## Styles
- `:bordered` - Simple tabs with bottom border on active (default)
- `:lifted` - Lifted appearance with border on sides and top for active
- `:boxed` - Pill-shaped tabs with background, active has primary fill
## Examples
<.tabs>
<:tab>Tab 1
<:tab active>Tab 2
<:tab>Tab 3
<.tabs style={:boxed}>
<:tab>Home
<:tab active>Profile
<:tab>Settings
<.tabs style={:lifted}>
<:tab>Overview
<:tab active>Details
<:tab>History
## With click handlers
<.tabs style={:boxed}>
<:tab active={@active_tab == "home"} phx-click="set_tab" phx-value-tab="home">Home
<:tab active={@active_tab == "profile"} phx-click="set_tab" phx-value-tab="profile">Profile
"""
use ClaperWeb, :view_component
attr :style, :atom, default: :bordered, values: [:bordered, :lifted, :boxed]
attr :class, :string, default: nil
attr :rest, :global
slot :tab, required: true do
attr :active, :boolean
attr :disabled, :boolean
attr :class, :string
attr :"phx-click", :string
attr :"phx-target", :string
attr :"phx-value-tab", :string
end
def tabs(assigns) do
~H"""
<%= for {tab, _index} <- Enum.with_index(@tab) do %>
<% end %>
"""
end
@doc """
Renders a single tab item. Use this for more control over individual tabs.
## Examples
<.tab_item active>Active Tab
<.tab_item phx-click="change_tab">Inactive Tab
"""
attr :style, :atom, default: :bordered, values: [:bordered, :lifted, :boxed]
attr :active, :boolean, default: false
attr :disabled, :boolean, default: false
attr :class, :string, default: nil
attr :rest, :global, include: ~w(phx-click phx-target phx-value-tab)
slot :inner_block, required: true
def tab_item(assigns) do
~H"""
"""
end
# Container classes based on style
defp container_classes(:bordered) do
"flex items-center border-b border-gray-200"
end
defp container_classes(:lifted) do
"flex items-end"
end
defp container_classes(:boxed) do
"inline-flex items-center bg-gray-100 rounded-full"
end
# Base tab classes based on style
defp tab_base_classes(:bordered) do
"px-4 py-1.5 text-sm font-normal font-display transition-all duration-200 rounded-t-lg -mb-px"
end
defp tab_base_classes(:lifted) do
"px-4 py-1.5 text-sm font-normal font-display transition-all duration-200 rounded-t-lg border-b border-gray-200"
end
defp tab_base_classes(:boxed) do
"px-5 py-3 text-sm font-normal font-display transition-all duration-200 rounded-full"
end
# Tab state classes (active/inactive) based on style
defp tab_state_classes(:bordered, true) do
"text-gray-800 border-b-2 border-gray-800 font-medium"
end
defp tab_state_classes(:bordered, false) do
"text-gray-500 hover:text-gray-700 border-b-2 border-transparent"
end
defp tab_state_classes(:lifted, true) do
"text-gray-800 bg-white border-l border-r border-t border-gray-200 border-b-0 -mb-px"
end
defp tab_state_classes(:lifted, false) do
"text-gray-500 hover:text-gray-700 bg-transparent"
end
defp tab_state_classes(:boxed, true) do
"text-white bg-primary-500 font-semibold"
end
defp tab_state_classes(:boxed, false) do
"text-gray-500 hover:text-gray-700 bg-transparent"
end
# Disabled classes
defp disabled_classes(true), do: "opacity-50 cursor-not-allowed"
defp disabled_classes(false), do: "cursor-pointer"
end