defmodule RiverConnectWeb.Components.UI.HoverCard do @moduledoc """ Implementation of hover card component with positioning and hover interactions. When a user hovers over the trigger element, the content card appears with a small delay. The card disappears when the user moves away from both the trigger and the content. ## Examples: <.hover_card id="user-hover-card"> <.hover_card_trigger> <.button variant="link">@salad_ui <.hover_card_content>
SaladUI
@salad_ui

UI component library for modern web applications.

""" use RiverConnectWeb.Components.UI, :component @doc """ The main hover card component that manages state and positioning. ## Options * `:id` - Required unique identifier for the hover card. * `:open-delay` - Delay in milliseconds before opening the hover card. Defaults to `300`. * `:close-delay` - Delay in milliseconds before closing the hover card. Defaults to `200`. * `:on-open` - Handler for hover card open event. * `:on-close` - Handler for hover card close event. * `:class` - Additional CSS classes. """ attr :id, :string, required: true, doc: "Unique identifier for the hover card" attr :"open-delay", :integer, default: 300, doc: "Delay in milliseconds before opening the hover card" attr :"close-delay", :integer, default: 200, doc: "Delay in milliseconds before closing the hover card" attr :"on-open", :any, default: nil, doc: "Handler for hover card open event" attr :"on-close", :any, default: nil, doc: "Handler for hover card close event" attr :class, :string, default: nil attr :rest, :global slot :inner_block, required: true def hover_card(assigns) do # Collect event mappings event_map = %{} |> add_event_mapping(assigns, "opened", :"on-open") |> add_event_mapping(assigns, "closed", :"on-close") assigns = assigns |> assign(:event_map, Jason.encode!(event_map)) |> assign( :options, Jason.encode!(%{ openDelay: assigns[:"open-delay"], closeDelay: assigns[:"close-delay"], animations: get_animation_config() }) ) ~H"""
{render_slot(@inner_block)}
""" end @doc """ The trigger element that activates the hover card when hovered. """ attr :class, :string, default: nil attr :rest, :global slot :inner_block, required: true def hover_card_trigger(assigns) do ~H"""
{render_slot(@inner_block)}
""" end @doc """ The hover card content that appears when triggered. ## Options * `:side` - Placement of the hover card relative to the trigger (top, right, bottom, left). Defaults to `"top"`. * `:align` - Alignment of the hover card (start, center, end). Defaults to `"center"`. * `:side-offset` - Distance from the trigger in pixels. Defaults to `4`. * `:align-offset` - Offset along the alignment axis. Defaults to `0`. * `:class` - Additional CSS classes. """ attr :class, :string, default: nil attr :side, :string, values: ~w(top right bottom left), default: "top" attr :align, :string, values: ~w(start center end), default: "center" attr :"side-offset", :integer, default: 8, doc: "Distance from the trigger in pixels" attr :"align-offset", :integer, default: 0, doc: "Offset along the alignment axis" attr :rest, :global slot :inner_block, required: true def hover_card_content(assigns) do assigns = assign(assigns, side_offset: assigns[:"side-offset"], align_offset: assigns[:"align-offset"] ) ~H""" """ end defp get_animation_config do %{ "open_to_closed" => %{ duration: 130, target_part: "content" } } end end