Selkie--Align
NAME
Selkie::Align - Text alignment and box cross-axis alignment enums
SYNOPSIS
use Selkie::Align;
use Selkie::Widget::Text;
use Selkie::Layout::VBox;
use Selkie::Sizing;
# Centre a banner's text inside its own plane.
my $banner = Selkie::Widget::Text.new(
text => 'Selkie',
align => TextCenter,
sizing => Sizing.fixed(1),
);
$banner.set-align(TextRight);
# Centre a fixed-width card inside a full-width column.
my $col = Selkie::Layout::VBox.new(sizing => Sizing.flex, align-items => CrossCenter);
$col.add: Selkie::Widget::Text.new(
text => 'a narrow card',
cross-sizing => Sizing.fixed(20), # 20 columns, centred in the VBox
sizing => Sizing.fixed(3),
);DESCRIPTION
Two enums, kept in one module so every widget that positions something inside a wider slot speaks the same language.
TextAlign is about glyphs within a widget's own plane: Selkie::Widget::Text offsets each wrapped line by Text.align-column. CrossAlign is about widgets within a container: Selkie::Layout::VBox and Selkie::Layout::HBox place each child along the axis they do not stack on.
The two are orthogonal, and so is gap: gap reserves cells along the main axis (between children), alignment moves a child along the cross axis. A VBox with gap =E<gt> 1 and align-items =E<gt> CrossCenter gets both, independently.
The cross axis
A VBox stacks children top to bottom, so its main axis is rows and its cross axis is columns. An HBox is the mirror image: main axis columns, cross axis rows. "Cross-axis alignment" therefore means horizontal placement in a VBox and vertical placement in an HBox.
Two attributes drive it, and they answer different questions:
How big is the child on the cross axis?
Widget.cross-sizingβ a Selkie::Sizing resolved against the container's cross extent. Undefined (the default) means "as big as the container", which is what Selkie has always done.Where does that size sit?
CrossAlignβ on the container asalign-items, overridable per child asWidget.align-self.
my $row = Selkie::Layout::HBox.new(sizing => Sizing.flex, align-items => CrossStart);
# Both are 1 row tall; the second opts out of the container's rule.
$row.add: $stamp; # cross-sizing => Sizing.fixed(1) β top
$row.add: $badge; # β¦and align-self => CrossEnd β bottom
$badge.set-align-self(CrossEnd);Defaults are the old behaviour
CrossFill plus an undefined cross-sizing is exactly what VBox and HBox did before alignment existed: every child gets the container's full cross extent at offset 0. TextLeft likewise puts every line at column 0. Nothing in an existing app moves by a cell.
EXAMPLES
A centred, fixed-width login form
my $screen = Selkie::Layout::VBox.new(
sizing => Sizing.flex,
gap => 1,
align-items => CrossCenter,
);
$screen.add: Selkie::Widget::Text.new(
text => 'Sign in',
align => TextCenter,
cross-sizing => Sizing.fixed(40),
sizing => Sizing.fixed(1),
);
$screen.add: $username-row; # cross-sizing => Sizing.fixed(40)
$screen.add: $password-row; # cross-sizing => Sizing.fixed(40)A right-aligned status column
my $col = Selkie::Layout::VBox.new(sizing => Sizing.flex, align-items => CrossEnd);
$col.add: Selkie::Widget::Text.new(
text => '3 unread',
cross-sizing => Sizing.percent(50), # half the column, flush right
sizing => Sizing.fixed(1),
);Note the difference between the two ways of pushing text to the right: TextRight moves the glyphs inside a full-width widget, while CrossEnd moves the widget inside a wider container. Reach for TextRight when the widget's own background should span the row, and for CrossEnd when it shouldn't.
SEE ALSO
Selkie::Widget::Text β
align/align-columnSelkie::Layout::Allocate β
resolve-cross-extent,cross-axis-offset,effective-cross-alignSelkie::Layout::VBox / Selkie::Layout::HBox β
align-itemsSelkie::Sizing β the fixed/percent/flex model
cross-sizingreusesSelkie::BorderStyle β
TitleAlign, the same idea for a frame's title
Horizontal placement of a line of text inside its widget's plane. TextLeft is the default and the historical behaviour: every line starts at column 0. TextCenter and TextRight shift each line independently, so a wrapped paragraph comes out ragged-left rather than block-justified. Alignment is an offset, never padding β Selkie does not write spaces on either side of the line. That keeps the untouched cells showing the plane's base cell, which is what makes aligned text work over a scrim or a gradient.
Placement of a child along its container's cross axis β columns in a VBox, rows in an HBox. CrossFill is the default: the child spans the container's whole cross extent (unless it declares a cross-sizing, which always wins on size; CrossFill then places it at offset 0, like CrossStart). CrossStart is flush left / top, CrossEnd flush right / bottom, and CrossCenter splits the leftover space, rounding the leading side down.