Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions lib/cookbook_web/live/recipes/modals_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule CookbookWeb.ModalsLive do
use CookbookWeb, :live_view
use CookbookNative, :live_view

def mount(_params, _session, socket) do
{:ok, socket
|> assign(:modal_type, nil)
|> assign(:form, to_form(%{
"type" => "sheet",
"detents" => false,
"drag_indicator" => false,
"background" => "",
"corner_radius" => "",
}))}
end

def render(assigns) do
~H""
end

def handle_event("form-changed", params, socket) do
{:noreply, socket
|> assign(:form, cast_form(params))}
end

def handle_event("open", %{ "type" => type } = params, socket) do
{:noreply, socket
|> assign(:modal_type, type)
|> assign(:form, cast_form(params))}
end

def handle_event("presentation-changed", _params, socket) do
{:noreply, assign(socket, :modal_type, nil)}
end

defp cast_form(%{ "detents" => detents, "drag_indicator" => drag_indicator } = params) do
to_form(
params
|> Map.put("detents", detents == "true")
|> Map.put("drag_indicator", drag_indicator == "true")
)
end
end
138 changes: 138 additions & 0 deletions lib/cookbook_web/live/recipes/modals_live.swiftui.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
defmodule CookbookWeb.ModalsLive.SwiftUI do
use CookbookNative, [:render_component, format: :swiftui]

def render(assigns) do
~LVN"""
<Group style='background(content: :modals); navigationTitle("Modals");'>
<.simple_form for={@form} id="type" phx-submit="open" phx-change="form-changed">
<.input
type="Picker"
field={@form[:type]}
options={[
{"Sheet", "sheet"},
{"Full Screen Cover", "fullScreenCover"},
{"Popover", "popover"},
{"Alert", "alert"},
{"Confirmation Dialog", "confirmationDialog"},
{"Inspector", "inspector"},
]}
label="Modal Type"
/>
<Section :if={@form[:type].value == "sheet"}>
<Text template="header">Sheet Customization</Text>
<.input
type="Toggle"
field={@form[:detents]}
label="Detents"
/>
<.input
type="Toggle"
field={@form[:drag_indicator]}
label="Drag Indicator"
/>
<.input
type="Picker"
field={@form[:background]}
options={[
{"Unspecified", ""},
{"Red", "system-red"},
{"Green", "system-green"},
{"Blue", "system-blue"}
]}
label="Background"
/>
<.input
type="Picker"
field={@form[:corner_radius]}
options={[
{"Unspecified", ""},
{"None", "0"},
{"Medium", "50"},
{"Large", "100"}
]}
label="Corner Radius"
/>
</Section>
<%!-- the popover is attached to the "Open" button --%>
<Group
style='popover(isPresented: attr("presented"), content: :content);'
presented={@modal_type == "popover"}
phx-change="presentation-changed"
>
<.button type="submit">Open</.button>

<%!-- `presentationCompactAdaptation` forces a popover to be used on smaller devices --%>
<VStack template="content" style="padding(); presentationCompactAdaptation(horizontal: .popover, vertical: .popover);">
<Text>Popover content</Text>
</VStack>
</Group>
</.simple_form>

<Group template="modals">
<VStack
style='sheet(isPresented: attr("presented"), content: :content);'
presented={@modal_type == "sheet"}
phx-change="presentation-changed"
>
<Group
template="content"
>
Sheet content
<VStack :if={@form[:detents].value} style="presentationDetents([.medium, .large]);"></VStack>
<VStack style='presentationDragIndicator(attr("visibility"));' visibility={if @form[:drag_indicator].value, do: "visible", else: "hidden"}></VStack>
<VStack :if={@form[:background].value != ""} style='presentationBackground(attr("background"));' background={@form[:background].value}></VStack>
<VStack :if={@form[:corner_radius].value != ""} style='presentationCornerRadius(attr("radius"));' radius={@form[:corner_radius].value}></VStack>
</Group>
</VStack>

<VStack
style='fullScreenCover(isPresented: attr("presented"), content: :content);'
presented={@modal_type == "fullScreenCover"}
phx-change="presentation-changed"
>
<VStack template="content">
<Text>Full screen cover content</Text>
<.button phx-click="presentation-changed">Dismiss</.button>
</VStack>
</VStack>

<VStack
style='alert("Alert Title", isPresented: attr("presented"), actions: :actions, message: :message);'
presented={@modal_type == "alert"}
phx-change="presentation-changed"
>
<Text template="message">Alert message content</Text>

<Button role="cancel" template="actions">
Cancel
</Button>
<Button role="destructive" template="actions">
Delete
</Button>
</VStack>

<VStack
style='confirmationDialog("Confirmation Dialog Title", isPresented: attr("presented"), titleVisibility: .visible, actions: :actions);'
presented={@modal_type == "confirmationDialog"}
phx-change="presentation-changed"
>
<Button role="cancel" template="actions">
Cancel
</Button>
<Button role="destructive" template="actions">
Delete
</Button>
</VStack>

<VStack
style='inspector(isPresented: attr("presented"), content: :content);'
presented={@modal_type == "inspector"}
phx-change="presentation-changed"
>
<Text template="content">Inspector content</Text>
</VStack>
</Group>
</Group>
"""
end
end
6 changes: 6 additions & 0 deletions lib/cookbook_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ defmodule CookbookWeb.Router do
description: "A list of message bubbles that starts at the bottom",
category: "UI"
}
live "/modals", ModalsLive, metadata: %{
title: "Modals",
icon: "macwindow.on.rectangle",
description: "Various modal options in SwiftUI",
category: "Navigation"
}
live "/onboarding", OnboardingLive, metadata: %{
title: "Onboarding",
icon: "list.star",
Expand Down