Input element helpers.
Emerge.UI.Input provides the two main interactive element constructors:
text/2for editable single-line text inputmultiline/2for auto-growing multiline text inputbutton/2for button-like interaction around any single child element
These helpers provide input behavior, not default visuals. Style them with the
same attrs you would use on other elements, such as Emerge.UI.Background,
Emerge.UI.Border, Emerge.UI.Font, and Emerge.UI.Interactive.
Text Input
text/2 builds a single-line text input element. multiline/2 builds a
multiline text input that defaults to a one-line minimum height and grows with
its content when height is omitted.
Both helpers are controlled inputs: the second argument is the currently rendered string value. Runtime editing can update the focused session immediately, but the next render still comes from the value you pass in.
For both text-input helpers, a matching Emerge.UI.Event.on_key_down/2
handler suppresses the default keydown behavior for that input. For example,
on_key_down(:a, ...) suppresses inserting "a", and
on_key_down(:enter, ...) can suppress the default newline insertion in
multiline/2.
Pair it with Emerge.UI.Event.on_change/1 when you want to receive updated
values, and with Emerge.UI.Event.on_focus/1 or Emerge.UI.Event.on_blur/1
when you care about focus changes.
Buttons
button/2 wraps exactly one child element and gives it button-like
interaction behavior.
The child can be any element tree, not just Emerge.UI.text/1. If you need a
more complex button body, wrap multiple visual parts in Emerge.UI.row/2,
Emerge.UI.column/2, or Emerge.UI.el/2 and pass that as the one child.
button/2 does not apply default styling. A typical button composes
Emerge.UI.Event.on_press/1 with visual attrs such as padding, background,
border radius, and interaction styles.
Examples
This render function builds a common form layout: a search field above a save button.
def render(state) do
column([spacing(16)], [
Input.text(
[
key(:search),
width(px(240)),
padding(12),
Background.color(color(:white)),
Border.rounded(8),
Event.on_change(:search_changed)
],
state.query
),
Input.button(
[
padding(12),
Background.color(color(:sky, 500)),
Border.rounded(8),
Font.color(color(:white)),
Event.on_press(:save)
],
text("Save")
)
])
end
Summary
Functions
Build a button-like element with exactly one child.
Build a multiline text input.
Build a single-line text input.
Types
@type t() :: Emerge.UI.element()
Input element returned by this module.
Functions
@spec button(Emerge.UI.attrs(), Emerge.UI.child()) :: t()
Build a button-like element with exactly one child.
button/2 is unstyled. Compose it with attrs such as
Emerge.UI.Event.on_press/1, Emerge.UI.Background.color/1,
Emerge.UI.Border.rounded/1, and Emerge.UI.Interactive.mouse_down/1 to get
the behavior and appearance you want.
The child can be any element tree. If you need multiple visual pieces inside the button, wrap them in a layout element and pass that layout as the one child.
Examples
This is a simple styled action button with pressed feedback.
Input.button(
[
padding(12),
Background.color(color(:sky, 500)),
Border.rounded(8),
Font.color(color(:white)),
Event.on_press(:save),
Interactive.mouse_down([Transform.move_y(1)])
],
text("Save")
)# Wrap multiple visual parts in a layout element and pass that layout
# as the button's single child.
Input.button(
[
padding(10),
Background.color(color(:slate, 100)),
Border.rounded(8),
Event.on_press(:open_menu)
],
row([spacing(8)], [
text("v"),
text("Actions")
])
)
@spec multiline(Emerge.UI.attrs(), String.t()) :: t()
Build a multiline text input.
value is the current content shown in the field. The element has no
children.
Input.multiline/2 defaults to a minimum height of one text line. When no
explicit height(...) attr is present, it grows vertically to fit its
wrapped content. When you do provide height(...), the element remains
multiline but stops auto-growing.
Like Input.text/2, pair it with Emerge.UI.Event.on_change/1 and treat the
second argument as the source of truth for the currently rendered content.
Content wraps to the resolved width of the element.
By default, both Enter and Shift+Enter insert a newline.
A matching Emerge.UI.Event.on_key_down/2 suppresses the default multiline
edit behavior for that keydown, including the normal Enter newline.
Example
This notes field auto-grows as its wrapped content expands.
def render(state) do
Input.multiline(
[
key(:notes),
width(fill()),
padding(12),
Background.color(color(:white)),
Border.rounded(8),
Event.on_change(:notes_changed)
],
state.notes
)
end
@spec text(Emerge.UI.attrs(), String.t()) :: t()
Build a single-line text input.
value is the current content shown in the field. The element has no
children.
Use Emerge.UI.Event.on_change/1 to receive updated values and treat the
second argument as the source of truth for the currently rendered content.
A matching Emerge.UI.Event.on_key_down/2 suppresses the default single-line
edit behavior for that keydown.
Example
This field keeps its rendered value in state.query and emits messages for
change, focus, and blur.
def render(state) do
Input.text(
[
key(:search),
width(px(240)),
padding(12),
Background.color(color(:white)),
Border.rounded(8),
Event.on_change(:search_changed),
Event.on_focus(:search_focused),
Event.on_blur(:search_blurred)
],
state.query
)
end