Emerge.UI.Size (Emerge v0.2.1)

Copy Markdown View Source

Length and sizing helpers for Emerge UI layouts.

Emerge.UI.Size provides the common vocabulary for sizing elements in rows, columns, and generic containers.

Use these helpers through width/1 and height/1.

Length Kinds

The main length helpers are:

  • px(n) for a fixed pixel size
  • fill() for taking remaining space
  • fill(n) for weighted remaining-space distribution
  • shrink() for sizing to content
  • content() as an alias for shrink()

fill() is visible inside layouts that distribute space between siblings, such as row/2 and column/2.

fill(2) does not mean 2 pixels. It means "take 2 shares of the remaining space". If a sibling uses fill(1), the fill(2) element gets twice as much of the leftover room.

Constraints

min/2 and max/2 wrap another length:

  • min(px(140), shrink()) means "size to content, but never below 140px"
  • max(px(180), fill()) means "fill remaining space, but never above 180px"

Examples

A fixed-width panel:

This is the most direct sizing mode: the panel is always 220px wide.

el(
  [
    width(px(220)),
    padding(12),
    Background.color(color(:slate, 900)),
    Border.rounded(10),
    Font.color(color(:slate, 50))
  ],
  text("Fixed panel")
)
Rendered fixed width size example

Shrink next to fill:

The first child stays only as wide as its content, while the second child expands to take the remaining room in the row.

row(
  [
    width(fill()),
    height(fill()),
    padding(12),
    spacing(12),
    Background.color(color(:slate, 900)),
    Border.rounded(12)
  ],
  [
    el(
      [
        width(shrink()),
        padding(10),
        Background.color(color(:slate, 50)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Shrink")
    ),
    el(
      [
        width(fill()),
        padding(10),
        Background.color(color(:slate, 100)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Fill")
    )
  ]
)
Rendered shrink and fill size example

Weighted fill distribution:

These three children split the leftover width in a 1:2:3 ratio.

row(
  [
    width(fill()),
    height(fill()),
    padding(12),
    spacing(8),
    Background.color(color(:slate, 900)),
    Border.rounded(12)
  ],
  [
    el(
      [
        width(fill(1)),
        padding(8),
        Background.color(color(:slate, 50)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("1")
    ),
    el(
      [
        width(fill(2)),
        padding(8),
        Background.color(color(:slate, 100)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("2")
    ),
    el(
      [
        width(fill(3)),
        padding(8),
        Background.color(color(:slate, 200)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("3")
    )
  ]
)
Rendered weighted fill size example

Min and max constraints:

The first item never becomes narrower than 140px, and the second fills the available space but stops growing once it reaches 180px.

row(
  [
    width(fill()),
    height(fill()),
    padding(12),
    spacing(12),
    Background.color(color(:slate, 900)),
    Border.rounded(12)
  ],
  [
    el(
      [
        width(min(px(140), shrink())),
        padding(10),
        Background.color(color(:slate, 50)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("At least 140px")
    ),
    el(
      [
        width(max(px(180), fill())),
        padding(10),
        Background.color(color(:slate, 100)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Fill, but cap at 180px")
    )
  ]
)
Rendered min and max size constraint example

Summary

Types

Base length accepted by width/1 and height/1.

Length with a minimum or maximum pixel constraint wrapped around another length.

Content-sized length. content() and shrink() return this value.

Fill length. Use fill() for one share or fill(n) for weighted fill.

Height attribute built from a length().

Public length type accepted by width/1 and height/1.

Fixed pixel length, for example px(220).

t()

Size attribute returned by this module.

Width attribute built from a length().

Functions

Size to content.

Fill the remaining space on an axis.

Apply a length to the element height.

Wrap a length in a maximum pixel constraint.

Wrap a length in a minimum pixel constraint.

Create a fixed pixel length.

Shrink to content.

Apply a length to the element width.

Types

base_length()

@type base_length() :: px_length() | fill_length() | content_length()

Base length accepted by width/1 and height/1.

constrained_length()

@type constrained_length() ::
  {:minimum, number(), length()} | {:maximum, number(), length()}

Length with a minimum or maximum pixel constraint wrapped around another length.

content_length()

@type content_length() :: :content

Content-sized length. content() and shrink() return this value.

fill_length()

@type fill_length() :: :fill | {:fill, number()}

Fill length. Use fill() for one share or fill(n) for weighted fill.

height_attr()

@type height_attr() :: {:height, length()}

Height attribute built from a length().

length()

@type length() :: base_length() | constrained_length()

Public length type accepted by width/1 and height/1.

px_length()

@type px_length() :: {:px, number()}

Fixed pixel length, for example px(220).

t()

@type t() :: width_attr() | height_attr()

Size attribute returned by this module.

width_attr()

@type width_attr() :: {:width, length()}

Width attribute built from a length().

Functions

content()

@spec content() :: content_length()

Size to content.

This is an alias for shrink/0.

fill()

@spec fill() :: :fill

Fill the remaining space on an axis.

fill() means one share of the leftover room. Use fill(n) for weighted distribution between siblings.

Examples

In the first example both children split the leftover width evenly. In the second, the right child gets twice as much space as the left child.

row([width(fill()), spacing(12)], [
  el([width(fill())], text("Left")),
  el([width(fill())], text("Right"))
])
row([width(fill()), spacing(8)], [
  el([width(fill(1))], text("1 share")),
  el([width(fill(2))], text("2 shares"))
])

fill(weight)

@spec fill(number()) :: {:fill, number()}

height(val)

@spec height(length()) :: height_attr()

Apply a length to the element height.

Height uses px(...), fill(), or shrink() depending on whether the element should be fixed, expand, or follow its content.

Example

The first child stays fixed at 48px tall, and the second child expands to use the rest of the available column height.

column([height(fill()), spacing(12)], [
  el([height(px(48))], text("Fixed height")),
  el([height(fill())], text("Fill remaining height"))
])

max(length_px, length)

@spec max(px_length(), length()) :: constrained_length()

Wrap a length in a maximum pixel constraint.

The resolved length must be at most the given px(...) value.

Example

This lets a flexible element participate in fill layout while still capping its final size.

el([width(max(px(180), fill()))], text("Fill, but cap at 180px"))

min(length_px, length)

@spec min(px_length(), length()) :: constrained_length()

Wrap a length in a minimum pixel constraint.

The resolved length must be at least the given px(...) value.

Example

This keeps a content-sized element from collapsing below a readable minimum.

el([width(min(px(140), shrink()))], text("At least 140px wide"))

px(n)

@spec px(number()) :: px_length()

Create a fixed pixel length.

Use px(...) when you want an exact width or height.

Example

Use this when a component should stay at an exact visual size.

el([width(px(220)), height(px(48))], text("Fixed size"))

shrink()

@spec shrink() :: content_length()

Shrink to content.

Use this when the element should be only as large as its child content.

shrink/0 and content/0 return the same value. shrink/0 is the clearer name in layout code.

Example

This is useful for labels, pills, and small controls that should hug their content instead of stretching.

row([width(fill()), spacing(12)], [
  el([width(shrink())], text("Content sized")),
  el([width(fill())], text("Takes the rest"))
])

width(val)

@spec width(length()) :: width_attr()

Apply a length to the element width.

width/1 accepts fixed, fill, shrink/content, and constrained lengths.

Example

This puts three width strategies next to each other so the difference is easy to see: fixed, fill, and shrink-to-content.

column([spacing(12)], [
  el([width(px(220))], text("Fixed")),
  el([width(fill())], text("Fill")),
  el([width(shrink())], text("Shrink"))
])