Current section
Files
Jump to
Current section
Files
lib/component/modal.ex
defmodule Orange.Component.Modal do
@moduledoc """
An modal/dialog component which renders an overlay in the middle of the viewport.
## Attributes
- `:open` - Whether the modal is open or not. This attribute is required.
- `:offset_x` - The offset from the left and right edge of the screen. This attribute is required.
- `:offset_y` - The offset from the top and bottom edge of the screen. This attribute is required.
> #### Info {: .info}
>
> When the offset_x/y is too big for the terminal size, the modal will not be rendered.
- `:children` - The content of the modal. This attribute is optional.
- `:title` - The title of the modal. See `Orange.Macro.rect/2` for supported values. This attribute is optional.
- `:style` - The modal style. See `Orange.Macro.rect/2` for supported values. This attribute is optional.
## Examples
defmodule Example do
@behaviour Orange.Component
import Orange.Macro
@impl true
def init(_attrs), do: %{state: %{search_value: ""}}
@impl true
def render(state, _attrs, update) do
modal_content =
rect do
"foo"
"bar"
end
rect do
line do
"Displaying modal..."
end
{
Orange.Component.Modal,
offset_x: 8,
offset_y: 4,
children: modal_content,
open: true
}
end
end
end

"""
@behaviour Orange.Component
import Orange.Macro
@impl true
def init(_attrs), do: %{state: nil}
@impl true
def render(_state, attrs, _update) do
{width, height} = terminal_impl().terminal_size()
offset_x = attrs[:offset_x]
offset_y = attrs[:offset_y]
style =
Keyword.merge(
Keyword.get(attrs, :style, []),
border: true
)
# Plus 2 for the border
if attrs[:open] && width > offset_x * 2 + 2 && height > offset_y * 2 + 2 do
rect position: {:fixed, offset_y, offset_x, offset_y, offset_x},
style: style,
title: attrs[:title] do
attrs[:children]
end
end
end
defp terminal_impl(), do: Application.get_env(:orange, :terminal, Orange.Terminal)
end