Components
XML v2 exposes a small, data-oriented Astryx component set. The old HTML aliases and compound slot tags are not supported. Use component attributes for labels, values, and state, then compose components with Stack, Grid, Card, and FormLayout.
Every interactive control needs an accessible label or i18n value. Localized interpolation data belongs in one values expression object; arbitrary placeholder attributes are rejected by the schema.
Text, Heading, and Code
Text replaces paragraph and inline HTML aliases. Heading requires an explicit semantic level from 1 to 6. Both accept literal value, localized i18n, or nested XML content. Code renders inline code with the same content precedence.
values: expression resolving to an object used for translation placeholders.count: numeric expression used for plural translation entries.Text as:span,p,div, orlabel.Text type:body,large,label,supporting,code, a display style, orinherit.
xml<Heading level="1" i18n="orders.title" /><Text as="p" i18n="orders.summary" values="${{ number: order.number, status: order.status }}" /><Code value="$order.reference" />
Link
Link replaces the old anchor alias. Use to for application navigation and href for a URL. External destinations can set isExternalLink; translated link text uses i18n.
xml<Link to="/orders/${order.id}" i18n="orders.open" hasUnderline="true" /><Link href="$document.downloadUrl" i18n="documents.download" isExternalLink="true" />
Icon
Icon renders a semantic Astryx icon name rather than a Lucide slug. Common names include info, success, warning, error, search, and wrench.
xml<Icon icon="info" size="sm" color="accent" />
Avatar
Avatar is a single data-oriented element. Set its image, fallback image, name, and alternative text as attributes instead of using image and fallback children. Sizes are tiny, xsmall, small, medium, and large.
xml<Avatar src="$user.avatarUrl" name="$user.name" alt="$user.name" size="medium" />
Badge
Badge requires a serializable label or an i18n key. Status variants include neutral, info, success, warning, and error.
xml<Badge label="$order.status" variant="info" />
Banner
Banner displays persistent status information. It requires a title or i18n key and can expand to show child content.
xml<Banner status="warning" i18n="orders.reviewRequired"><Text i18n="orders.reviewInstructions" /></Banner>
Divider
Divider replaces the horizontal-rule alias. It supports horizontal or vertical orientation, optional translated labels, and subtle or strong variants.
xml<Divider i18n="common.or" variant="strong" />
Button and ButtonGroup
Button requires a label or i18n key. Use isDisabled, isLoading, and isIconOnly for state. ButtonGroup accepts Button or Action children and also requires an accessible group label.
variant:primary,secondary,ghost, ordestructive.type:button,submit, orreset.appendanditem: append a resolved item to array state before running the nearest Action.
xml<ButtonGroup label="Order actions"><Action action="/api/orders/${order.id}/approve" method="PATCH"><Button variant="primary" i18n="orders.approve" /></Action><Button isDisabled="$order.locked" i18n="orders.edit" /></ButtonGroup>
TextInput, NumberInput, FileInput, and TextArea
These controls replace Input, Textarea, Field, and InputGroup compounds. Each control owns its label, description, validation status, and value. A $state.path value creates a writable binding.
labelori18n: required accessible field label, even whenisLabelHiddenis true.isRequired,isOptional,isDisabled: explicit field states.status:warning,error, orsuccess, with optionalstatusMessage.- NumberInput writes numbers. FileInput keeps File values available to Action
formpayloads.
xml<State id="draft" title="" amount="0" notes="" file="${null}" /><FormLayout><TextInput i18n="orders.fields.title" value="$draft.title" isRequired="true" /><NumberInput i18n="orders.fields.amount" value="$draft.amount" min="0" units="CHF" /><TextArea i18n="orders.fields.notes" value="$draft.notes" rows="4" /><FileInput i18n="orders.fields.attachment" value="$draft.file" accept=".pdf" /></FormLayout>
CheckboxInput, Switch, and Slider
Boolean and range controls also bind through value. Use a State object with a value field when the control owns the entire state slot.
xml<State id="accepted" value="false" /><State id="notifications" value="true" /><State id="budget" value="2500" /><CheckboxInput label="Accept terms" value="$accepted" isRequired="true" /><Switch label="Notifications" value="$notifications" /><Slider label="Budget" value="$budget" min="500" max="10000" step="500" />
Selector
Selector replaces the Select compound. It requires an accessible label and one or more flat SelectorOption children. Each option requires a value and uses label or i18n for visible text.
xml<State id="filters" status="open" /><Selector i18n="filters.status" value="$filters.status" hasClear="true"><SelectorOption value="open" i18n="statuses.open" /><SelectorOption value="closed" i18n="statuses.closed" /></Selector>
RadioList
RadioList replaces RadioGroup and contains flat RadioListItem children. The list and every item require accessible labels.
xml<State id="workflow" owner="manager" /><RadioList i18n="workflow.owner" value="$workflow.owner"><RadioListItem value="manager" i18n="workflow.roles.manager" /><RadioListItem value="finance" i18n="workflow.roles.finance" /></RadioList>
Table
Table replaces DataTable and its slot compounds. It consumes array data and flat TableColumn children. Every column needs a key or dotted field; use an explicit key for custom cells. Child content becomes the cell renderer and can read the configured row name, index, and value.
data: required expression resolving to an array of objects.rowName: row variable exposed to custom cells. Defaults torow.idKey: optional stable row identifier field.emptyLabel: literal empty-state text.
xml<Query id="orders" path="/api/orders" /><Table data="$orders" rowName="order" idKey="id" emptyLabel="No orders found."><TableColumn key="number" field="number" i18n="orders.table.number" /><TableColumn key="customer" i18n="orders.table.customer"><Link to="/orders/${order.id}" i18n="orders.open" /></TableColumn><TableColumn key="status" i18n="orders.table.status"><Badge label="$order.status" variant="info" /></TableColumn></Table>