diff --git a/lib/claper_web.ex b/lib/claper_web.ex
index 82c232e..c03cb5e 100644
--- a/lib/claper_web.ex
+++ b/lib/claper_web.ex
@@ -112,6 +112,7 @@ defmodule ClaperWeb do
# Import design system components
import ClaperWeb.Component.Button
import ClaperWeb.Component.Badge
+ import ClaperWeb.Component.Tabs
unquote(verified_routes())
end
diff --git a/lib/claper_web/views/components/tabs_component.ex b/lib/claper_web/views/components/tabs_component.ex
new file mode 100644
index 0000000..54c7053
--- /dev/null
+++ b/lib/claper_web/views/components/tabs_component.ex
@@ -0,0 +1,157 @@
+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 :class, :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 :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 p-0.5 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-4 py-1.5 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-bold"
+ end
+
+ defp tab_state_classes(:boxed, false) do
+ "text-gray-500 hover:text-gray-700 bg-transparent"
+ end
+end