Utilities
To avoid the tedium of writing out styles explicitly over and over, Counterweight provides a variety of Tailwind-inspired "utility styles". These utilities are pre-defined styles that can be combined to form more complex styles.
The utilities can be imported from the counterweight.styles.utilities module.
We recommend a * import for ease of use:
That brings in the utilities, the palette's colors, and the ColorName, Shade and Side types the utility functions take,
but not Style, Color or anything else the module itself imports, which come from counterweight.styles.
Each utility is a Style that sets just a small set of properties.
Some are constants (e.g., border_heavy, justify_children_center),
and the rest are functions that return one (e.g., gap(n), margin_x(n), pad(n)).
Color utilities take a color name and shade, or any color.
For example, border_color("rose", 200) returns a Style that sets the border color to rose-200,
as does border_color(rose_200), with the palette's constant for that color:
from counterweight.styles import Style, CellStyle, Color
border_color("rose", 200) == Style(border_style=CellStyle(foreground=Color.from_hex("#fecdd3")))
border_color(rose_200) == border_color("rose", 200)
Since they are normal Styles, they can be combined to form more complex styles using the | operator.
Here we make a new Style for a rose_200-colored heavy border on the top and bottom sides:
from counterweight.styles.utilities import *
border_heavy_top_bottom_rose_200 = border_y | border_heavy | border_color("rose", 200)
Actually giving a name to the new style is optional. We can also use the expression directly in our component:
from counterweight.styles.utilities import *
from counterweight.components import component
from counterweight.elements import Text
@component
def my_component() -> Text:
return Text(
content="Hello, world!",
style=border_y | border_heavy | border_color("rose", 200),
)
Performance Considerations
If you have an expression like border_y | border_heavy | border_color("rose", 200) in your component,
it will be evaluated every time the component is rendered.
Merging styles with | does take some time, though it is aggressively cached inside the framework.
If you find that this is causing performance issues,
you should create the style just once,
ideally outside your component (i.e., at module scope),
so that it runs only once.
Reference
Each table below is built from the utilities module when the docs are built. The constants' tables list every field each one sets. Fields not listed are left unset, so merging the utility into another style leaves them alone (see Merging). The functions' tables give their signatures, since what they set depends on their arguments.
default is the empty style, a starting point that sets nothing.
| Utility | Sets |
|---|---|
default |
Nothing |
Colors
The color utilities draw from Tailwind's color palette
when given a ColorName such as "rose" and a Shade from 50 (lightest) to 950 (darkest).
Given one color instead, they use it, as Tailwind's arbitrary values such as text-[#fbbf24] do:
a Color, such as a palette constant or Color.from_hex("#fbbf24"),
one of the terminal colors, or a gradient.
text_white and text_black are outside the palette.
Each utility colors one part of a box. In the box below, every part has its own color, matched by the swatch beside the utility that paints it:
PLACES: tuple[tuple[str, ColorName, Shade], ...] = (
("margin_color", "indigo", 900),
("border_color", "amber", 400),
("border_bg", "slate", 600),
("padding_color", "teal", 700),
("content_color", "rose", 900),
("text_color", "lime", 300),
("text_bg", "sky", 800),
)
def legend_line(utility: str, color: ColorName, shade: Shade) -> Text:
return Text(
content=(
Chunk(content="██ ", style=text_color(color, shade).text_style),
Chunk(content=f'{utility}("{color}", {shade})'),
)
)
@component
def places() -> Div:
return Div(
style=row | gap(2) | align_children_center,
children=(
Div(
style=width(26)
| height(7)
| center_children
| margin(1)
| margin_color("indigo", 900)
| border
| border_heavy
| border_color("amber", 400)
| border_bg("slate", 600)
| pad_x(2)
| pad_y(1)
| padding_color("teal", 700)
| content_color("rose", 900),
children=(Text(style=text_color("lime", 300) | text_bg("sky", 800), content="Some text"),),
),
Div(style=col, children=tuple(legend_line(*place) for place in PLACES)),
),
)
| Utility | Sets |
|---|---|
text_white |
text_style.foreground = #ffffff |
text_black |
text_style.foreground = #000000 |
| Function | Description |
|---|---|
text_color(color: ColorName, shade: Shade) -> Styletext_color(color: AnyColor | Gradient) -> Style |
Color the text with a palette color, by name and shade, or with any color or gradient. |
text_bg(color: ColorName, shade: Shade) -> Styletext_bg(color: AnyColor | Gradient) -> Style |
Color the background behind the text with a palette color, by name and shade, or with any color or gradient. |
border_color(color: ColorName, shade: Shade) -> Styleborder_color(color: AnyColor | Gradient) -> Style |
Color the border characters with a palette color, by name and shade, or with any color or gradient. |
border_bg(color: ColorName, shade: Shade) -> Styleborder_bg(color: AnyColor | Gradient) -> Style |
Color the background behind the border characters with a palette color, by name and shade, or with any color or gradient. |
margin_color(color: ColorName, shade: Shade) -> Stylemargin_color(color: AnyColor | Gradient) -> Style |
Fill the margin with a palette color, by name and shade, or with any color or gradient. |
padding_color(color: ColorName, shade: Shade) -> Stylepadding_color(color: AnyColor | Gradient) -> Style |
Fill the padding with a palette color, by name and shade, or with any color or gradient. |
content_color(color: ColorName, shade: Shade) -> Stylecontent_color(color: AnyColor | Gradient) -> Style |
Fill the whole box with a palette color, by name and shade, or with any color or gradient, under any margin, padding and border colors. |
Palette
Every palette color is also a Color constant named <color>_<shade>, such as rose_200,
for style fields that take a Color directly.
Hover over a swatch to see its name and hex code.
| 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| slate | |||||||||||
| gray | |||||||||||
| zinc | |||||||||||
| neutral | |||||||||||
| stone | |||||||||||
| red | |||||||||||
| orange | |||||||||||
| amber | |||||||||||
| yellow | |||||||||||
| lime | |||||||||||
| green | |||||||||||
| emerald | |||||||||||
| teal | |||||||||||
| cyan | |||||||||||
| sky | |||||||||||
| blue | |||||||||||
| indigo | |||||||||||
| violet | |||||||||||
| purple | |||||||||||
| fuchsia | |||||||||||
| pink | |||||||||||
| rose |
counterweight.styles.utilities.ColorName
module-attribute
ColorName = Literal[
"slate",
"gray",
"zinc",
"neutral",
"stone",
"red",
"orange",
"amber",
"yellow",
"lime",
"green",
"emerald",
"teal",
"cyan",
"sky",
"blue",
"indigo",
"violet",
"purple",
"fuchsia",
"pink",
"rose",
]
The name of one of the palette's colors, as the color utilities take it, such as "sky".
counterweight.styles.utilities.Shade
module-attribute
Shade = Literal[
50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
]
One of the palette's shades, from lightest (50) to darkest (950), as in Tailwind's palette.
Terminal colors
A Color looks the same in every terminal.
The terminal's own colors follow the user's theme instead, as the colors of a program run in it do:
an IndexedColor is an entry of the terminal's 256-color palette,
whose first 16 are the black, red, green, yellow, blue, magenta, cyan and white that themes set, then their bright forms,
and TERMINAL_DEFAULT is the terminal's default foreground where it colors text,
and its default background where it fills one.
These utilities set them in each place the color utilities above do,
the *_indexed ones taking a palette index from 0 to 255.
Screenshots draw them in DEFAULT_PALETTE, and the defaults as white on black,
as the first 16 indexed colors and the defaults are drawn below.
In a terminal, they take whatever colors its theme gives them.
def swatch(index: int) -> Text:
return Text(style=text_bg_indexed(index) | width(6) | text_justify_center, content=str(index))
@component
def terminal_colors() -> Div:
return Div(
style=col,
children=(
Div(style=row, children=tuple(swatch(index) for index in range(8))),
Div(style=row, children=tuple(swatch(index) for index in range(8, 16))),
Text(
style=text_terminal_default | text_bg_terminal_default | margin_top(1) | pad_x(1),
content="text_terminal_default | text_bg_terminal_default",
),
),
)
| Utility | Sets |
|---|---|
text_terminal_default |
text_style.foreground = TerminalDefault() |
text_bg_terminal_default |
text_style.background = TerminalDefault() |
border_terminal_default |
border_style.foreground = TerminalDefault() |
border_bg_terminal_default |
border_style.background = TerminalDefault() |
margin_terminal_default |
margin_color = TerminalDefault() |
padding_terminal_default |
padding_color = TerminalDefault() |
content_terminal_default |
content_color = TerminalDefault() |
| Function | Description |
|---|---|
text_indexed(index: int) -> Style |
Color the text with entry index of the terminal's palette, which follows the user's theme. |
text_bg_indexed(index: int) -> Style |
Color the background behind the text with entry index of the terminal's palette. |
border_indexed(index: int) -> Style |
Color the border characters with entry index of the terminal's palette. |
border_bg_indexed(index: int) -> Style |
Color the background behind the border characters with entry index of the terminal's palette. |
margin_indexed(index: int) -> Style |
Fill the margin with entry index of the terminal's palette. |
padding_indexed(index: int) -> Style |
Fill the padding with entry index of the terminal's palette. |
content_indexed(index: int) -> Style |
Fill the whole box with entry index of the terminal's palette, under any margin, padding and border colors. |
Gradients
A gradient in a color place maps over the box that place paints unless the gradient names its own box.
The color utilities above take one, and these put one in each place too.
| Function | Description |
|---|---|
text_gradient(gradient: Gradient) -> Style |
Color the text with a gradient, which maps over the content box unless it names another box. |
text_bg_gradient(gradient: Gradient) -> Style |
Color the background behind the text with a gradient, which maps over the content box unless it names another. |
border_gradient(gradient: Gradient) -> Style |
Color the border characters with a gradient, which maps over the border box unless it names another. |
border_bg_gradient(gradient: Gradient) -> Style |
Color the background behind the border characters with a gradient, over the border box unless it names another. |
margin_gradient(gradient: Gradient) -> Style |
Fill the margin with a gradient, which maps over the margin box unless it names another. |
padding_gradient(gradient: Gradient) -> Style |
Fill the padding with a gradient, which maps over the padding box unless it names another. |
content_gradient(gradient: Gradient) -> Style |
Fill the whole box with a gradient, under any margin, padding and border colors, which maps over the border box unless it names another. |
Attributes
The text_* attributes draw the text bold, dim, italic, underlined or struck through,
and the border_* ones draw the border characters that way.
Each has a not_ form that turns it off when merged over a style that turns it on,
such as a style for a selected row that isn't bold, merged over a table's bold one.
text_link(uri) makes the text a hyperlink that the terminal opens when it's clicked,
and text_link(None) makes it not a link, inside text that is one.
They're CSS's font-weight: bold, font-style: italic and text-decoration,
with dim, which a terminal draws faint, in place of CSS's lighter weights.
TEXT_ATTRIBUTES: tuple[tuple[str, Style], ...] = (
("text_bold", text_bold),
("text_dim", text_dim),
("text_italic", text_italic),
("text_underline", text_underline),
("text_strikethrough", text_strikethrough),
)
EMPHASIS = text_bold | text_italic | text_underline | text_color("amber", 300)
def bordered(utility: str, style: Style) -> Text:
return Text(content=utility, style=border | border_heavy | border_color("sky", 400) | pad_x(1) | style)
@component
def attributes() -> Div:
return Div(
style=col | gap(1),
children=(
Div(
style=col,
children=tuple(Text(content=utility, style=style) for utility, style in TEXT_ATTRIBUTES),
),
Div(
style=col,
children=(
Text(content="EMPHASIS", style=EMPHASIS),
Text(content="EMPHASIS | text_not_italic", style=EMPHASIS | text_not_italic),
Text(content="EMPHASIS | text_not_underline", style=EMPHASIS | text_not_underline),
),
),
Div(
style=row | gap(1),
children=(
bordered("border_bold", border_bold),
bordered("border_dim", border_dim),
bordered("border_dim | border_not_dim", border_dim | border_not_dim),
),
),
),
)
text_bold
text_dim
text_italic
text_underline
text_strikethrough
EMPHASIS
EMPHASIS | text_not_italic
EMPHASIS | text_not_underline
┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ border_bold ┃ ┃ border_dim ┃ ┃ border_dim | border_not_dim ┃
┗━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
How each looks is up to the terminal and its font: some can draw bold text in a brighter color as well as, or instead of, a heavier weight, and a terminal whose font has no italic face can draw italic text upright.
| Utility | Sets |
|---|---|
text_bold |
text_style.bold = True |
text_not_bold |
text_style.bold = False |
text_dim |
text_style.dim = True |
text_not_dim |
text_style.dim = False |
text_italic |
text_style.italic = True |
text_not_italic |
text_style.italic = False |
text_underline |
text_style.underline = True |
text_not_underline |
text_style.underline = False |
text_strikethrough |
text_style.strikethrough = True |
text_not_strikethrough |
text_style.strikethrough = False |
border_bold |
border_style.bold = True |
border_not_bold |
border_style.bold = False |
border_dim |
border_style.dim = True |
border_not_dim |
border_style.dim = False |
border_italic |
border_style.italic = True |
border_not_italic |
border_style.italic = False |
border_underline |
border_style.underline = True |
border_not_underline |
border_style.underline = False |
border_strikethrough |
border_style.strikethrough = True |
border_not_strikethrough |
border_style.strikethrough = False |
| Function | Description |
|---|---|
text_link(uri: str | None) -> Style |
Make the text a hyperlink to uri, which the terminal opens when it's clicked, or with None, not a link. |
Direction and wrapping
These set the flexbox main axis, and whether children wrap onto more lines when they don't fit. See Choosing a layout model and Wrapping without a grid.
| Utility | Sets |
|---|---|
row |
layout.flex_direction = FlexDirection.Row |
col |
layout.flex_direction = FlexDirection.Column |
row_reverse |
layout.flex_direction = FlexDirection.RowReverse |
col_reverse |
layout.flex_direction = FlexDirection.ColumnReverse |
flex_no_wrap |
layout.flex_wrap = FlexWrap.NoWrap |
flex_wrap |
layout.flex_wrap = FlexWrap.Wrap |
flex_wrap_reverse |
layout.flex_wrap = FlexWrap.WrapReverse |
Splitting space
These size children along their parent's main axis. See Splitting space.
| Function | Description |
|---|---|
grow(n: float) -> Style |
Take n shares of the free space along the parent's main axis (flex_grow). |
shrink(n: float) -> Style |
Give up n shares of the overflow along the parent's main axis when the children don't fit (flex_shrink). |
length(n: int) -> Style |
Take exactly n cells along the parent's main axis, whatever the content (ratatui's Length). |
percentage(p: float) -> Style |
Take p percent of the parent's main axis, whatever the content (ratatui's Percentage). |
ratio(numerator: int, denominator: int) -> Style |
Take numerator / denominator of the parent's main axis, whatever the content (ratatui's Ratio). |
fill(n: float = 1) -> Style |
Share the parent's free main-axis space in proportion to n, whatever the content (ratatui's Fill). |
Alignment
justify_children_* distributes children along the main axis, align_children_* places them on the cross axis,
and align_self_* overrides that for one child.
justify_items_* and justify_self_* place grid items within their cells along the row.
The center and end forms are safe: content that doesn't fit overflows past the end edge only.
The _unsafe forms overflow both edges.
See Alignment and distribution.
| Utility | Sets |
|---|---|
justify_children_start |
layout.justify_content = AlignContent.Start |
justify_children_center |
layout.justify_content = AlignContent.SafeCenter |
justify_children_end |
layout.justify_content = AlignContent.SafeEnd |
justify_children_space_between |
layout.justify_content = AlignContent.SpaceBetween |
justify_children_space_around |
layout.justify_content = AlignContent.SpaceAround |
justify_children_space_evenly |
layout.justify_content = AlignContent.SpaceEvenly |
justify_children_center_unsafe |
layout.justify_content = AlignContent.Center |
justify_children_end_unsafe |
layout.justify_content = AlignContent.End |
align_children_start |
layout.align_items = AlignItems.Start |
align_children_center |
layout.align_items = AlignItems.SafeCenter |
align_children_end |
layout.align_items = AlignItems.SafeEnd |
align_children_stretch |
layout.align_items = AlignItems.Stretch |
align_children_center_unsafe |
layout.align_items = AlignItems.Center |
align_children_end_unsafe |
layout.align_items = AlignItems.End |
align_self_start |
layout.align_self = AlignItems.Start |
align_self_center |
layout.align_self = AlignItems.SafeCenter |
align_self_end |
layout.align_self = AlignItems.SafeEnd |
align_self_stretch |
layout.align_self = AlignItems.Stretch |
align_self_center_unsafe |
layout.align_self = AlignItems.Center |
align_self_end_unsafe |
layout.align_self = AlignItems.End |
justify_items_start |
layout.justify_items = AlignItems.Start |
justify_items_center |
layout.justify_items = AlignItems.SafeCenter |
justify_items_end |
layout.justify_items = AlignItems.SafeEnd |
justify_items_stretch |
layout.justify_items = AlignItems.Stretch |
justify_items_center_unsafe |
layout.justify_items = AlignItems.Center |
justify_items_end_unsafe |
layout.justify_items = AlignItems.End |
justify_self_start |
layout.justify_self = AlignItems.Start |
justify_self_center |
layout.justify_self = AlignItems.SafeCenter |
justify_self_end |
layout.justify_self = AlignItems.SafeEnd |
justify_self_stretch |
layout.justify_self = AlignItems.Stretch |
justify_self_center_unsafe |
layout.justify_self = AlignItems.Center |
justify_self_end_unsafe |
layout.justify_self = AlignItems.End |
center_children |
layout.align_items = AlignItems.SafeCenterlayout.justify_content = AlignContent.SafeCenter |
Sizing
See Sizing one box.
| Utility | Sets |
|---|---|
content_box |
layout.box_sizing = BoxSizing.ContentBox |
border_box |
layout.box_sizing = BoxSizing.BorderBox |
min_content_width |
layout.size_width = MinContent() |
max_content_width |
layout.size_width = MaxContent() |
fit_content_width |
layout.size_width = FitContentKeyword() |
stretch_width |
layout.size_width = Stretch() |
min_content_height |
layout.size_height = MinContent() |
max_content_height |
layout.size_height = MaxContent() |
fit_content_height |
layout.size_height = FitContentKeyword() |
stretch_height |
layout.size_height = Stretch() |
full_width |
layout.size_width = Stretch() |
full_height |
layout.size_height = Stretch() |
full |
layout.size_height = Stretch()layout.size_width = Stretch() |
| Function | Description |
|---|---|
width(n: int) -> Style |
Make the box n cells wide. |
height(n: int) -> Style |
Make the box n cells tall. |
size(w: int, h: int) -> Style |
Make the box w cells wide and h cells tall. |
min_width(n: int) -> Style |
Keep the box at least n cells wide. |
min_height(n: int) -> Style |
Keep the box at least n cells tall. |
max_width(n: int) -> Style |
Keep the box at most n cells wide. |
max_height(n: int) -> Style |
Keep the box at most n cells tall. |
aspect_ratio(ratio: float) -> Style |
Keep the box's width divided by its height at ratio, so either one sets the other. |
Spacing
| Utility | Sets |
|---|---|
margin_auto |
layout.margin_bottom = Auto()layout.margin_left = Auto()layout.margin_right = Auto()layout.margin_top = Auto() |
margin_x_auto |
layout.margin_left = Auto()layout.margin_right = Auto() |
margin_y_auto |
layout.margin_bottom = Auto()layout.margin_top = Auto() |
margin_top_auto |
layout.margin_top = Auto() |
margin_bottom_auto |
layout.margin_bottom = Auto() |
margin_left_auto |
layout.margin_left = Auto() |
margin_right_auto |
layout.margin_right = Auto() |
| Function | Description |
|---|---|
margin_top(n: int) -> Style |
Put n cells of margin above the box. |
margin_bottom(n: int) -> Style |
Put n cells of margin below the box. |
margin_left(n: int) -> Style |
Put n cells of margin left of the box. |
margin_right(n: int) -> Style |
Put n cells of margin right of the box. |
margin_x(n: int) -> Style |
Put n cells of margin left and right of the box. |
margin_y(n: int) -> Style |
Put n cells of margin above and below the box. |
margin(n: int) -> Style |
Put n cells of margin on all four sides of the box. |
margin_sides(top: int, right: int, bottom: int, left: int) -> Style |
Put margin on each side of the box separately, in the order of CSS's four-value margin. |
gap_width(n: int) -> Style |
Put n cells between children placed side by side. |
gap_height(n: int) -> Style |
Put n cells between children placed one above another. |
gap(n: int) -> Style |
Put n cells between children in both directions. |
pad(n: int) -> Style |
Put n cells of padding inside the border on all four sides. |
pad_x(n: int) -> Style |
Put n cells of padding inside the border on the left and right. |
pad_y(n: int) -> Style |
Put n cells of padding inside the border on the top and bottom. |
pad_top(n: int) -> Style |
Put n cells of padding inside the border on the top. |
pad_bottom(n: int) -> Style |
Put n cells of padding inside the border on the bottom. |
pad_left(n: int) -> Style |
Put n cells of padding inside the border on the left. |
pad_right(n: int) -> Style |
Put n cells of padding inside the border on the right. |
pad_sides(top: int, right: int, bottom: int, left: int) -> Style |
Put padding inside the border on each side separately, in the order of CSS's four-value padding. |
Borders
A side is drawn where its border width is 1, and each width utility has a _0 form that takes its sides away.
See Borders on some sides.
| Utility | Sets |
|---|---|
border |
layout.border_bottom = Length(1)layout.border_left = Length(1)layout.border_right = Length(1)layout.border_top = Length(1) |
border_top |
layout.border_top = Length(1) |
border_bottom |
layout.border_bottom = Length(1) |
border_left |
layout.border_left = Length(1) |
border_right |
layout.border_right = Length(1) |
border_x |
layout.border_left = Length(1)layout.border_right = Length(1) |
border_y |
layout.border_bottom = Length(1)layout.border_top = Length(1) |
border_0 |
layout.border_bottom = Length(0)layout.border_left = Length(0)layout.border_right = Length(0)layout.border_top = Length(0) |
border_top_0 |
layout.border_top = Length(0) |
border_bottom_0 |
layout.border_bottom = Length(0) |
border_left_0 |
layout.border_left = Length(0) |
border_right_0 |
layout.border_right = Length(0) |
border_x_0 |
layout.border_left = Length(0)layout.border_right = Length(0) |
border_y_0 |
layout.border_bottom = Length(0)layout.border_top = Length(0) |
border_collapse |
layout.gap_height = Length(-1)layout.gap_width = Length(-1) |
| Function | Description |
|---|---|
border_contract(n: int) -> Style |
Stop each border edge n cells short at an end next to a side that isn't drawn. |
border_sides(sides: frozenset[Side]) -> Style |
Draw the border on exactly the given sides. |
counterweight.styles.utilities.Side
module-attribute
Side = Literal['top', 'bottom', 'left', 'right']
One side of a box.
Border kinds
The border kind only chooses the characters, and draws nothing without a border width.
border_none removes the border along with its space.
Every other kind is drawn below, each around its own name:
KINDS: tuple[tuple[str, Style], ...] = (
("border_light", border_light),
("border_lightrounded", border_lightrounded),
("border_lightangled", border_lightangled),
("border_heavy", border_heavy),
("border_double", border_double),
("border_thick", border_thick),
("border_mcgugan", border_mcgugan),
("border_lightshade", border_lightshade),
("border_mediumshade", border_mediumshade),
("border_heavyshade", border_heavyshade),
("border_star", border_star),
)
@component
def gallery() -> Div:
return Div(
style=display_grid | grid_template_columns(fr(1), fr(1), fr(1)) | gap(1),
children=tuple(Text(style=border | kind | pad(1) | text_justify_center, content=name) for name, kind in KINDS),
)
┌──────────────────────┐ ╭──────────────────────╮ /▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔╲
│ │ │ │ ▏ ▕
│ border_light │ │ border_lightrounded │ ▏ border_lightangled ▕
│ │ │ │ ▏ ▕
└──────────────────────┘ ╰──────────────────────╯ ╲▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁/
┏━━━━━━━━━━━━━━━━━━━━━━┓ ╔══════════════════════╗ ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜
┃ ┃ ║ ║ ▌ ▐
┃ border_heavy ┃ ║ border_double ║ ▌ border_thick ▐
┃ ┃ ║ ║ ▌ ▐
┗━━━━━━━━━━━━━━━━━━━━━━┛ ╚══════════════════════╝ ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ░░░░░░░░░░░░░░░░░░░░░░░░ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▕ ▏ ░ ░ ▒ ▒
▕ border_mcgugan ▏ ░ border_lightshade ░ ▒ border_mediumshade ▒
▕ ▏ ░ ░ ▒ ▒
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ ░░░░░░░░░░░░░░░░░░░░░░░░ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ************************
▓ ▓ * *
▓ border_heavyshade ▓ * border_star *
▓ ▓ * *
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ************************
The light, rounded, heavy and double kinds use box-drawing characters, which border healing joins where borders meet. The rest don't join, and draw their edges with block elements, shades, slashes or asterisks.
| Utility | Sets |
|---|---|
border_none |
border_kind = None |
border_light |
border_kind = BorderKind.Light |
border_lightrounded |
border_kind = BorderKind.LightRounded |
border_lightangled |
border_kind = BorderKind.LightAngled |
border_heavy |
border_kind = BorderKind.Heavy |
border_double |
border_kind = BorderKind.Double |
border_thick |
border_kind = BorderKind.Thick |
border_mcgugan |
border_kind = BorderKind.McGugan |
border_lightshade |
border_kind = BorderKind.LightShade |
border_mediumshade |
border_kind = BorderKind.MediumShade |
border_heavyshade |
border_kind = BorderKind.HeavyShade |
border_star |
border_kind = BorderKind.Star |
Display and grids
display_none hides a box and everything in it: they take no space and aren't drawn.
See Grids and wrapping for the grid utilities.
| Utility | Sets |
|---|---|
display_flex |
layout.display = Display.Flex |
display_block |
layout.display = Display.Block |
display_grid |
layout.display = Display.Grid |
display_none |
layout.display = Display.Nil |
grid_auto_flow_row |
layout.grid_auto_flow = GridAutoFlow.Row |
grid_auto_flow_column |
layout.grid_auto_flow = GridAutoFlow.Column |
grid_auto_flow_row_dense |
layout.grid_auto_flow = GridAutoFlow.RowDense |
grid_auto_flow_column_dense |
layout.grid_auto_flow = GridAutoFlow.ColumnDense |
| Function | Description |
|---|---|
fr(n: float = 1) -> waxy.Minmax |
A grid track taking n shares of the free space, whatever the content (minmax(0, n fr)). |
span(n: int) -> waxy.GridSpan |
A grid placement spanning n tracks, for grid_row and grid_column. |
grid_template_rows(*tracks: waxy.GridTrackValue | int) -> Style |
Define the grid's rows, one track each, with an int meaning that many cells. |
grid_template_columns(*tracks: waxy.GridTrackValue | int) -> Style |
Define the grid's columns, one track each, with an int meaning that many cells. |
grid_row(start: waxy.GridPlacementValue | int | None = None, end: waxy.GridPlacementValue | int | None = None) -> Style |
Place a grid item between row lines start and end, with an int meaning that line. |
grid_column(start: waxy.GridPlacementValue | int | None = None, end: waxy.GridPlacementValue | int | None = None) -> Style |
Place a grid item between column lines start and end, with an int meaning that line. |
Positioning and layering
See Layering.
The inset_* utilities with a center axis, such as inset_bottom_center, center a box on that axis
only in a parent that centers its children, such as with center_children.
To center a box in any parent, see A dialog centered over the app.
| Utility | Sets |
|---|---|
inset_top_left |
layout.inset_left = Length(0)layout.inset_top = Length(0)layout.position = Position.Absolute |
inset_top_center |
layout.inset_left = Auto()layout.inset_right = Auto()layout.inset_top = Length(0)layout.position = Position.Absolute |
inset_top_right |
layout.inset_right = Length(0)layout.inset_top = Length(0)layout.position = Position.Absolute |
inset_center_left |
layout.inset_bottom = Auto()layout.inset_left = Length(0)layout.inset_top = Auto()layout.position = Position.Absolute |
inset_center_center |
layout.inset_bottom = Auto()layout.inset_left = Auto()layout.inset_right = Auto()layout.inset_top = Auto()layout.position = Position.Absolute |
inset_center_right |
layout.inset_bottom = Auto()layout.inset_right = Length(0)layout.inset_top = Auto()layout.position = Position.Absolute |
inset_bottom_left |
layout.inset_bottom = Length(0)layout.inset_left = Length(0)layout.position = Position.Absolute |
inset_bottom_center |
layout.inset_bottom = Length(0)layout.inset_left = Auto()layout.inset_right = Auto()layout.position = Position.Absolute |
inset_bottom_right |
layout.inset_bottom = Length(0)layout.inset_right = Length(0)layout.position = Position.Absolute |
position_relative |
layout.position = Position.Relative |
position_absolute |
layout.position = Position.Absolute |
| Function | Description |
|---|---|
inset_top(n: int) -> Style |
Inset a positioned box n cells from the top. |
inset_bottom(n: int) -> Style |
Inset a positioned box n cells from the bottom. |
inset_left(n: int) -> Style |
Inset a positioned box n cells from the left. |
inset_right(n: int) -> Style |
Inset a positioned box n cells from the right. |
inset_x(n: int) -> Style |
Inset a positioned box n cells from the left and right. |
inset_y(n: int) -> Style |
Inset a positioned box n cells from the top and bottom. |
inset(n: int) -> Style |
Inset a positioned box n cells from all four sides. |
inset_sides(top: int, right: int, bottom: int, left: int) -> Style |
Inset a positioned box from each side separately, in the order of CSS's four-value inset. |
z(z: int = 0) -> Style |
Draw the box and its descendants as one layer at z among the boxes of the stacking context it belongs to, where the higher z is drawn on top, and make it a stacking context for its descendants' own z. |
Overflow, clipping and scrolling
overflow_hidden, overflow_clip and overflow_scroll clip a box's children (and a Text's own lines) to its padding box, on both axes or, with _x or _y, on one,
and overflow_scroll makes the box a scroll container there.
clip_to_border lets a child, such as a border title, draw on its parent's border instead,
and clip_to_screen lets one, such as a dropdown, escape every clip above it.
See Clipping.
overflow_anchor_none turns off scroll anchoring,
and stick_to_end makes a scroll container follow its end,
on both axes or, with _x or _y, on one; unstick undoes it.
| Utility | Sets |
|---|---|
overflow_visible |
layout.overflow_x = Overflow.Visiblelayout.overflow_y = Overflow.Visible |
overflow_x_visible |
layout.overflow_x = Overflow.Visible |
overflow_y_visible |
layout.overflow_y = Overflow.Visible |
overflow_hidden |
layout.overflow_x = Overflow.Hiddenlayout.overflow_y = Overflow.Hidden |
overflow_x_hidden |
layout.overflow_x = Overflow.Hidden |
overflow_y_hidden |
layout.overflow_y = Overflow.Hidden |
overflow_clip |
layout.overflow_x = Overflow.Cliplayout.overflow_y = Overflow.Clip |
overflow_x_clip |
layout.overflow_x = Overflow.Clip |
overflow_y_clip |
layout.overflow_y = Overflow.Clip |
overflow_scroll |
layout.overflow_x = Overflow.Scrolllayout.overflow_y = Overflow.Scroll |
overflow_x_scroll |
layout.overflow_x = Overflow.Scroll |
overflow_y_scroll |
layout.overflow_y = Overflow.Scroll |
clip_to_padding |
clip_to = 'padding' |
clip_to_border |
clip_to = 'border' |
clip_to_screen |
clip_to = 'screen' |
overflow_anchor_auto |
overflow_anchor = 'auto' |
overflow_anchor_none |
overflow_anchor = 'none' |
stick_to_end |
stick_to_end_x = Truestick_to_end_y = True |
stick_to_end_x |
stick_to_end_x = True |
stick_to_end_y |
stick_to_end_y = True |
unstick |
stick_to_end_x = Falsestick_to_end_y = False |
unstick_x |
stick_to_end_x = False |
unstick_y |
stick_to_end_y = False |
Text
See Text wrapping, Ending a line with …,
and Text in layout.
| Utility | Sets |
|---|---|
text_justify_left |
text_justify = 'left' |
text_justify_center |
text_justify = 'center' |
text_justify_right |
text_justify = 'right' |
text_wrap_none |
text_wrap = 'none' |
text_wrap_stable |
text_wrap = 'stable' |
text_wrap_pretty |
text_wrap = 'pretty' |
text_wrap_balance |
text_wrap = 'balance' |
text_overflow_clip |
text_overflow = 'clip' |
text_overflow_ellipsis |
text_overflow = 'ellipsis' |