A rendered frame returned by Tela.view/1 and Tela.Component.view/1.
A Frame carries two pieces of information: the rendered UI content as a
plain string, and an optional cursor position that tells the runtime where
to place the real terminal cursor after rendering.
Content
content is the full UI string for this frame, with lines separated by
\n. It is passed directly to Tela.Renderer.diff/2 for line-diff
rendering, exactly as the String.t() return from view/1 was previously.
Cursor
cursor is either nil (hide the terminal cursor) or a
{row, col, shape} tuple:
row— 0-indexed row relative to this frame's top-left.col— 0-indexed column relative to this frame's top-left.shape—:block,:bar, or:underline.
Cursor coordinates are relative to the component's own top-left. When
frames are composed with join/2, the accumulated row offset of each
preceding frame is added to the cursor row of the frame that holds it.
Composition
Use join/2 to stack frames vertically. It concatenates content strings
with a separator (default "\n"), adjusts the cursor row of each frame by
the cumulative line count of all preceding frames and their separators, and
takes the cursor from the first frame in the list that has a non-nil cursor.
a = Frame.new("Line A")
b = Frame.new("Line B", cursor: {0, 3, :block})
Frame.join([a, b])
# => %Frame{content: "Line A\nLine B", cursor: {1, 3, :block}}Usage in view/1
A top-level app with no interactive cursor:
def view(model) do
Frame.new("Count: #{model.count}\nPress q to quit.")
endA top-level app composing a TextInput component:
def view(model) do
header = Frame.new("What's your name?\n")
input = TextInput.view(model.input)
footer = Frame.new("\n(esc to quit)")
Frame.join([header, input, footer], separator: "")
end
Summary
Types
A cursor position within a frame. Coordinates are 0-indexed and relative to the frame's own top-left corner.
The shape of the terminal cursor.
A rendered frame, optionally carrying a cursor position.
Functions
Stacks a list of frames vertically, producing a single composed frame.
Returns a new frame with the given content and no cursor.
Returns a new frame with the given content and cursor options.
Types
@type cursor() :: {row :: non_neg_integer(), col :: non_neg_integer(), shape :: cursor_shape()}
A cursor position within a frame. Coordinates are 0-indexed and relative to the frame's own top-left corner.
@type cursor_shape() :: :block | :bar | :underline
The shape of the terminal cursor.
A rendered frame, optionally carrying a cursor position.
Functions
Stacks a list of frames vertically, producing a single composed frame.
Content strings are joined with separator (default "\n"). The cursor
is taken from the first frame in the list that has a non-nil cursor,
with its row adjusted by the cumulative line count of all preceding frames
and their separators.
Options
separator:— the string inserted between each frame's content (default"\n").
Examples
iex> alias Tela.Frame
iex> a = Frame.new("Line A")
iex> b = Frame.new("Line B", cursor: {0, 2, :block})
iex> Frame.join([a, b])
%Frame{content: "Line A\nLine B", cursor: {1, 2, :block}}
iex> alias Tela.Frame
iex> frames = [Frame.new("A"), Frame.new("B"), Frame.new("C")]
iex> Frame.join(frames)
%Frame{content: "A\nB\nC", cursor: nil}
Returns a new frame with the given content and no cursor.
The terminal cursor will be hidden while this frame is displayed.
Returns a new frame with the given content and cursor options.
Options
cursor:—{row, col, shape}tuple ornil. Coordinates are 0-indexed and relative to this frame's top-left. Shape is:block,:bar, or:underline.nilhides the cursor (equivalent tonew/1).