defmodule RiverConnectWeb.Components.UI.Sheet do
@moduledoc """
Implementation of Sheet component for SaladUI framework.
Sheets are like dialogs that appear from the edge of the screen. They can be configured
to slide in from different sides of the viewport.
## Examples:
<.sheet id="user-sheet">
<.sheet_trigger>
<.button variant="outline">Open Sheet
<.sheet_content side="right">
<.sheet_header>
<.sheet_title>Edit profile
<.sheet_description>
Make changes to your profile here. Click save when you're done.
<.sheet_footer>
<.button type="submit">Save changes
"""
use RiverConnectWeb.Components.UI, :component
@doc """
The main sheet component that manages state and positioning.
## Options
* `:id` - Required unique identifier for the sheet.
* `:open` - Whether the sheet is initially open. Defaults to `false`.
* `:on-open` - Handler for sheet open event.
* `:on-close` - Handler for sheet close event.
* `:class` - Additional CSS classes.
"""
attr :id, :string, required: true, doc: "Unique identifier for the sheet"
attr :open, :boolean, default: false, doc: "Whether the sheet is initially open"
attr :class, :string, default: nil
attr :"close-on-outside-click", :boolean, default: true
attr :"on-open", :any, default: nil, doc: "Handler for sheet open event"
attr :"on-close", :any, default: nil, doc: "Handler for sheet close event"
attr :rest, :global
slot :inner_block, required: true
def sheet(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, json(event_map))
|> assign(:initial_state, if(assigns.open, do: "open", else: "closed"))
|> assign(
:options,
json(%{
animations: get_animation_config(),
closeOnOutsideClick: assigns[:"close-on-outside-click"]
})
)
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
The trigger element that opens the sheet.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_trigger(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
The sheet content that appears when triggered.
## Options
* `:side` - The side from which the sheet appears (top, right, bottom, left). Defaults to `"right"`.
* `:class` - Additional CSS classes to customize dimensions and appearance.
"""
attr :class, :string, default: nil
attr :side, :string,
values: ~w(top right bottom left),
default: "right",
doc: "The side from which the sheet appears"
attr :rest, :global
slot :inner_block, required: true
def sheet_content(assigns) do
assigns = assign(assigns, :variant_class, sheet_variants(assigns))
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
Renders a sheet header section for title and description.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_header(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
Renders a sheet title within the header section.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_title(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
Renders a sheet description within the header section.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_description(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
Renders a footer section for the sheet, typically containing actions.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_footer(assigns) do
~H"""
{render_slot(@inner_block)}
"""
end
@doc """
The close button for the sheet.
"""
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def sheet_close(assigns) do
~H"""