Drafter.Widget.Card (drafter v0.3.2)

Copy Markdown View Source

Renders a bordered panel with an optional title and text content lines.

Four border styles are available: :single, :double, :rounded (default), and :heavy. When a :title is provided it is embedded into the top border left-aligned with one padding character on either side. Content lines are padded and truncated to fit the inner width.

Component tag

This module has no component_tag/0 and is not reached through the widget registry. Drafter.App builds it as the element {:card, children, opts}:

card(children, opts)

children is the content: the renderer wraps it in a list and calls to_string/1 on each entry, so every entry must implement String.Chars. Pass strings. The remaining props come from opts.

Options

  • :title - String.t/0 shown in the top border. Default nil. A title whose padded length reaches the inner width is dropped and a plain border is drawn instead
  • :content - list of strings, one per inner line. Default []. A single non-list value is wrapped in a list at render time
  • :border - border style atom: :rounded (default), :single, :double, :heavy. An unknown value falls back to :rounded at render time
  • :border_color - {r, g, b} tuple for border characters. Default nil, which falls back to the theme's border colour and then to :color
  • :color - {r, g, b} tuple for content text. Default nil, which falls back to the theme and then to {200, 200, 200}
  • :background - {r, g, b} tuple for the card background. Default nil, which falls back to the theme and then to {40, 44, 52}
  • :style - map/0 of style properties. Default %{}
  • :class - theme class atom or list of them, reaching mount/1 as :classes. Default []
  • :app_module - module supplying a per-app theme. Default nil

update/2 re-reads every option except :border and :app_module, which are mount-only.

Widget value

Drafter.get_widget_value/1 is not implemented for this widget; the card is display-only and never focusable.

Usage

card(["Line 1", "Line 2"], title: "Summary", border: :rounded)
card(["Disk full"], title: "Alert", border_color: {255, 80, 80})

Summary

Functions

Ignores every event and returns {:noreply, state}. The card is not focusable and never consumes input.

Builds the card state from props.

Draws the card into rect.

Callback implementation for Drafter.Widget.unmount/1.

Folds fresh props into state.

Types

border()

@type border() :: :single | :double | :rounded | :heavy

rgb()

@type rgb() :: {0..255, 0..255, 0..255}

t()

@type t() :: %Drafter.Widget.Card{
  app_module: module() | nil,
  background: rgb() | nil,
  border: border(),
  border_color: rgb() | nil,
  classes: [atom()],
  color: rgb() | nil,
  content: [String.t()] | String.t() | nil,
  style: map(),
  title: String.t() | nil
}

Functions

focused(state)

handle_event(event, state)

@spec handle_event(Drafter.Event.t(), t()) :: {:noreply, t()}

Ignores every event and returns {:noreply, state}. The card is not focusable and never consumes input.

mount(props)

@spec mount(Drafter.Widget.props()) :: t()

Builds the card state from props.

iex> c = Drafter.Widget.Card.mount(%{title: "Summary", content: ["a", "b"]})
iex> {c.title, c.content, c.border}
{"Summary", ["a", "b"], :rounded}

iex> c = Drafter.Widget.Card.mount(%{})
iex> {c.title, c.content, c.border, c.color, c.background, c.classes}
{nil, [], :rounded, nil, nil, []}

preferred_height(args, opts)

render(state, rect)

Draws the card into rect.

Accepts either a t/0 or a raw props map, which is mounted first. Returns [] when rect.width is under 2. Otherwise returns 2 + length(content) strips — a top border, one row per content line padded and truncated to the inner width, and a bottom border. rect.height is not consulted, so a card with more content lines than rows overflows.

unmount(state)

Callback implementation for Drafter.Widget.unmount/1.

update(props, state)

@spec update(Drafter.Widget.props(), t()) :: t()

Folds fresh props into state.

Re-reads :title, :content, :style, :border_color, :background, :color and :classes. :border and :app_module are ignored here and keep their mounted values.

iex> c = Drafter.Widget.Card.mount(%{border: :single, content: ["a"]})
iex> updated = Drafter.Widget.Card.update(%{content: ["b"], border: :heavy}, c)
iex> {updated.content, updated.border}
{["b"], :single}

update_props_from_mount(mount_props, existing_state, opts)