Skip to content
HotLayout Docs

Widget reference

This page is a reference: every widget a document can contain, with its properties as the contract describes them. Contract version: 9.28.0.

Who needs it: someone who reads or writes document JSON by hand, checks what a field of a published document means, or writes a renderer. To put screens into an app you do not need to read it — start with the quickstart for Flutter or React.

How to read it:

  • Widgets are grouped as in the builder’s palette. Each has a table of its props: the type of the value, whether it is required, the default, and what it means.
  • How a style is read — the rules of style, which is the same on every widget.
  • Shared types — the types the tables link to: tokens, conditions, bindings, actions.
  • The descriptions are those of the schema file screen-schema.json, generated with it. Names in «…» are fields and blocks of that file.

Sections: Layout · Content · Actions · Progress and status · How a style is read · Shared types.

A document is a tree of nodes. Every node has the same outer shape; what differs is type and the props that go with it.

Node field Meaning
id Unique within a screen, not within the document: two screens may hold copies of one composition. Address a node as screen + id.
type The widget name, one of the headings below.
props The properties of that widget — the tables on this page.
children Child nodes, for widgets that hold other widgets.
visibleIf Optional condition on data; when it does not hold, the node is not drawn. See VisibilityCondition.
style Optional. The whole look of the node's box — padding, size, background, border, radius, shadow, opacity, color, text style — the same on every widget. See NodeStyle and How a style is read.
styleWhen Optional list of “condition → style”. The first case whose condition holds is laid over style, field by field at the top level. See StyleCase.
fill Only inside Stack: the layer takes the size of the stack.
weight Only inside a non-scrolling, non-wrapping Row: the share of the row width. See NodeWeight.
layer Only on a direct child of Stack: the layer becomes an overlay with its own alignment, shift and rotation, and never changes the size of the stack. See NodeLayer.
pull Only where children follow one another (Screen, Column, Container, a non-scrolling, non-wrapping Row): the node and everything after it move towards the start of the main axis, over what precedes them. See NodePull.

What a renderer does with a widget, operator or field it does not know is decided by the compatibility policy, not by the renderer.

Layout#

Screen#

Screen root: background and outer padding. Created together with the screen.

Since contract 1.0.0. Children: AppBar, Column, Row, Container, Grid, Stack, Tabs, Accordion, ChoiceGroup, Repeater, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, TextField, Switch, Checkbox, NavBar, at most 20. Extra node fields: styleOn, propsOn.

Property Type Required Default Notes
gap SpacingRef yes "sm"
align AlignToken no Where the children of the screen root that do not stretch stand across the screen (a node with its own «style.width» and the widgets of «x-style.layout.column.naturalWidth»): «start» — the start of the script (the right edge in RTL), «center», «end». Stretched children keep the full width. No field — «start», the screen as it was before 9.15.0. It is the cross alignment of the root column («x-style.layout.column.naturalWidthAlign»), so a pinned block of natural width follows it too; the app bar and the navigation bar always take the full width.
justify "start" | "center" | "end" | "between" no How the children of the BODY are placed from top to bottom when the content is shorter than the visible body (the area between the app bar and the bottom zone): «start», «center», «end», «between». Content taller than the body scrolls as before and the field changes nothing. Only the children of the body take part: the app bar, the pinned block and the navigation bar do not. No field — «start». Rules — «x-style.layout.alignment.screen».
contentMaxWidth integer 320–1920 no The largest width of the CONTENT of the screen, in logical pixels (9.18.0). The background of the root and of the zones (app bar, bottom zone) runs edge to edge; the content of the app bar, of the body and of the bottom zone is a column no wider than this number, centred — the same in LTR and RTL. A screen narrower than the number is not changed. No field — the content takes the full width, as before 9.18.0. Rules — «x-style.layout.widthClass.contentMaxWidth». A renderer older than 9.18.0 skips the field.
bodyTop "screenTop" no Where the BODY area of the screen starts (9.19.0). Without the field — at the bottom edge of the app bar (without an app bar — below the top safe inset): the screen as it was before 9.19.0. «screenTop» — at the top edge of the screen: the body lies UNDER the app bar and under the status bar, the app bar stays fixed in its place OVER the body and takes the presses in its box, and scrolled content shows through an app bar without a background. Nothing else changes: only the body scrolls. Rules — «x-style.layout.bodyTop» and «x-style.layout.safeTop». No field or an unknown word — the screen as before 9.19.0. A renderer older than 9.19.0 skips the field and draws the app bar as a strip above the body.

AppBar#

Top bar of the screen: title, subtitle, a back button and up to two actions on the right. One only, and first.

Since contract 6.0.0. Children: IconButton, Button, at most 3. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, styleScrolled.

Property Type Required Default Notes
title BindableString yes
subtitle BindableString no
showBack boolean yes true
titleAlign "start" | "center" no Where the title block stands (9.16.0): «center» — in the centre of the bar while it fits (the rule of 9.9.0), «start» — right after the leading zone, lines aligned to the start; logical, mirrored in right-to-left scripts. Rules — «x-style.layout.appBarTitle». No field — «center», exactly as before 9.16.0.
titleShown "scrolled" no When the title block is drawn (9.21.0). «scrolled» — only while the body is scrolled («x-style.layout.appBarScrolled»); at rest it is not drawn but keeps its place, so the zones do not jump. No field or an unknown word — always, exactly as before 9.21.0.

Column#

Holds other widgets and stacks them top to bottom with an even gap.

Since contract 1.0.0. Children: Column, Row, Container, Grid, Stack, Tabs, Accordion, ChoiceGroup, Repeater, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, TextField, Switch, Checkbox, at most 30. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, propsOn.

Property Type Required Default Notes
gap SpacingRef yes "sm"
align AlignToken yes "start"
justify "start" | "center" | "end" | "between" no How the children are placed along the MAIN axis (top to bottom) when the node is taller than its content: «start» — at the top, «center», «end» — at the bottom, «between» — the free space goes between the children. Free space exists only when the height of the node is named («style.height», «style.minHeight») or given by the parent (a layer with «fill»); a node as tall as its content has none, and the field changes nothing — it is not an error. «gap» stays the smallest distance between children. No field — «start». Rules — «x-style.layout.alignment». A renderer older than 9.15.0 skips the field.
action PressAction no
label PressLabel no
longPress LongPressAction no
longPressLabel LongPressLabel no

Row#

Holds other widgets and lays them left to right, with or without wrapping.

Since contract 2.0.0. Children: Column, Row, Container, Stack, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, TextField, Switch, Checkbox, at most 10. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, propsOn.

Property Type Required Default Notes
gap SpacingRef yes "sm"
align AlignToken yes "center"
justify "start" | "center" | "end" | "between" yes "start"
wrap boolean yes false
scrollable boolean no false The row scrolls sideways and the children keep their natural width. Stronger than «wrap»: if both are true, the row scrolls instead of wrapping.
carousel Carousel no Turns the sideways scroll into a carousel: the scroll snaps to the cards and dots show the position. Rules — «x-style.layout.carousel». A renderer older than 9.11.0 skips the field and shows the plain row.
action PressAction no
label PressLabel no
longPress LongPressAction no
longPressLabel LongPressLabel no

Container#

Card: holds other widgets, adding background, corner radius, shadow and padding.

Since contract 2.0.0. Children: Column, Row, Container, Grid, Stack, Tabs, Accordion, ChoiceGroup, Repeater, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, TextField, Switch, Checkbox, at most 15. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, propsOn.

Property Type Required Default Notes
direction ContainerDirection no "column" The direction the container stacks children in: «column» — one under another, «row» — side by side. The cross axis is the same as in the «Column» and «Row» widgets: in a column the child takes the full width of the container, in a row the children are centred vertically. Documents before 8.1.0 have no such field — there it reads «column».
gap SpacingRef yes "none"
align AlignToken no The CROSS axis. In a column container — where the children that do not stretch stand horizontally (a node with its own «style.width» and the widgets of «x-style.layout.column.naturalWidth»; stretched children keep the full width); no field — «start». In a row container — how the children stand vertically; no field — «center». Both are the container as it was before 9.15.0 («x-style.layout.alignment.cross»).
justify "start" | "center" | "end" | "between" no The MAIN axis: «start», «center», «end», «between» — where the free space along the direction of the container goes. In a row container the free space is the width the children leave. In a column container it exists only when the height of the node is named («style.height», «style.minHeight») or given by the parent (a layer with «fill»); otherwise the field changes nothing and is not an error. No field — «start». Rules — «x-style.layout.alignment».
action PressAction no
label PressLabel no
longPress LongPressAction no
longPressLabel LongPressLabel no

Grid#

Holds other widgets and lays them out in equal columns, wrapping to the next row.

Since contract 8.5.0. Children: Column, Row, Container, Spacer, Stack, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, at most 24. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, propsOn.

Property Type Required Default Notes
columns integer 2–4 yes 2 How many cells go in a row. The cell width is the same across the grid: (grid width − gaps) ÷ number of columns.
gap SpacingRef yes "sm"

Stack#

Layers content one on top of another: a lock on a card, a badge in the corner. First in the list is the lowest.

Since contract 8.6.0. Children: Column, Row, Container, Grid, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, at most 5. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
alignHorizontal AlignToken yes "center" Where a layer narrower than the stack sits: «start» — at the start of the line (on the left in LTR), «end» — at the end.
alignVertical AlignToken yes "center" Where a layer shorter than the stack sits: «start» — at the top, «end» — at the bottom.
action PressAction no
label PressLabel no
longPress LongPressAction no
longPressLabel LongPressLabel no

Tabs#

Several panels under one bar of titles; exactly one is visible. The user switches them.

Since contract 8.8.0. Children: Tab, at most 5. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
initialTab integer 0–9007199254740991 yes 0 Index of the tab open when the screen is shown; counting from zero among ALL «Tab» children in document order — tabs hidden by «visibleIf» are counted too, so the index does not shift with data. If the named tab is hidden at that moment, the first visible tab is opened. After that the user switches tabs, and the document never learns about it.

Tab#

One tab panel together with its title in the bar. Does not exist outside Tabs.

Since contract 8.8.0. Children: Column, Row, Container, Grid, Stack, Accordion, ChoiceGroup, Repeater, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, TextField, Switch, Checkbox, at most 15. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
title BindableString yes

Accordion#

Holds other widgets under a title and hides them until tapped open.

Since contract 3.0.0. Children: Column, Row, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, at most 10. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
title BindableString yes
initiallyExpanded boolean yes false

Repeater#

Draws its single child once per record in the data. Fields of the current record are available inside.

Since contract 8.4.0. Children: Column, Row, Container, Grid, Stack, Accordion, Repeater, Spacer, Divider, Text, Image, Icon, Button, IconButton, ListTile, ProgressBar, CircularProgress, Badge, at most 2. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, propsOn.

Property Type Required Default Notes
source non-empty string yes Name of a collection from the data contract, for example «tasks». An item of that collection becomes available to the nodes inside the template under its own prefix: the «tasks» collection gives «task.title», «task.progress» and the rest of the task fields.
item non-empty string yes
direction ContainerDirection no "column"
gap SpacingRef yes "sm"
columns integer 2–4 no How many copies of the template go in a row. No field — one per row. The cell width is computed exactly as in Grid: (width − gaps) ÷ columns.
limit integer 1–50 no
carousel Carousel no Turns the sideways scroll into a carousel: the scroll snaps to the cards and dots show the position. Rules — «x-style.layout.carousel». A renderer older than 9.11.0 skips the field and shows the plain row.
where ListWhereCondition no Draw only the records for which this condition holds (9.23.0), judged in the scope of THAT record over the outer scope. A record that does not pass does not exist for the layout: the grid packs, the carousel counts stops and dots of the cards drawn, numbers count the records drawn; «limit» takes the first records that passed. A comparison by «valuePath» with no value under it holds for every record («All»). No field — every record. Rules — «x-listFilter».
groupBy non-empty string no Group the drawn records (9.26.0): records that follow one another with the same value under this path of the RECORD (for example «activity.day») form one group, and the SECOND child of the Repeater — the group header — is drawn before each group in the scope of its FIRST record. The order is the order of the data; groups are formed after «where» and «limit». Only a list in a column: with «columns» or a row direction the field is not published. No field — no groups, and the Repeater has one child. Rules — «x-repeaterGroup».

Spacer#

Empty space of a given size between neighbours.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
size SpacingRef yes "md"
orientation Orientation yes "horizontal"

Divider#

A thin line between neighbours.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
color ColorRef yes "border"
spacing SpacingRef yes "sm"
orientation Orientation yes "horizontal"

Content#

Text#

Text: a literal or a value from data. Can limit the number of lines.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
content BindableString yes
align AlignToken yes "start"
maxLines integer 1–20 no
overflow "clip" | "ellipsis" | "visible" yes "ellipsis"
spans object no Own styles of parts of the text, keyed by the NAME of a template value of content. Every piece of the rendered string that comes from the place {name} is drawn with this style over the style of the node.
marker TextMarker no List item marker before the text (9.17.0): «bullet» — «•» in the font of the text, «number» — the number of the item among consecutive numbered siblings and a dot, «none» or no field — plain text. The text hangs: its second line starts under the first line of the text, not under the marker («x-style.layout.listMarker»).
animateChanges true no When the DATA change the value of this node while it is shown, the renderer leads from the old value to the new one (9.21.0): a number of a text with a numeric format counts through the values between, a scale grows. Duration, curve, steps and when there is no transition — «x-valueTransition». No field — the value changes at once, exactly as before 9.21.0.
animateIn true no When the node is SHOWN, its value grows from zero to its own (9.24.0): a number of a text with a numeric format counts up from 0 with the same curve, duration and steps as «animateChanges»; a ProgressBar or CircularProgress fills from empty. Shown — the first show of the screen, a screen shown again («back»), a node that appears (condition, width class, a new record). Rules — «x-valueAppear». No field — the value is there at once, exactly as before 9.24.0.

Image#

A picture: an asset bundled with the app or an https link.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
source ImageSource yes {"kind":"asset","asset":"placeholder"}
aspectRatio ImageRatio yes "16:9"
fit "cover" | "contain" no "cover"
alt AltText no

Icon#

An icon from the contract dictionary, in a given color and size.

Since contract 2.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
name IconToken yes "star"
iconPath IconPath no
size "sm" | "md" | "lg" yes "md"
glyphSize integer 8–128 no Own size of the drawing, a whole number of logical pixels (9.16.0): the side of the square the icon is drawn in. Stronger than the word in «size» and than «style.typography»; the word stays in the document as the value a renderer older than 9.16 draws. Rules — «x-style.layout.ownGlyphSize». No field — the size is the word in «size», exactly as before 9.16.0.
alt AltText no

Actions#

ChoiceGroup#

Holds list rows of which exactly one can be picked. The choice belongs to the group.

Since contract 6.0.0. Children: ListTile, Divider, at most 20. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
value BindableString64 yes
gap SpacingRef yes "none"
required true no Must be filled before a «requiresFilled» control of the screen is enabled («x-style.layout.form.required»). No field — not required.

Button#

A button with a label and an action: go to a screen, submit, share.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, zone.

Property Type Required Default Notes
label BindableString yes
variant "primary" | "secondary" | "ghost" yes "primary"
action ButtonAction yes {"type":"none"}
fullWidth boolean yes true
icon IconToken no Icon beside the label. Drawn by the rule «x-style.layout.iconBesideText»: same color as the label, a gap between them, centred on the line of the label. No field — no icon.
iconPath IconPath no
iconPosition IconPosition no
size ButtonSize no
requiresFilled true no Disabled while a required field of the screen is not filled («x-style.layout.form.filled», «…form.button»). No field — not read.
disabledIf VisibilityCondition no Disabled while the condition holds; with «requiresFilled» — when either holds («x-style.layout.form.button»). No field — not disabled.
confirm "swipe" no How the press is confirmed (9.22.0). «swipe» — the button is drawn as a track with a thumb at the inline start; the action and its «track» run only when the thumb is dragged to the inline end past the threshold and released; released earlier, it returns. From the keyboard and for assistive technology it is an ordinary button named by its label: Enter and Space act at once. A disabled button does not move. Rules — «x-swipeConfirm». No field or an unknown word — an ordinary press, exactly as before 9.22.0.

IconButton#

A round button with an icon and no visible text: back, info, close. It needs a name for screen readers.

Since contract 9.5.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback, zone.

Property Type Required Default Notes
icon IconToken yes "info"
iconPath IconPath no
label BindableString yes
variant "primary" | "secondary" | "ghost" yes "secondary"
size ButtonSize yes "md"
glyphSize integer 8–128 no Own size of the drawing, a whole number of logical pixels (9.16.0): the side of the square the icon is drawn in. Stronger than the word in «size» and than «style.typography»; the word stays in the document as the value a renderer older than 9.16 draws. Rules — «x-style.layout.ownGlyphSize». No field — the size is the word in «size», exactly as before 9.16.0.
action ButtonAction yes {"type":"none"}
requiresFilled true no Disabled while a required field of the screen is not filled («x-style.layout.form.filled», «…form.button»). No field — not read.
disabledIf VisibilityCondition no Disabled while the condition holds; with «requiresFilled» — when either holds («x-style.layout.form.button»). No field — not disabled.

The bottom bar that switches sections of the app: 2–5 items, an icon above a label. It stays at the bottom while the screen scrolls.

Since contract 9.12.0. Children: NavItem, at most 5. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
widePlacement "top" | "bottom" no Where the bar stands when the box of the screen is «medium» or «expanded» wide (9.18.0): «top» — at the top, its items inside the app bar of the screen or, without one, in a bar of their own; «bottom» — at the bottom on every width, as on a phone. On «compact» the bar is always at the bottom. The document does not change: the bar stays the last child of the screen root. Rules — «x-style.layout.wideNav». No field — «top».
float true no The bar floats over the body (9.22.0): the body area reaches the bottom of the screen and the content scrolls UNDER the bottom zone; the renderer adds the height of the zone at the end of the body content, so the last row scrolls clear of it, and puts the bottom safe inset OUTSIDE the box of the bar. The look of the pill is the style of the node (margin, radius, «backdropBlur», shadow). Read only where the bar stands in the bottom zone; on «medium» and «expanded» with the bar at the top it changes nothing. Rules — «x-style.layout.navFloat». No field — the bar as before 9.22.0.

An item of the navigation bar: an icon, a label and the section it opens.

Since contract 9.12.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
icon IconToken yes "house"
label BindableString yes
action ButtonAction yes {"type":"none"}
badgeWhen VisibilityCondition no Show a dot on the icon of the item while the condition holds (9.22.0): the same form, check and missing-data rule as «visibleIf». Only a dot, no number; its colour is the core token «accent». The accessible name stays the label. Rules — «x-style.layout.navBadge». No field or a condition the renderer does not understand — no dot.

TextField#

A field the person types into: a label above, the field, a hint or an error below. What is typed is written to a data path.

Since contract 9.13.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
label BindableString yes
value InputValue no
valueType TextFieldValueType no
required true no Must be filled before a «requiresFilled» control of the screen is enabled («x-style.layout.form.required»). No field — not required.
placeholder BindableString no
helper BindableString no
error BindableString no
keyboard InputKeyboard no
maxLength integer 1–10000 no Limit of the entered text in Unicode code points; the renderer cuts the input to it. A counter is drawn only with «counter».
lines integer 1–8 no Visible lines of the field. More than one — a multiline field: Enter is a new line. No field — one line.
disabledIf VisibilityCondition no
fieldRadius RadiusRef no Radius of the box of the field itself (9.19.0): a token or a number. No field — «sm». Rules — «x-style.layout.inputParts.field».
fieldBackground ColorRef no Background of the box of the field (9.19.0). No field — «surface». Rules — «x-style.layout.inputParts.field».
fieldBorderColor ColorRef no Colour of the border of the field at rest (9.19.0); the colours of focus and error replace it as before. No field — «border». Rules — «x-style.layout.inputParts.field».
fieldBorderWidth integer 1–4 no Width of the border of the field in logical pixels (9.19.0), the same in every state. No field — 1. Rules — «x-style.layout.inputParts.field».
fieldHeight integer 32–120 no Exact height of the box of a ONE-LINE field in logical pixels (9.19.0); the text is centred. Not read by a multiline field. No field — border, padding and the line. Rules — «x-style.layout.inputParts.field».
prefix FieldAffix no
suffix FieldAffix no
counter true no Draws «count / maxLength» under the field, at the end of the row of the helper (9.19.0); the count is in Unicode code points. Read only together with «maxLength». No field — no counter. Rules — «x-style.layout.inputParts.counter».

Switch#

A row with a label and a switch at the end — a setting that applies at once. Writes yes or no to a data path.

Since contract 9.13.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
label BindableString yes
value InputValue no
disabledIf VisibilityCondition no

Checkbox#

A row with a box and a label — a consent or a choice the person confirms. Writes yes or no to a data path.

Since contract 9.13.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
label BindableString yes
value InputValue no
required true no Must be filled before a «requiresFilled» control of the screen is enabled («x-style.layout.form.required»). No field — not required.
disabledIf VisibilityCondition no

ListTile#

One widget with slots, not an assembly: photo or icon, title with description, value or choice.

Since contract 1.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
leading ListTileLeading yes {"kind":"icon","icon":"chevron"}
title BindableString yes
subtitle BindableString no
titleMaxLines integer 1–5 no The largest number of lines of the title of the row (9.19.0); the rest is cut with an ellipsis at the end of the last line. No field — the text wraps without a limit, as before 9.19.0. Rules — «x-style.layout.listTileParts.maxLines».
subtitleMaxLines integer 1–5 no The largest number of lines of the subtitle of the row (9.19.0); the rest is cut with an ellipsis at the end of the last line. No field — the text wraps without a limit, as before 9.19.0. Rules — «x-style.layout.listTileParts.maxLines».
trailing ListTileTrailing yes {"kind":"chevron"}
action ButtonAction no
longPress LongPressAction no
longPressLabel LongPressLabel no

Progress and status#

ProgressBar#

Progress bar: current value and limit, both can come from data.

Since contract 2.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
value BindableNumber yes
max BindableNumber yes {"kind":"literal","value":100}
color ColorRef yes "primary"
labelFormat "valueOfMax" | "percent" | "none" yes "valueOfMax"
thickness SpacingRef no Thickness of the track and of the fill: the height of the bar track, the stroke of the ring arc. A spacing token or a whole number of dp. No field (or a token the theme does not declare) — «x-style.layout.progress.defaultThickness». A ring never draws thicker than half of its diameter; zero draws neither the track nor the fill.
trackColor ColorRef no Color of the track — the whole scale under the fill. No field (or a token the theme does not declare) — «x-style.layout.progress.defaultTrackColor».
gradient GradientRef no Gradient of the fill, stronger than «color» while it resolves. It runs along the FILLED part: position 0 — the start of the scale, position 1 — the end of the fill («x-style.layout.progress.gradient»); the angle is not read. No field, an unknown token or unordered stops — the fill is the solid «color».
cap "round" no Ends of the scale (9.21.0). «round» — the ends of the ring arc and of the bar track and fill are half-circles of the thickness, kept INSIDE the filled part: geometry — «x-style.layout.progressCap». No field or an unknown word — square ends of the ring arc and the theme «pill» radius of the bar, exactly as before 9.21.0.
animateChanges true no When the DATA change the value of this node while it is shown, the renderer leads from the old value to the new one (9.21.0): a number of a text with a numeric format counts through the values between, a scale grows. Duration, curve, steps and when there is no transition — «x-valueTransition». No field — the value changes at once, exactly as before 9.21.0.
animateIn true no When the node is SHOWN, its value grows from zero to its own (9.24.0): a number of a text with a numeric format counts up from 0 with the same curve, duration and steps as «animateChanges»; a ProgressBar or CircularProgress fills from empty. Shown — the first show of the screen, a screen shown again («back»), a node that appears (condition, width class, a new record). Rules — «x-valueAppear». No field — the value is there at once, exactly as before 9.24.0.
glow ProgressGlow no
segments integer 2–12 no Cuts the scale into this many equal steps with a gap between them. A step is filled WHOLE or not at all: filled = floor(ratio × segments). Geometry, gap, rounding and the gradient — «x-style.layout.progressSegments». No field — the continuous bar.
currentColor ColorRef no Color of the CURRENT step — the first one that is not filled yet. Read only with «segments». No field (or a token the theme does not declare) — the current step looks like every other unfilled one.

CircularProgress#

An arc around an empty center: how much of the scale is done. What goes in the center is decided by Stack.

Since contract 8.7.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
value BindableNumber yes
max BindableNumber yes {"kind":"literal","value":100}
color ColorRef yes "primary"
size "sm" | "md" | "lg" yes "md" Diameter of the ring when the node names no size of its own: «sm» — around a badge, «md» — a rank in a ring, «lg» — the main ring of the screen («x-style.layout.progress.ring.sizes»). A node with «style.width» or «style.height» takes its diameter from them instead (9.7.0).
labelFormat "valueOfMax" | "percent" | "none" no "none" Label in the CENTER of the ring: «percent» — «75%», «valueOfMax» — «3/4», «none» — nothing, and the center stays free for a Stack layer. Unlike the progress bar, the default here is «none»: the center is space the contract already promised to the document.
thickness SpacingRef no Thickness of the track and of the fill: the height of the bar track, the stroke of the ring arc. A spacing token or a whole number of dp. No field (or a token the theme does not declare) — «x-style.layout.progress.defaultThickness». A ring never draws thicker than half of its diameter; zero draws neither the track nor the fill.
trackColor ColorRef no Color of the track — the whole scale under the fill. No field (or a token the theme does not declare) — «x-style.layout.progress.defaultTrackColor».
gradient GradientRef no Gradient of the fill, stronger than «color» while it resolves. It runs along the FILLED part: position 0 — the start of the scale, position 1 — the end of the fill («x-style.layout.progress.gradient»); the angle is not read. No field, an unknown token or unordered stops — the fill is the solid «color».
cap "round" no Ends of the scale (9.21.0). «round» — the ends of the ring arc and of the bar track and fill are half-circles of the thickness, kept INSIDE the filled part: geometry — «x-style.layout.progressCap». No field or an unknown word — square ends of the ring arc and the theme «pill» radius of the bar, exactly as before 9.21.0.
animateChanges true no When the DATA change the value of this node while it is shown, the renderer leads from the old value to the new one (9.21.0): a number of a text with a numeric format counts through the values between, a scale grows. Duration, curve, steps and when there is no transition — «x-valueTransition». No field — the value changes at once, exactly as before 9.21.0.
animateIn true no When the node is SHOWN, its value grows from zero to its own (9.24.0): a number of a text with a numeric format counts up from 0 with the same curve, duration and steps as «animateChanges»; a ProgressBar or CircularProgress fills from empty. Shown — the first show of the screen, a screen shown again («back»), a node that appears (condition, width class, a new record). Rules — «x-valueAppear». No field — the value is there at once, exactly as before 9.24.0.
glow ProgressGlow no
labelTypography TypographyRef no Font style of the label in the center of the ring (9.17.0): a theme token or a token with overrides. No field — «x-style.layout.progress.ring.labelTypography». The label does not scale with the diameter.
labelColor ColorRef no Colour of the label in the center of the ring (9.17.0). No field — «x-style.layout.progress.ring.labelColor».

Badge#

A short label in color that means a state: success, warning, accent. With an icon and its own colors it is the chip of a design: «4 days left», «LIMITED».

Since contract 2.0.0. Holds no children. Extra node fields: pin, showOn, styleOn, motion, pressFeedback.

Property Type Required Default Notes
label BindableString yes
tone "neutral" | "success" | "warning" | "danger" | "accent" yes "neutral"
icon IconToken no Icon beside the label, by the same rule as in a button («x-style.layout.iconBesideText»). No field — no icon.
iconPath IconPath no
iconPosition IconPosition no

How a style is read#

The rules below are the x-style and x-tokens blocks of the schema artifact, in words. They are part of the contract: two renderers that read them differently draw the same document differently.

Box model. Outside is margin; then the box — size, background, border, radius, shadow, opacity; inside it padding; inside that, what the widget draws. A size (width, height) is the size of the box including its border and padding.

  • A node without style has no background, no padding and no radius (hiddenDefaults: "none"). The builder writes the usual look of a card into the document; a renderer adds nothing of its own.
  • Sides and corners are logical — start and end, not left and right (sides: "logical"). A side or corner that is not named is zero (unnamedSide: "zero").
  • A node weight overrides style.width (weightOverridesWidth: true), and a fill layer overrides both style.width and style.height (fillOverridesSize: true). Each size goes together with its min… and max….
  • The share of a row that a weight gives is the whole place of the node, its own margin included (weightShareIncludes): the margin lies inside the share and the box inside the margin. In CSS the element that carries flex: N 1 0 must not be the one that carries the margin.
  • The corner radius clips the background and the content, children included (background, content); the shadow lies outside and is not clipped. opacity applies to background, border, shadow, content together, as one box.
  • The root of a screen has no margin, width, height, minWidth, maxWidth, minHeight, maxHeight (a separate ScreenStyle in the schema). A renderer that receives them ignores them and applies the rest of the style.

States. The first case of styleWhen whose condition holds applies (caseSelection: "first-match"). It is laid over the base style by top-level fields (caseMerge: "top-level-fields"): a case with padding replaces padding as a whole, not side by side. With no matching case the base style applies.

Inheritance. color, typography pass down the tree, after the state is applied (inheritance: "after-case-merge"). At the root of a screen they are color: onSurface and typography: bodyM. A text style is inherited as a whole, not edit by edit.

Inherited field Widgets that read it
color Text, Icon, ListTile, AppBar, Tab, NavItem, Accordion
typography Text

Only Text reads the text style. Button, IconButton and Badge read neither: their look comes from the theme role (below). The composite widgets read the color part by part, from the table below.

Which part reads a named color (colorParts). A primary part takes the color as it is. A secondary part takes the same color with opacity 0.6 (secondaryOpacity): a token becomes a tint of that token, not a value of its own. whenUnnamed says what to draw until nobody has named a color: root — the root onSurface; built-in — the widget's own built-in colors, as before 9.0.0.

Widget Part Emphasis Until a color is named
Text content primary root
Icon glyph primary root
ListTile title primary built-in
ListTile subtitle secondary built-in
ListTile leadingIcon primary built-in
ListTile trailingText primary built-in
ListTile trailingIcon primary built-in
ListTile chevron secondary built-in
AppBar title primary built-in
AppBar subtitle secondary built-in
AppBar backIcon primary built-in
Tab activeTitle primary built-in
Tab inactiveTitle secondary built-in
NavItem activeItem primary built-in
NavItem inactiveItem secondary built-in
Accordion title primary built-in
Accordion chevron secondary built-in

A color counts as named when the node itself or an ancestor sets style.color — even to onSurface. Keep that as a flag in the inheritance context; comparing the color with the root color misses a card that names the root color on purpose. A color the theme does not declare is not named and not inherited: the parent value stays (unknownInheritedToken: keep-parent).

The leading icon of a ListTile is a plain glyph with no disc under it, and it reads the named color (leadingIcon). The photo, the radio circle, the active tab bar and the dividers do not read a named color.

Widgets with a role. The look of these widgets comes from a role of the theme by default (default: "theme-role"):

Widget Property that names the role Group in theme.roles
Button variant buttonVariant
IconButton variant buttonVariant
Badge tone badgeTone
  • The role gives the background, the label color and the border; a role border is 1 logical pixel wide.
  • These fields of the node's own style — base style with the active state — override the role, each one separately (override: "own-style-per-slot"): background, color, border, radius, shadow, padding, typography.
  • They apply to the surface of the widget itself — the button, the pill — and are not applied a second time to the box around it (appliesTo: "widget-surface"). margin, sizes and opacity describe the box, as on every node.
  • A color inherited from an ancestor does not override the role (inheritedColor: "does-not-override-role").

Token names. The theme declares them; the schema checks only the shape of a name: ^[a-z][a-zA-Z0-9]{0,39}$. Every theme has the core names below, and may add up to 64 of its own per dictionary.

Dictionary Core names
color primary, onPrimary, secondary, accent, surface, onSurface, muted, border, success, warning, danger, locked, inProgress, completed
gradient brandBackdrop
spacing none, xs, sm, md, lg, xl
radius none, sm, md, lg, pill
elevation none, low, medium
typography displayL, titleM, titleS, bodyM, bodyS, caption, numericL

The three state colors — locked, inProgress, completed — are listed with the core because a document may always name them, but a theme may leave them out: they have documented fallbacks. See theme.

Gradient geometry (x-gradientGeometry). A custom gradient and a gradient of the theme are drawn in the same way.

  • coordinates: normalized box: (0,0) top-left, (1,1) bottom-right, y grows downwards
  • axis: as CSS: 0 — to top, 90 — to right, 180 — to bottom, 270 — to left; from the middle of one edge to the middle of the opposite edge
  • diagonal: exactly CSS «to <corner>»: 45 — to top right, 135 — to bottom right, 225 — to bottom left, 315 — to top left. The gradient line passes through the center perpendicular to the diagonal joining the two OTHER corners, so the 50% isoline passes through those two corners and the target corner gets position 1
  • formula: for a box w×h and direction signs (sx, sy): end = (0.5 + sx·h²/(w²+h²), 0.5 + sy·w²/(w²+h²)), start is symmetric about the center; in Flutter: Alignment(2x−1, 2y−1)
  • direction: physical: not mirrored in right-to-left scripts
  • equalStops: ordered

What a renderer does with a token the theme does not declare, with a style field it does not know, with gradient stops that go backwards and with a minimum size above the maximum is on the compatibility page.

Shared types#

Types the tables above link to. A token type names a value the project theme declares. A …Ref type accepts a token or a value of the document's own within the limits shown; the token is the shorter form and the one a rebrand moves.

SpacingRef#

One of:

SpacingToken#

Name of a «spacing» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

AlignToken#

One of: "start", "center", "end".

ColorRef#

One of:

  • ColorToken
  • { token: ColorToken, opacity: number 0–1 }
  • { value: string matching ^#[0-9a-f]{6}$, opacity?: number 0–1 }

ColorToken#

Name of a «color» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

TypographyRef#

One of:

TypographyToken#

Name of a «typography» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

TypographyOverride#

Property Type Required Default Notes
token TypographyToken yes
fontSize number 8–96 no
fontWeight integer 100–900 no
lineHeight number 0.8–3 no
letterSpacing number -2–8 no

TextFontStyle#

One of: "normal", "italic".

TextDecoration#

One of: "none", "underline", "lineThrough".

GradientRef#

One of:

GradientToken#

Name of a «gradient» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

CustomGradient#

Property Type Required Default Notes
angle 0 | 90 | 180 | 270 | 45 | 135 | 225 | 315 yes
stops array of object { color, position } (min 2, max 8) yes

BoxSpacing#

One of:

SpacingSides#

Property Type Required Default Notes
top SpacingRef no
end SpacingRef no
bottom SpacingRef no
start SpacingRef no

BoxRadius#

One of:

RadiusRef#

One of:

RadiusToken#

Name of a «radius» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

RadiusCorners#

Property Type Required Default Notes
topStart RadiusRef no
topEnd RadiusRef no
bottomEnd RadiusRef no
bottomStart RadiusRef no

NodeBorder#

Property Type Required Default Notes
width number 0.5–16 yes
color ColorRef yes
style "dashed" no Line of the border (9.22.0). «dashed» — dashes of 3 and gaps of 2 border widths along the centre line of the border, following the corner arcs; the count closes the loop evenly. Rules — «x-style.layout.borderDash». No field or an unknown word — solid, exactly as before 9.22.0.

NodeBackground#

One of:

ImageSource#

One of:

  • { kind: "asset", asset: AssetToken }
  • { kind: "url", url: string (length 0–2048) }
  • { kind: "binding", path: non-empty string, fallback: AssetToken }

AssetToken#

One of: "logo", "banner", "placeholder".

ShadowRef#

One of:

ElevationToken#

Name of a «elevation» token of the project theme. The schema checks only the shape of the name; whether the theme declares it is a semantic rule checked against the active theme.

string matching ^[a-z][a-zA-Z0-9]{0,39}$.

CustomShadowLayer#

Property Type Required Default Notes
offsetX number -64–64 yes
offsetY number -64–64 yes
blur number 0–128 yes
spread number -64–64 yes
color ColorRef yes

ShadowColor#

Colour of the shadow (9.25.0): «background» — every layer of «shadow» (a token or own layers) takes the hue of the own background of this node, keeping the opacity of the layer: a solid background gives its colour, a gradient the stop nearest to its middle. No background, an image background or a colour that does not resolve — the shadow keeps its own colour. Rules — «x-shadowColor». No field — the shadow keeps its own colour, exactly as before 9.25.0.

One of: "background".

VisibilityCondition#

One of:

UnaryVisibilityCondition#

Property Type Required Default Notes
path non-empty string yes
op "isTrue" | "isFalse" | "isEmpty" | "isNotEmpty" yes

EqualityVisibilityCondition#

Property Type Required Default Notes
path non-empty string yes
op "eq" | "neq" yes
value string (length 0–128) | number | boolean yes

OrderVisibilityCondition#

Property Type Required Default Notes
path non-empty string yes
op "gt" | "gte" | "lt" | "lte" yes
value number yes

PathComparisonCondition#

Property Type Required Default Notes
path non-empty string yes
op "eq" | "neq" | "gt" | "gte" | "lt" | "lte" yes
valuePath non-empty string yes The operand is the value under this OTHER data path (9.23.0), read in the same scope as «path»: «reward.category eq ui.rewardsCategory». No value under it (or the empty string) — see «x-listFilter.operandMissing».

FilteredEmptinessCondition#

Property Type Required Default Notes
path non-empty string yes
op "isEmpty" | "isNotEmpty" yes
item non-empty string yes Prefix of a record of the collection, as «Repeater.item» (9.23.0).
where ListWhereCondition yes Count only the records for which this condition holds (9.23.0) — the same predicate as «Repeater.where». Rules — «x-listFilter.emptiness».

ListWhereCondition#

One of:

BindableString#

One of:

BindingFormat#

One of: "date", "dateTime", "time", "number", "currency", "daysUntil", "countdownPart".

CurrencyCode#

An ISO 4217 currency code: three capital letters (USD, JOD). Required exactly when format is currency.

string matching ^[A-Z]{3}$.

CurrencyDisplay#

Money (9.19.0): symbol shows the currency by its sign from «x-money.symbols» instead of the code. A code the table does not have is shown as the code. Only with format: currency. No field — the code.

One of: "symbol".

CurrencyPosition#

Money (9.19.0): before puts the currency before the amount — a sign with no gap, a code with U+00A0. Only with format: currency. No field — after the amount, with U+00A0.

One of: "before".

NumberSign#

Sign of a number (9.19.0): always writes «+» before a positive number. Zero has no sign. With format: number or currency. No field — a negative number only, as the platform writes it.

One of: "always".

DateParts#

Which parts of a date to show, beside «format: date» (9.19.0): «dayMonth» — day and month in full, no year; «weekdayDayMonth» — the day of the week, day and month in full; «dayMonthYear» — day, month in full and year. Order and separators come from CLDR for the formatting locale. Rules — «x-dateParts». No field — year, short month and day, exactly as before 9.19.0. A word the renderer does not know — the field is absent.

One of: "dayMonth", "weekdayDayMonth", "dayMonthYear".

CountdownUnit#

Which part of the time left the «countdownPart» format shows (9.21.0): «days» — whole days; «hours» — 0–23; «minutes» — 0–59; «seconds» — 0–59. Required exactly when «format» is «countdownPart». Arithmetic, ticking and the clock — «x-countdown».

One of: "days", "hours", "minutes", "seconds".

NumberNotation#

Compact number (9.23.0): «compact» writes 48 200 as «48.2K» (en) or «48,2 тис.» (uk) — one fraction digit, half up, suffixes from a closed table by language. Only with «format: number». Rules — «x-compactNumber». No field — every digit.

One of: "compact".

NodeStyle#

Property Type Required Default Notes
color ColorRef no
typography TypographyRef no
fontStyle TextFontStyle no Slant of the text (9.17.0). Inherited down the tree like «typography»; read by Text only. «normal» cancels an inherited italic.
textDecoration TextDecoration no Line under or through the text (9.17.0), in the colour of the text. Inherited down the tree; read by Text only. «none» cancels an inherited line.
textGradient GradientRef no Gradient painted on the GLYPHS of the text (9.23.0): a gradient token of the theme or an own gradient of the same form as a gradient «background». It lies over the whole content box of the text, not line by line; a part of the text that names its own colour keeps it. «color» stays the fallback: an older renderer and a gradient that does not resolve paint the text with it. Not inherited; read by Text only. Rules — «x-textGradient».
padding BoxSpacing no
margin BoxSpacing no
width Dimension no
height Dimension no
minWidth Dimension no
maxWidth Dimension no
minHeight Dimension no
maxHeight Dimension no
radius BoxRadius no
border NodeBorder no
background NodeBackground no
shadow ShadowRef no
shadowColor ShadowColor no
opacity number 0–1 no
backdropBlur integer 1–40 no Blur of whatever is painted UNDER the box of this node, clipped by its «radius» (9.20.0) — frosted glass on a card, a navigation bar or a button. Logical pixels, the standard deviation of a Gaussian blur; the node own background lies over the blur, the node and its children are never blurred. Not inherited. No field — no blur. Rules — «x-backdropBlur.style».

Dimension#

One of:

  • number 1–1200
  • { kind: "binding", path: non-empty string, fallback: number 1–1200 }

StyleCase#

Property Type Required Default Notes
when VisibilityCondition yes
style NodeStyle yes

NodeWeight#

Share of the row width this child takes. Children with a weight split the row in proportion to their weights; children without one keep their natural width. A weight overrides the widget own width. Legal only inside a row of finite width: the «Row» widget without «wrap» and without «scrollable», or a «Container» with direction «row». No field — the child keeps its natural width, exactly as before 8.17.0.

integer 1–4.

NodeLayer#

Placement of this layer inside a «Stack» (9.10.0). A layer with this field is an OVERLAY: it is positioned against the box of the stack and never changes the size of the stack. «alignHorizontal» / «alignVertical» — its own alignment (no key — the alignment of the stack); «offset» — a shift from that place along the axes of the stack («x.toward»: start | end, logical; «y.toward»: top | bottom; «by» — a spacing token or logical pixels); «rotate» — whole degrees clockwise about the centre of the layer, mirrored in RTL. The layer may stick out of the stack; who clips it and where it catches a tap — «x-style.layout.layer». Legal only on a direct child of «Stack» and not together with «fill». No field — an ordinary layer, exactly as before 9.10.0.

Property Type Required Default Notes
alignHorizontal AlignToken no
alignVertical AlignToken no
offset LayerOffset no
rotate integer -180–180 no

LayerOffset#

Property Type Required Default Notes
x object { toward, by } no
y object { toward, by } no

NodePull#

Pulls this child towards the START of the main axis of its parent by this much (9.10.0): the child and everything after it move, so the child lies OVER what precedes it and the parent gets shorter by the same amount. The gap of the parent stays: the overlap is «pull» minus the gap. A spacing token or logical pixels. Legal only where children follow one another: «Screen», «Column», «Container», and a «Row» without «wrap» and without «scrollable»; not together with «weight». Rules — «x-style.layout.pull». No field — the child stands where the flow puts it, exactly as before 9.10.0.

SpacingRef.

PressAction#

Makes the whole container pressable (9.19.0): the same action form and the same execution path as a button. The container is a control when the action type is not «none» or the action carries «track». A control inside it (a button, an input, a choice option, a list row with an action) takes its own press — the container gets the rest of its box. No field — a plain container, exactly as before 9.19.0.

ButtonAction.

ButtonAction#

Property Type Required Default Notes
type string (length 1–64) yes
params object no
paramBindings object no Parameter name → data-contract path. At press time the renderer reads the path with the data scope of the node; a non-empty string replaces the literal in «params», anything else leaves the literal (the fallback).
carryRecord true no Only on «navigate»: the opened screen gets the record scope of this node even when it is a page opened from outside a list row. Absent — the rule of 9.2.0.
track ActionTrack no
haptic "light" | "medium" | "heavy" | "selection" | "success" | "warning" no Haptic feedback of the press (9.25.0) — a REQUEST to the host, like «track»: the renderer never vibrates by itself, it hands the word to the host once per press, before the action and next to the analytics event. «light», «medium», «heavy» — an impact; «selection» — a change of choice; «success», «warning» — an outcome. Rules — «x-haptic». No field — no request.

ActionTrack#

Analytics event of the press. Handed to the host once per press, before the action is performed, with the same source as the action. Not an action: any action may carry it.

Property Type Required Default Notes
event string matching `^(?!(?:constructor prototype)$)[A-Za-z][A-Za-z0-9_]*$` yes
params object no

PressLabel#

Hidden accessible name of a pressable container (9.19.0): read first, before the text of its content. Required when nothing inside the container says anything without data.

BindableString.

LongPressAction#

Long press of the node (9.26.0): the same action form and execution path as «action». It fires while the finger is still down, once it has stayed within the touch slop for the threshold of «x-longPress»; the press of «action» then does not happen. Only on a pressable container and on ListTile — never on a button. Requires «longPressLabel». No field — no long press.

ButtonAction.

LongPressLabel#

Name of the long press action for assistive technologies (9.26.0): a named custom action of the node, the context menu key and Shift+F10. Required when «longPress» does something. Translatable.

BindableString.

Property Type Required Default Notes
perView integer 1–6 no How many WHOLE cards the viewport shows; every card then has the same width — (viewport − inline-start padding − perView × gap − peek) ÷ perView — and its own «style.width» is not read. No field — cards keep the width a scrolling row gives them («x-style.layout.scrollableRow»).
peek SpacingRef no How much of the NEXT card shows at the inline end of the viewport. Read only with «perView». No field (or a token the theme does not declare) — «x-style.layout.carousel.card.defaultPeek».
indicator "dots" | "none" no The dots under the carousel: one per snap stop, the active one follows the scroll. No field or an unknown word — «x-style.layout.carousel.indicator.default».

ContainerDirection#

One of: "column", "row".

BindableString64#

One of:

Orientation#

The axis of a «Spacer» or a «Divider», named after the SHAPE of the widget, not after the layout around it. «horizontal»: the divider is a horizontal line and the spacer adds HEIGHT — the form used inside a column. «vertical»: the divider is a vertical line and the spacer adds WIDTH — the form used inside a row. The container dictates the axis: a column needs «horizontal», a row needs «vertical».

One of: "horizontal", "vertical".

TextMarker#

One of: "none", "bullet", "number".

ImageRatio#

Proportion of the image frame: a word of the list or an own «width : height» pair (9.9.0). It gives the HEIGHT of the box from its width, and only when «style.height» does not name it: a named size of the node box is stronger («x-style.layout.image»). A renderer that does not know the value uses «16:9».

One of:

CustomImageRatio#

Own proportion of the image frame: «width» to «height», two integers. Only their RATIO matters — «343 × 120» and «686 × 240» are the same frame. The ratio must stay within «x-style.layout.image.ratioRange»; a renderer clamps what is outside it.

Property Type Required Default Notes
width integer 1–1200 yes
height integer 1–1200 yes

AltText#

Description for a screen reader. A plain string — the text in the default language of the document, translated under the key of the field itself (<screenId>/<nodeId>/alt); or, from 9.19.0, a string of the document — a binding to data or a template, read and translated as any other. A wrapped literal equals the plain string. A renderer older than 9.19 hears the plain string and reads an object as «no description».

One of:

IconToken#

One of: "star", "trophy", "gift", "target", "clock", "check", "chevron", "user", "info", "lock", "accessibility", "activity", "alarm-clock", "anchor", "apple", "archive", "arrow-down", "arrow-down-left", "arrow-down-right", "arrow-left", "arrow-right", "arrow-up", "arrow-up-left", "arrow-up-right", "award", "baby", "backpack", "badge-check", "badge-dollar-sign", "badge-percent", "ban", "bandage", "banknote", "battery", "battery-charging", "battery-full", "bed", "beer", "bell", "bell-off", "bell-ring", "biceps-flexed", "bike", "bird", "book", "book-open", "bookmark", "bookmark-check", "bot", "box", "briefcase", "building", "bus", "cake", "calculator", "calendar", "calendar-check", "calendar-clock", "calendar-days", "calendar-plus", "camera", "car", "cat", "chart-bar", "chart-column", "chart-line", "chart-pie", "check-check", "cherry", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-down", "chevrons-left", "chevrons-right", "chevrons-up", "circle", "circle-alert", "circle-arrow-down", "circle-arrow-left", "circle-arrow-right", "circle-arrow-up", "circle-check", "circle-chevron-left", "circle-chevron-right", "circle-dollar-sign", "circle-help", "circle-minus", "circle-percent", "circle-play", "circle-plus", "circle-star", "circle-user", "circle-x", "clipboard", "clipboard-list", "clock-alert", "cloud", "cloud-download", "cloud-lightning", "cloud-rain", "cloud-snow", "cloud-sun", "cloud-upload", "code", "coffee", "coins", "compass", "contact", "cookie", "copy", "credit-card", "crown", "database", "diamond", "dice-5", "dices", "dog", "dollar-sign", "door-open", "download", "droplet", "dumbbell", "ellipsis", "ellipsis-vertical", "euro", "external-link", "eye", "eye-off", "file", "file-plus", "file-text", "fingerprint-pattern", "fish", "flag", "flame", "flower", "folder", "folder-open", "folder-plus", "footprints", "forward", "frown", "fuel", "funnel", "gamepad-2", "gauge", "gem", "glasses", "globe", "goal", "graduation-cap", "hamburger", "hand", "hand-coins", "hand-heart", "handshake", "headphones", "headset", "heart", "heart-handshake", "heart-pulse", "history", "hospital", "hotel", "hourglass", "house", "ice-cream-cone", "id-card", "image", "images", "inbox", "infinity", "key", "lamp", "landmark", "languages", "laugh", "layout-grid", "layout-list", "leaf", "lightbulb", "link", "list", "list-checks", "list-ordered", "loader-circle", "lock-open", "log-in", "log-out", "luggage", "mail", "mail-open", "map", "map-pin", "medal", "megaphone", "menu", "message-circle", "message-square", "mic", "minus", "monitor", "moon", "mountain", "music", "navigation", "newspaper", "package", "package-check", "package-open", "paintbrush", "palette", "paperclip", "party-popper", "pause", "paw-print", "pencil", "percent", "phone", "phone-call", "piggy-bank", "pill", "pin", "pizza", "plane", "plane-landing", "plane-takeoff", "play", "plus", "podium", "popcorn", "pound-sterling", "printer", "puzzle", "qr-code", "rainbow", "receipt", "recycle", "redo", "redo-2", "refresh-ccw", "refresh-cw", "repeat", "reply", "ribbon", "rocket", "rotate-ccw", "rotate-cw", "route", "save", "scale", "scan", "scan-face", "school", "scissors", "search", "send", "settings", "share", "share-2", "shield", "shield-check", "ship", "shirt", "shopping-bag", "shopping-basket", "shopping-cart", "shuffle", "signpost", "skip-back", "skip-forward", "sliders-horizontal", "smartphone", "smile", "snowflake", "sofa", "sparkles", "sprout", "square-check", "square-pen", "star-half", "stethoscope", "store", "sun", "tag", "tags", "tent", "thermometer", "thumbs-down", "thumbs-up", "ticket", "ticket-check", "ticket-percent", "tickets", "timer", "timer-reset", "toggle-left", "toggle-right", "train-front", "trash-2", "tree-pine", "trending-down", "trending-up", "triangle-alert", "truck", "tv", "umbrella", "undo", "undo-2", "upload", "user-check", "user-plus", "user-round", "user-x", "users", "utensils", "video", "volume-2", "volume-x", "wallet", "wand-sparkles", "watch", "waves", "wifi", "wifi-off", "wind", "wine", "wrench", "x", "zap".

IconPath#

Path in the data dictionary that holds the NAME of an icon of the contract icon set (9.19.0). The name of the document stays beside it: it is drawn when the data has no value (absent, null, an empty string) and by a renderer older than 9.19. A name that is not in the set, or a value that is not a string, is an empty box of the same size. Never an address or a drawing. Rules — «x-iconFromData». No field — the icon of the document, exactly as before 9.19.0.

string (length 1–128).

IconPosition#

Where the icon stands relative to the text beside it, in READING order: «start» — before the text (on the left in LTR, on the right in RTL), «end» — after it. The renderer never swaps the two by itself; the direction of the script does. No field — «start» («x-style.layout.iconBesideText.defaultPosition»). Without an icon the field means nothing.

One of: "start", "end".

ButtonSize#

Size of a button. The padding and the text style of each size are data of the contract («x-style.layout.buttonSizes»), expressed in theme tokens. No field — «md» («x-style.layout.defaultButtonSize»), the button as it was before 9.5.0.

One of: "sm", "md", "lg".

ListTileLeading#

One of:

ListTileLeadingTile#

A tinted square (or circle — radius «pill») under the leading icon of a list row (9.19.0). The tile takes the place of the icon in the row; the gap to the texts is unchanged. Rules — «x-style.layout.listTileParts.leading.tile».

Property Type Required Default Notes
color ColorRef yes Background of the tile: a token, a token with opacity («10 % of the brand colour») or an own colour.
radius RadiusRef no Radius of the tile: a token or a number. No field — «sm», the radius of the leading image.
size integer 24–96 no Side of the square tile in logical pixels. No field — 40. The glyph keeps its size and stands in the centre.

ListTileTrailing#

One of:

PartStyle#

Colour and typography of ONE part of a composite widget (9.19.0), named apart from the node: token or own value, like a field of «style». A field that is not named is not applied: the part keeps what it had (the named colour of the node or the built-in one). A token the theme does not know — the field is skipped. Rules — «x-style.layout.partStyle».

Property Type Required Default Notes
color ColorRef no
typography TypographyRef no

PartStyleCase#

One state of a part: the condition of the same form as «visibleIf» and the style laid over the base style of the part while it holds.

Property Type Required Default Notes
when VisibilityCondition yes
style PartStyle yes

BindableNumber#

One of:

  • { kind: "literal", value: number }
  • { kind: "binding", path: non-empty string, fallback: number }

ProgressGlow#

Glow of the FILLED part of the scale (9.25.0): a blurred copy of the fill under it, in its own colour or gradient — «soft» or «strong», numbers in «x-progressGlow». A bar with steps lights one step: the current one when «currentColor» paints it, otherwise the last step with any fill. It changes no layout and is not clipped by the own box of the node. No field or an unknown word — no glow, exactly as before 9.25.0.

One of: "soft", "strong".

InputValue#

Where an input reads its value and writes the change: a path of the data contract. Read through the data layers («x-dataScope.layers»); written to the session of the renderer and handed to the host. No literal and no fallback: an input without data is empty (a toggle is off).

Property Type Required Default Notes
kind "binding" yes
path non-empty string yes

TextFieldValueType#

What a text field holds and writes. «number» — a path of type number, the numeric keyboard, a JSON number is written («x-style.layout.form.number»). No field or an unknown word — «string».

One of: "string", "number".

InputKeyboard#

Intent of the screen keyboard of a text field, not a platform attribute: what each word becomes on the web and in Flutter is data («x-style.layout.inputs.textField.keyboards»). No field or an unknown word — «text». Not read by a multiline field.

One of: "text", "email", "number", "phone", "url".

FieldAffix#

A mark inside the box of a text field (9.19.0): a short text («₴», «kg») or an icon, at the logical start («prefix») or end («suffix») of the box by the direction of the SCREEN. It is not part of the value and is never written. Rules — «x-style.layout.inputParts.affix».

One of: