Emerge.UI.Space (Emerge v0.2.1)

Copy Markdown View Source

Padding and child-gap helpers.

Emerge layouts are spaced with padding and spacing rather than margins.

Use:

Padding

Padding lives inside the element. It pushes content and child layout inward from the element edges.

This is the usual way to create gutters inside cards, buttons, pills, and panels. Padding works together with helpers such as Emerge.UI.Background and Emerge.UI.Border when you want the frame to remain visible around the content.

Child Gaps

Spacing lives between siblings, not around the outside of a container. In Emerge there are no margins, so container padding creates the outer gutter while spacing separates the items inside it.

spacing/1 applies the same gap everywhere the layout kind consumes spacing. spacing_xy/2 lets layouts consume horizontal and vertical gaps separately.

Layout Behavior

Layout containers consume spacing like this:

  • row/2 uses horizontal spacing
  • column/2 and text_column/2 use vertical spacing
  • wrapped_row/2 uses horizontal spacing within each line and vertical spacing between wrapped lines

Wrapped rows also measure each line from the resolved child frames on that line. If a child grows taller after reflow, the line height and total wrapped row height grow with it, and later siblings are pushed down accordingly.

Even Distribution

space_evenly/0 is for rows and columns with definite room on their main axis.

  • on row/2, the row needs definite width, such as width(px(...)) or width(fill()) inside a bounded parent
  • on column/2, the column needs definite height, such as height(px(...)) or height(fill()) inside a bounded parent
  • when active, space_evenly/0 derives equal gaps from the remaining room between children
  • it does not add extra gap before the first child or after the last child
  • it replaces fixed main-axis spacing while active, so spacing/1 or spacing_xy/2 no longer controls those gaps

Examples

Padding creates inner gutters:

el(
  [
    width(px(360)),
    padding_xy(16, 12),
    Background.color(color(:slate, 900)),
    Border.rounded(12),
    Font.color(color(:slate, 50))
  ],
  row([width(fill()), spacing(12), center_y()], [
    el(
      [
        padding_each(4, 8, 4, 8),
        Background.color(color(:slate, 100)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.size(12),
        Font.color(color(:slate, 800))
      ],
      text("Stable")
    ),
    column([spacing(4)], [
      el([Font.color(color(:slate, 50))], text("Release branch")),
      el(
        [Font.size(12), Font.color(color(:slate, 300))],
        text("Padding creates the card gutter")
      )
    ])
  ])
)
Rendered padding example

spacing_xy/2 separates wrapped content in both axes:

wrapped_row(
  [
    width(px(320)),
    padding(12),
    spacing_xy(10, 12),
    Background.color(color(:slate, 900)),
    Border.rounded(12)
  ],
  [
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Docs")
    ),
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Layout")
    ),
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Nearby")
    ),
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Animation")
    ),
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Input")
    ),
    el(
      [
        padding_xy(10, 6),
        Background.color(color(:slate, 50)),
        Border.rounded(999),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Scroll")
    )
  ]
)
Rendered spacing_xy example

space_evenly/0 turns remaining width into equal gaps between children:

row(
  [
    width(px(360)),
    height(fill()),
    padding(12),
    space_evenly(),
    Background.color(color(:slate, 900)),
    Border.rounded(12)
  ],
  [
    Input.button(
      [
        padding_xy(12, 8),
        Background.color(color(:slate, 50)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Back")
    ),
    Input.button(
      [
        padding_xy(12, 8),
        Background.color(color(:slate, 100)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Review")
    ),
    Input.button(
      [
        padding_xy(12, 8),
        Background.color(color(:slate, 50)),
        Border.rounded(8),
        Border.width(1),
        Border.color(color(:slate, 300)),
        Font.color(color(:slate, 800))
      ],
      text("Ship")
    )
  ]
)
Rendered space_evenly example

Summary

Functions

Set the same padding on all four sides.

Set padding per edge as top, right, bottom, left.

Set horizontal and vertical padding.

Turn remaining main-axis room into equal gaps between children.

Set the gap between adjacent children.

Set horizontal and vertical spacing separately.

Types

edge_values()

@type edge_values() :: {number(), number(), number(), number()}

padding_attr()

@type padding_attr() :: {:padding, number() | edge_values()}

space_evenly_attr()

@type space_evenly_attr() :: {:space_evenly, true}

spacing_attr()

@type spacing_attr() :: {:spacing, number()}

spacing_xy_attr()

@type spacing_xy_attr() :: {:spacing_xy, {number(), number()}}

t()

Functions

padding(n)

@spec padding(number()) :: padding_attr()

Set the same padding on all four sides.

Use this when an element needs a uniform inner gutter around its content.

Example

This card uses one padding value to keep the text away from the frame.

el(
  [
    padding(16),
    Background.color(color(:slate, 900)),
    Border.rounded(12),
    Font.color(color(:white))
  ],
  text("Build passed")
)

padding_each(top, right, bottom, left)

@spec padding_each(number(), number(), number(), number()) :: padding_attr()

Set padding per edge as top, right, bottom, left.

Use this when a layout needs asymmetric insets, such as a header with extra room on one side or a panel whose top and bottom spacing differ.

Example

This header uses extra right padding to make room for a trailing affordance.

el(
  [
    padding_each(10, 18, 10, 12),
    Background.color(color(:white)),
    Border.rounded(10),
    Border.width(1),
    Border.color(color(:slate, 200))
  ],
  text("Project settings")
)

padding_xy(x, y)

@spec padding_xy(number(), number()) :: padding_attr()

Set horizontal and vertical padding.

The first argument is horizontal padding and the second is vertical padding. This is useful when controls need wider left and right insets than top and bottom insets.

Example

This pill uses wider horizontal padding so the label has more breathing room.

el(
  [
    padding_xy(14, 8),
    Background.color(color(:sky, 600)),
    Border.rounded(999),
    Font.color(color(:white))
  ],
  text("Deploy")
)

space_evenly()

@spec space_evenly() :: space_evenly_attr()

Turn remaining main-axis room into equal gaps between children.

space_evenly/0 only takes effect on rows and columns that have definite room on their main axis. It creates equal gaps between consecutive children, with no extra outer gap before the first child or after the last child.

When active, fixed main-axis spacing no longer controls those gaps.

Example

This row has a definite width, so the leftover room becomes equal gaps between the three actions.

row([width(px(360)), space_evenly()], [
  Input.button(
    [padding_xy(12, 8), Background.color(color(:sky, 500)), Border.rounded(8)],
    text("Back")
  ),
  Input.button(
    [padding_xy(12, 8), Background.color(color(:slate, 700)), Border.rounded(8), Font.color(color(:white))],
    text("Review")
  ),
  Input.button(
    [padding_xy(12, 8), Background.color(color(:emerald, 500)), Border.rounded(8)],
    text("Ship")
  )
])

spacing(n)

@spec spacing(number()) :: spacing_attr()

Set the gap between adjacent children.

spacing/1 is the common single-value gap helper for rows, columns, wrapped rows, and text columns.

Example

This column keeps a steady 10px rhythm between stacked actions.

column([spacing(10)], [
  Input.button([padding(10), Background.color(color(:sky, 500))], text("Save")),
  Input.button([padding(10), Background.color(color(:slate, 300))], text("Duplicate")),
  Input.button([padding(10), Background.color(color(:rose, 500))], text("Delete"))
])

spacing_xy(x, y)

@spec spacing_xy(number(), number()) :: spacing_xy_attr()

Set horizontal and vertical spacing separately.

Layouts consume these values differently:

  • row/2 uses the horizontal value
  • column/2 and text_column/2 use the vertical value
  • wrapped_row/2 uses horizontal spacing within a line and vertical spacing between wrapped lines

Example

This wrapped row keeps tags 10px apart on the same line and 12px apart when they wrap onto a new line.

wrapped_row([width(px(280)), spacing_xy(10, 12)], [
  el([padding_xy(10, 6), Background.color(color(:white)), Border.rounded(999)], text("Docs")),
  el([padding_xy(10, 6), Background.color(color(:white)), Border.rounded(999)], text("Layout")),
  el([padding_xy(10, 6), Background.color(color(:white)), Border.rounded(999)], text("Nearby")),
  el([padding_xy(10, 6), Background.color(color(:white)), Border.rounded(999)], text("Animation")),
  el([padding_xy(10, 6), Background.color(color(:white)), Border.rounded(999)], text("Input"))
])