Language reference

Every statement a .milda file can contain: where it may stand, how it is spelled, what it means, what the document stores, and what happens when it is left out. Use it to read a file you exported, or to check what a word means.

The other language pages explain the ideas - values, facets & tokens, layout, behaviors, archetypes. This page is for looking things up. It is checked against the parser, so a keyword the language accepts cannot be missing here, and every example on it parses.

#Index

#Lexical basics

Everywhere in the file.

# text to the end of the line

A comment. Everything from # to the end of the line is ignored, which is why a hex colour is written hex(3b82f6) rather than #3b82f6.

Comments are not carried: a file that is read and written back loses them. Anything that should survive a round trip has a statement of its own - a description string, a meta entry, a note.

milda
# Brand colours, from the 2026 refresh
milda 0.10

Explained on The .milda file

See also milda, meta

statement ; statement   |   statement <newline> statement

A statement ends at a newline or a semicolon. The two are interchangeable, so a short block can stay on one line.

milda
part Toolbar: container {
  layout { stack row; gap space.sm; align center }
}

Explained on The .milda file

name . name …

A dotted path addresses something by name: a token (space.sm), a part (Header.Title), a context value. A token NAME may be written with / (space/sm); a reference to it uses dots.

Nothing in a .milda file is addressed by a database id. Every reference is a name the file itself declares, so the file resolves on its own.

milda
token space/sm : spacing = 8px
token gap/default : spacing = alias by Density { default -> space.sm }

Explained on The .milda file

left -> right   |   left → right

The arrow maps one thing to another: a context to a token in an alias, a predicate to a value in a content block, one end of a wire to the other. -> and → are the same token.

milda
token violet/500 : color = hex(8b5cf6)
token violet/600 : color = hex(7c3aed)
token accent : color = alias by ColorScheme { default -> violet.600; Dark -> violet.500 }

Explained on The .milda file

See also alias, content, wire

#File header

At the top level, usually first.

milda <version>

Which version of the surface syntax the file is written in. Bumped whenever the grammar gains capability, so a reader can tell "this file predates motion" from "this file has no motion".

Today the version is recorded, preserved and printed, but nothing gates on it: a newer construct is read whatever the header says.

When omitted
The reader assumes the current surface version, and the printer writes that. A file that does not say is not treated as an old file.
Stored as
document.milda
milda
milda 0.10

Explained on The .milda file

See also prelude

prelude <version>

Which version of the prelude - the built-in archetypes and behaviour atoms - the file was authored against.

When omitted
The current prelude version.
Stored as
document.prelude
milda
milda 0.10
prelude 0.0.2

Explained on The .milda file

meta

proposal 0026
meta { <key> <value> … }

Descriptive metadata. At the top level, name, version and description describe the design system itself and every other key becomes a project metadata entry. Inside a component it is the component’s metadata.

A value is a string, a number, true/false, a bare word, or a list in [ ].

A component is declared with an identifier, so a component whose display name is free text ("Color picker") carries that name as meta { name "Color picker" }.

Stored as
document.meta, foundations.metadata[], component.meta
milda
meta {
  name "Acme"
  version "2.1.0"
  tags [web, ios]
}

Explained on The document

#Foundations and tokens

At the top level (context-group, foundations), and inside foundations { }.

context-group

proposal 0001
context-group <Name> { <Context> … }

A dimension a token can answer differently along: colour scheme, density, platform, brand. Its members are the contexts. A token chooses per context with alias by <Name>, and a prop typed by the group chooses the context per instance.

Stored as
foundations.contextGroups[]
milda
context-group ColorScheme { Light Dark }

Explained on Tokens & context

See also alias, Type expressions

foundations { token … | layer <Name> { token … } … }

The design tokens. Tokens written directly inside it land in a default layer; layer blocks give them an authored order.

Stored as
foundations.layers[].tokens[]
milda
foundations {
  token space/sm : spacing = 8px
}

Explained on Tokens & context

See also layer, token

layer

proposal 0006
layer <Name> { token … }

A named layer of tokens, such as primitives and then the semantic tokens that alias them. Declaration order is layer order.

When omitted
Every token goes into one default layer. A fully layered file gains no empty default layer.
Stored as
foundations.layers[]
milda
layer Base {
  token violet/600 : color = hex(7c3aed)
}
layer Semantic {
  token accent : color = alias by ColorScheme { default -> violet.600 }
}

Explained on Tokens & context

token <name> : <type> = <value> [ "description" ]

Declares a design token. The type is a closed word that decides what the value means, so 1.5 is a ratio for a ratio token and an error for a spacing one.

A length type (spacing, radius, size, border, font-size, letter-spacing) needs a unit: 8px, or scaled(1.25) for a length relative to the reader’s text size. A bare number is rejected there.

The trailing string is the token’s description, which the docs show next to it.

Older spellings are still read and never written: dimension for size, line-height and number for ratio, camelCase forms such as fontSize.

color
A colour, written with a colour function: hex(…), oklch(…), rgb(…).
spacing
A gap or padding length.
radius
A corner radius. pill means fully rounded.
size
A length for a width or height.
border
A border width.
font-size
A text size.
letter-spacing
Tracking.
font-weight
A numeric weight, 100 to 900.
font-family
A font family record: family, fallback, source, licence, asset.
typography
A text style record: family, size, weight, line height, letter spacing.
ratio
A unitless ratio, such as a line height of 1.5.
duration
A time: 120ms, 0.2s.
easing
A timing curve.
opacity
A transparency from 0 to 1.
shadow
A shadow.
elevation
Depth. Each platform realizes it its own way (shadow, tonal surface, nothing).
tonal
A tonal elevation step.
ring
A focus-indicator colour.
backdrop
A colour behind a layer (a scrim).
blur
A blur radius.
gradient
A gradient.
none
The explicit absence of a value, typically one platform’s slot of an alias.
Stored as
foundations.layers[].tokens[] { name, type, value, description }
milda
token space/md : spacing = 12px "Default gap between related controls"
token leading/normal : ratio = 1.5

Explained on Tokens & context

See also Literals, alias, compute

#Token values

After the = of a token declaration, and in the slots of an alias block.

hex(…) | oklch(…) | srgb(…) | rgb(…) | p3(…) | hsl(…) | <n>px | scaled(<n>) | <n>ms | <n> | pill | transparent

A value written as itself. Literals type themselves: a colour function is a colour, a number with a unit is a length or a time, a bare number takes the meaning the token’s type gives it. The full table is on the Values & literals page.

px and dp are the same density-independent unit; rem and sp are read as text-scaled lengths and written as scaled(n). rgba/hsla are read as rgb/hsl.

hex
sRGB as 3, 4, 6 or 8 hex digits: hex(3b82f6).
oklch
Perceptual lightness, chroma and hue.
srgb
sRGB channels in 0..1.
rgb
sRGB channels in 0..255.
p3
Display-P3 channels in 0..1, a wider gamut than sRGB.
hsl
Hue, saturation, lightness.
scaled
A length relative to the reader’s text size: scaled(1.25).
transparent
No colour at all.
pill
A radius that fully rounds the shorter side.
px
A density-independent length. Canonical; what the printer writes.
dp
The same unit as px, read for authors coming from Android.
rem
Read as a text-scaled length and written back as scaled(n).
sp
The same as rem.
ms
Milliseconds.
s
Seconds.
milda
token brand : color = oklch(0.62 0.19 256)
token radius/round : radius = pill
token fast : duration = 120ms

Explained on Values & literals

See also token

raw <value> | raw { <field>: <value>; … }

An explicit typed value. Needed for an opaque string (a shadow or easing written out) and for the structured records of font-family and typography; a bare { … } record may omit the keyword.

A typography record is a text style when it names a family: a font-family token path, or a font-family record written in place. Without one it is carried as an opaque value.

Stored as
token.value = { kind: "raw", value }
milda
token standard : easing = raw "cubic-bezier(0.2, 0, 0, 1)"
token font/sans : font-family = { family: "Inter"; fallback: sans-serif; source: google; license: "OFL-1.1" }
token body : typography = { family: font.sans; size: 15px; weight: 400; line-height: 1.5 }

Explained on Values & literals

alias by <ContextGroup> { default -> <value>; <Context> -> <value>; … }

A token whose value depends on a context. Each slot names a context of the group (or default) and points at another token, a literal, or a compute.

default is the fallback for every context the block does not name.

A literal or compute in a slot is stored as a token of its own and printed back inline; the reader notes each one with an inline-literal message.

Writing a bare token path after = (token on-accent : color = white) is sugar for an alias with only a default slot, and the reader says so with a ref-sugar warning.

Stored as
token.value = { kind: "alias", by, refs }
milda
token white : color = hex(ffffff)
token slate/900 : color = hex(0f172a)
token surface : color = alias by ColorScheme {
  default -> white
  Dark -> slate.900
}

Explained on Tokens & context

See also context-group

escape "platform text" [ note "why" ]

A platform-specific value the language cannot express, carried verbatim. It marks the token as partial: a target that cannot read the string has nothing to fall back on, so use it as a last resort and say why in the note.

Stored as
token.value = { kind: "escape", raw, note }
milda
token tint : color = escape "color-mix(in srgb, red 40%, blue)" note "web only, until compute can mix in srgb"

Explained on Values & literals

compute

proposal 0044
compute <base> [ in <space> ] { <step> … }

A value derived from another one, live: "the accent, 20% lighter". When the base changes, the result follows. The steps that are legal depend on the token’s type, so a colour step on a length is an error, not a no-op.

The base is a token path, a literal, or another compute.

in <space> picks the colour space the maths happens in: srgb, display-p3, oklch, hsl, oklab, lab, lch. It is wider than the set a literal can be written in, because the maths space and the spelling space are different questions.

A literal base is stored as a token of its own, like a literal in an alias slot.

A fraction is written as a percentage or a number: 20% and 0.2 are the same step.

lighten
Colour: raise lightness by a fraction.
darken
Colour: lower lightness by a fraction.
saturate
Colour: raise saturation by a fraction.
desaturate
Colour: lower saturation by a fraction.
alpha
Colour: set the opacity.
rotate
Colour: turn the hue by degrees: rotate 30deg.
mix
Colour: blend with another operand by a fraction.
scale
Length: multiply.
offset
Length: add a length (2px).
round
Length: round to a multiple of a length.
Stored as
token.value = { kind: "compute", base, ops, space }
milda
token accent : color = hex(7c3aed)
token accent-hover : color = compute accent in oklch { darken 10% }
token space/sm : spacing = 8px
token space/lg : spacing = compute space.sm { scale 2 }

Explained on Tokens & context

#Types

At the top level (type), and wherever a type is expected: a prop, a demo variable, a part value.

type <Name> = <type expression>

A shared type, declared once and used by name in any prop. A bare name in a type position resolves to a shared type or, failing that, to a context group.

Stored as
foundations.sharedTypes[]
milda
type Option = object {
  label : string
  value : string
  disabled? : boolean
}

Explained on Components, parts & the contract

See also Type expressions

string | number | boolean | enum(a, b) | ref <Name> | array<T> | object { f : T; g? : T } | union(T, U) | component[(A, B)] | context <Group> | <Name>

What a prop, a demo variable or a part value holds. These are neutral types: each target maps them to its own (a TypeScript union, a Swift enum).

string
Text.
number
A number.
boolean
true or false.
enum
One of a fixed set of words: enum(primary, secondary).
ref
A shared type by name: ref Option.
array
A list: array<string>.
object
A record of fields; ? after a field name makes it optional.
union
Any one of several types.
component
A slot for a component instance, optionally only the listed ones: component(Icon, Avatar).
context
A context of a context group, chosen per instance: context Size. A bare group name means the same.
milda
props {
  tone : enum(neutral, danger) = neutral
  items : array<string>
  leading : component(Icon)
}

Explained on Components, parts & the contract

#System-wide declarations

At the top level.

global-prop

proposal 0051
global-prop <name> : <type> [ = <default> ] [ "description" ]

A prop declared once for the whole system, so every component that takes it agrees on its name, type and default. A component takes it with global <name> in its props block.

Stored as
foundations.globalProps[]
milda
global-prop size : enum(sm, md, lg) = md "The control size, shared by every input"

Explained on Components, parts & the contract

See also global

rule

proposal 0052
rule <id> error|warning { <statement> because "reason" }

A usage rule: how the system is meant to be composed, checked over the instances a consumer writes. One rule states one thing, and the reason is mandatory - it is what a person or an agent reads when the rule fires.

A subject is a component by name or archetype <Name>, optionally narrowed with where <predicate> over its props.

A reference that resolves to nothing is a warning, and the rule is kept.

error
Severity: the composition is wrong.
warning
Severity: the composition is suspicious.
because
The reason, as a quoted string. Required.
min
min 1 Tab within Tabs - at least N of the subject inside the container.
max
max 1 Button where variant = primary within Form - at most N.
never
never Badge within Button - the subject must not appear inside the container.
only
only Tab within Tabs - the subject may appear only inside the listed containers.
within
Introduces the container of a count, never or only rule.
where
Narrows a subject by a predicate over its props.
tokens
tokens color, spacing - those token types may only be used through tokens, never as literals.
prefer
prefer Select for archetype SingleSelect - use this component wherever that archetype is wanted.
Stored as
foundations.rules[]
milda
rule no-stacked-dialogs error {
  never archetype Dialog within archetype Dialog
  because "A dialog over a dialog traps focus twice."
}

Explained on Usage rules & constraints

#Components

At the top level (component), and inside component { }.

component <Name> [ "description" ] { … }

A component of the library: its contract (props, events), its anatomy (parts), and how it is realized. The name is an identifier, because every reference to the component resolves against it.

Stored as
components[]
milda
component Button "The primary action." {
  archetype Button
}

Explained on Components, parts & the contract

See also archetype, part, props

archetype <Archetype>

The built-in blueprint the component is an instance of (Button, Select, Dialog, ...). It brings the contract, the anatomy and the behaviour the component starts from. The Archetypes reference lists them.

When omitted
An archetype-less component (a Card, a layout): nothing to inherit, every part is the author’s.
Stored as
component.archetype
milda
archetype Select

Explained on Archetypes

group <path/to/group>

Inside a component: the library category the component sits in, by group path. The group itself is declared at the top level.

Stored as
component.group
milda
group Forms/Inputs

Explained on The library around the components

See also group, group

uses

proposal 0024
uses <atom> [ ( <param>: <value>, … ) ] as <Alias>

Composes a behaviour atom from the prelude into the component, under an alias that wire and gate refer to. The Behaviors reference lists the atoms.

Stored as
component.composition.uses[]
milda
uses selection.single as S
uses presentation(surface: popover) as P

Explained on Behaviours

See also wire, gate

wire <A.signal> [ when <prop>[=<value>] ] -> <B.action>[(<arg>)]

Coordination between composed behaviours: when one atom signals, another acts. Also allowed inside realize.

Stored as
component.composition.coordination[] (wire)
milda
uses selection.single as S
uses presentation as P
wire S.change -> P.close

Explained on Behaviours

gate <Alias> active when <prop>[=<value>]

A composed behaviour is only active while a prop condition holds.

Stored as
component.composition.coordination[] (gate)
milda
uses presentation as P
gate P active when disabled=false

Explained on Behaviours

requires <capability> …

A capability the component needs (input.pointer, platform.web). Read and reported, but not stored: the document has no field for it yet, so the reader warns and moves on.

milda
requires input.pointer

Explained on Behaviours

part

proposal 0041
part <path> [ : <node kind> ] { <part statement> … }

A node of the component’s anatomy. The name is a PATH, and the path is how the tree is written down: Header.Title is the child Title of the part Header.

The FIRST part in the component is its root. Every part whose path has no dotted prefix naming another part is a child of the root.

The header says what the part IS where it is named: part Title: text { is the same part as one whose body says kind text. The colon reads as everywhere else on the surface - a name, then what it is. Exports write the header (surface 0.9); the statement keeps working, and saying a kind both ways is reported, with the header winning a contradiction (proposal 0055).

Which parts a component cannot do without is its archetype’s answer, not the file’s: a Button has a label. A file may leave a required part out and the reader adds it; editor tooling reports the gap as an error and offers to write the part in.

A part keeps its braces even when nothing follows the header: part icon: icon {}.

Parts are addressed by path everywhere else too: an accessible name’s labelled-by, a behaviour’s target node, an ancestor predicate leaf.

Stored as
component.anatomy (one node per part)
milda
component Card {
  part Card: container {}
  part Header: container {}
  part Header.Title: text {
    content "Hello"
  }
}

Explained on Components, parts & the contract

See also origin, kind

#Props and events

Inside a component’s props { } and events { } blocks.

props { <name> : <type> [ = <default> ] [ required [when <predicate>] ] [ bind <param> ] [ @<key> <value> … ] [ "description" ] … }

The component’s public inputs. A name, a colon, a type; then optionally a default, whether it is required, which archetype parameter it drives, annotations, and its documentation.

bind <param> connects the prop to one of the archetype’s bindable parameters - value : ref Option bind selected makes value the controlled selection of a select.

The colon is required (since surface 0.4): a name then its type is written one way everywhere.

Stored as
component.contract.props[]
milda
props {
  label : string = "Save" "The visible text"
  variant : enum(primary, secondary) = primary
  disabled : boolean = false
}

Explained on Components, parts & the contract

See also required, Prop constraints, global, @

required

proposal 0052
<prop> : <type> required [ when <predicate> ]

The prop must be given. With when, it must be given while a condition over the component’s other props holds. Only prop leaves are allowed in that predicate.

Stored as
prop.required / prop.requiredWhen
milda
props {
  href : string
  kind : enum(button, link) = button
  label : string required
  target : string required when kind = link
}

Explained on Usage rules & constraints

Prop constraints

proposal 0052
one-of a, b | any-of a, b | exclusive a, b

A constraint over a group of props. Written on its own line in the props block, and read as a keyword only when a prop name follows, so a prop may still be called exclusive.

one-of
Exactly one of the props is given.
any-of
At least one of them is given.
exclusive
At most one of them is given.
Stored as
component.contract.constraints[]
milda
props {
  label : string
  icon : string
  any-of label, icon
}

Explained on Usage rules & constraints

global

proposal 0051
global <name>, <name> …

Takes system-wide props declared with global-prop. Their type and default come from the declaration. A name nothing declares is an error and the prop is dropped.

Stored as
component.contract.props[] with global: true
milda
global-prop size : enum(sm, md, lg) = md
component Input {
  props {
    global size
    label : string
  }
}

Explained on Components, parts & the contract

See also global-prop

@

proposal 0026
<prop> : <type> @<key> <value> …

Descriptive annotations on a prop, such as its lifecycle. They describe the prop and never change its contract.

Stored as
prop.meta
milda
props {
  tone : string @status deprecated @since 1.2.0
}

Explained on Components, parts & the contract

events { <name> [ from <Machine.signal> ] … }

The events the component raises. A part says WHEN with emits; from names the behaviour signal an event surfaces, when it is one.

Stored as
component.contract.events[]
milda
events {
  click
  valueChange from S.change
}

Explained on Components, parts & the contract

See also emits

#Realization

Inside a component’s realize <target> { } block.

realize <target> [ when <prop>=<value> ] { … }

How the component is realized on one target, where the targets genuinely differ in behaviour or structure (a listbox on the web, a wheel on iOS). Style divergence does not belong here - that is token aliasing.

presentation
presentation popover { place bottom; flip; matchWidth } - the surface the content is presented on, and how it is placed.
browse
browse roving - how the user moves through items.
commit
commit explicit on click enter | commit continuous { live input; settled change } - when a choice becomes the value.
drop
drop typeahead - leave out composed atoms this target does not realize.
note
note "…" - prose about the realization.
dismiss
dismiss outside escape | dismiss none - what closes an overlay.
backdrop
backdrop scrim | blur | none - what is drawn behind an overlay.
wire
Target-specific coordination, as at the component level.
explicit
Commit mode: the value changes only on the listed interactions (on click enter).
continuous
Commit mode: the value follows the user as they go, as on a slider.
live
In a continuous block: the event raised while the user is moving.
settled
In a continuous block: the event raised once they let go.
Stored as
component.realize[]
milda
realize web {
  presentation dialog { place center }
  backdrop scrim
  dismiss outside escape
  note "Focus is trapped while open."
}

Explained on Archetypes

#Parts: what a part is

Inside part <path> { }, in a component or an example; the kind also in its header.

kind

proposal 0041
part <path>: <node kind> { … }  |  kind <node kind>

What the part IS, in neutral terms. The platform element (div, UIView, Composable) is the target’s decision and is deliberately not in the file.

Two spellings, one meaning: after the colon in the part’s header (part label: text {), which is what an export writes, or as a statement in its body. Both at once is a warning when they agree and an error when they do not, and then the header wins (proposal 0055).

An export states the kind of EVERY part rather than leaving it to the archetype’s role: a role is a safe default only while the prelude keeps it, and a saved file should not change meaning when the prelude does.

container
Holds and lays out other parts.
item
One entry of a collection (an option, a menu item).
text
Text.
control
Something the user activates or toggles.
input
Something the user types or picks a value into.
output
A computed or status value shown to the user.
icon
A glyph.
content
Media: an image, a video, an embed.
fragment
A grouping with no box of its own.
foreign
Quarantined target-specific code.
table
A table.
row
A table row.
cell
A table cell.
instance
Another component of the library, nested.
When omitted
The archetype’s own role for the part, if it names one; otherwise inferred - a part with children is a container, a part with text paint is text.
Stored as
node.kind
milda
part label: text {}
part icon {
  kind icon
}

Explained on Components, parts & the contract

See also part

origin

proposal 0041
origin root | archetype | author

Where the part came from: provenance. It answers "did the archetype give me this part, or did I add it?" - and for the root, "this is the component’s outermost node".

Which part IS the root is decided by position - the first part of the component - not by this statement. That is also why the printer leaves origin root out (proposal 0055): it would repeat what the position says. The reader still accepts it, and writing it on a later part does not move the root.

Unlike the kind, provenance is not a header word: the header says what a part is, and where it came from stays in the body.

root
The component’s root node, exactly one per component. What it may contain comes from what the archetype produces (a Button’s root accepts inline content only), and it is never a transparent wrapper.
archetype
Born from the archetype’s anatomy, like a checkbox’s indicator. The default, so the printer leaves it out.
author
Added by the author: a part the archetype does not declare.
When omitted
root for the first part, archetype when the archetype declares a part of that name (or the component has no archetype), author otherwise.
Stored as
node.origin
milda
part Button: container {}
part spinner: icon {
  origin author
}

Explained on Components, parts & the contract

See also part

present

proposal 0031
present when <predicate>

The part exists only while the predicate holds - not hidden, absent. An icon that renders only when the icon prop is set, a clear button only while there is a value.

When omitted
The part is always present.
Stored as
node.presence
milda
part icon: icon {
  present when icon
}

Explained on Components, parts & the contract

See also Predicates

instance

proposal 0012
instance <Component> { <prop> = <value> … }

The part is another component of the library, nested, with its props set. A value is fixed or bind <prop> to pass one of this component’s props through. A component cannot contain itself, directly or through others.

Stored as
node.instance
milda
part status: instance {
  instance Badge {
    label = "Beta"
    tone = bind tone
  }
}

Explained on Components, parts & the contract

foreign

proposal 0041
foreign <target> [ "label" ] "code"

Code written in one target’s own language, quarantined. A reader that does not implement that target keeps it verbatim and skips it rather than interpreting it. The escape hatch of last resort: the rest of the system stays portable.

Stored as
node.foreign
milda
part chart: foreign {
  foreign web-react "Sparkline" "<Sparkline data={props.points} />"
}

Explained on Components, parts & the contract

#Parts: content and data

Inside part <path> { }.

slot

proposal 0004
slot [ single | optional | many ] [ of content | of <Type> ] [ keyed-by <field> ] [ default ] [ as <name> ] [ role trigger|panel ] [ sample <sample> ] [ "description" ]

The part is a hole the consumer fills: the label of a button, the items of a menu. What it accepts and how many are part of the component’s public API.

single
Exactly one fill. The default.
optional
Zero or one.
many
Any number.
of
of content (free content, the default) or of <Type> (typed data or a child component).
keyed-by
The field that identifies each item of a many slot.
default
This slot receives the component’s positional children.
as
The slot’s public name, when it differs from the part’s.
role
Its structural role in a disclosure: trigger or panel.
trigger
Role: the part that opens the disclosure.
panel
Role: the part that is disclosed.
sample
A design-time fill for the preview, never generated: "Item", example "Name", or a list ["a", "b"].
Stored as
node.slot
milda
part label: text {
  slot of content default sample "Get started"
}

Explained on Components, parts & the contract

content "text" | content bind <prop> | content { default <v>; when <predicate> -> <v>; otherwise <v> }

The text the part shows: fixed, bound to a prop, or chosen by conditions. In the block form the rules are tried in order and default answers when none match.

Not text: text is the paint facet for the text style, and a keyword whose meaning depends on its argument reads fine and parses wrong.

Stored as
node.content
milda
part label: text {
  content {
    default bind label
    when disabled -> "Unavailable"
  }
}

Explained on Components, parts & the contract

value <type>

The type of value an input part holds, such as string for a text field or number for a slider.

Stored as
node.value.type
milda
part control: input {
  value string
  bind value value
}

Explained on Components, parts & the contract

See also bind

repeat <prop> [ as <alias> ] | repeat static [ a, b, … ] [ as <alias> ]

The part is drawn once per item of a list prop (or of a fixed list). Inside, <alias> names the current item.

When omitted
The part is drawn once. The alias defaults to item.
Stored as
node.repeat
milda
part option: item {
  repeat items as option
}

Explained on Components, parts & the contract

cell [ header ] [ col | row ]

A table cell’s role: a data cell, or a header cell for its column or its row.

header
A header cell.
col
Heads its column.
row
Heads its row.
Stored as
node.cell
milda
part heading: cell {
  cell header col
}

Explained on Components, parts & the contract

media

proposal 0028
media img | video | audio | embed

What kind of media a content part shows.

img
An image.
video
A video.
audio
Audio.
embed
An embedded document.
Stored as
node.media
milda
part avatar: content {
  media img
  source bind src sample url "https://example.com/a.png"
  alt bind name
}

Explained on Components, parts & the contract

See also source, alt

source

proposal 0028
source static <asset> | source [bind] <prop> [ sample asset <asset> | sample url "…" ]

Where a media part’s file comes from: a fixed asset of the library, or a prop - with an optional sample the preview shows while the prop is empty.

Stored as
node.mediaSource
milda
part logo: content {
  media img
  source static brand-logo
}

Explained on Components, parts & the contract

alt "text" | alt bind <prop>

A media part’s text alternative, fixed or bound to a prop.

Stored as
node.mediaAlt
milda
part photo: content {
  media img
  alt bind caption
}

Explained on Components, parts & the contract

destination "url" | destination bind <prop>

Where a navigating part goes - a link’s target - fixed or bound to a prop. Stated, never guessed from a prop name.

Stored as
node.destination
milda
part Link: container {
  destination bind href
}

Explained on Components, parts & the contract

#Parts: events, bindings and behaviour

Inside part <path> { }.

emits { <event> [ on <interaction> ] [ payload <value> ] [ signal <name> ] [ locked ] … }

Which declared event this part raises, and on what interaction. The event must be declared in the component’s events block.

on
The interaction that fires it. Defaults to activate.
payload
What the event carries: a fixed value or bind <prop>.
signal
The behaviour signal this emission stands for.
locked
The emission belongs to the archetype and cannot be removed in the editor.
activate
Interaction: clicked, tapped, or Enter/Space.
change
Interaction: the value changed and was committed.
input
Interaction: the value changed while editing.
focus
Interaction: received focus.
blur
Interaction: lost focus.
select
Interaction: an item was chosen.
open
Interaction: opened.
close
Interaction: closed.
dismiss
Interaction: dismissed by the user (outside press, Escape).
Stored as
node.emits[]
milda
part control: input {
  emits {
    valueChange on input payload bind value
  }
}

Explained on Behaviours

See also events

bind value <prop> | bind state <state> <prop>

A prop drives something about the part. bind value makes the prop the part’s value (two-way for an input). bind state puts the part into a state while the prop is true - bind state disabled disabled.

The same word is the "bound to a prop" form of a value elsewhere: content bind label, alt bind caption, tone = bind tone.

Stored as
node.valueBinding / node.stateBindings[]
milda
part Field: container {
  bind state disabled disabled
  bind state error invalid
}

Explained on Behaviours

behavior

proposal 0041
behavior <kind> { <field> <value> … }

A free behaviour attached to the part: portable interactions that are not tied to an archetype. Fields that name a node take a part path. behaviour is the same keyword.

focus-trap
Keep focus inside while open: initial-focus-node-id, return-focus-on-close, allow-escape-key.
typeahead
Jump to an item by typing its first letters: target-node-id, label-node-id, reset-delay-ms, case-sensitive.
cursor-navigation
Arrow keys move a cursor through items: orientation, wrap, target-node-id, item-node-id.
clickaway
React to a press outside: event-type, exclude-node-ids.
overlay-management
Position and open/close an overlay: anchor-node-id, placement, offset-px, flip, same-width, open-prop-name, close-on-select, commit-from-binding.
scroll-lock
Stop the page scrolling while open: target.
roving-tabindex
One tab stop for a group, arrows move within it: orientation, target-node-id, item-node-id, loop.
filter
Narrow the items by a query: query-prop-name, item-field, match-mode, case-sensitive.
Stored as
node.behaviors[]
milda
part list: container {
  behavior roving-tabindex {
    orientation vertical
    loop
  }
}

Explained on Behaviours

Config blocks

proposal 0034
<config> { <field> <value> … }   |   severity <level>   |   accordion single|multiple

The per-archetype settings that change what a component does rather than how it looks. Every field is checked against a fixed list, because a .milda file is untrusted input. A block-shaped config is read as one only when { follows its name, which keeps overlay { … } apart from the overlay paint facet.

calendar
selection-mode single|range, week-starts-on <n>, disabled-weekdays [0, 6].
time-picker
step <minutes>, use24-hour.
tabs
orientation horizontal|vertical, activation automatic|manual.
slider
range, orientation horizontal|vertical.
rating
max <n>, allow-half.
color-picker
formats, default-format hex|rgb|hsl|hsb, color-space srgb|oklch, alpha, eyedropper, swatches, layout popover|inline.
overlay
dismiss outside escape closeButton, placement top|bottom|left|right|center, backdrop none|scrim|blur.
severity
Single-valued: severity info|success|warning|danger.
accordion
Single-valued: accordion single|multiple.
Stored as
node.calendar, node.tabs, node.overlay, …
milda
part tablist: container {
  tabs {
    orientation vertical
    activation manual
  }
}

Explained on Archetypes

control

proposal 0016
control checkbox | switch

How a boolean control is realized: as a checkbox or as a switch. The contract is the same either way.

checkbox
A box with a check glyph; can be indeterminate.
switch
A sliding track and thumb.
Stored as
node.control
milda
part toggle: control {
  control switch
}

Explained on Archetypes

group

proposal 0022
group radio | segmented

Inside a part: how a one-of-N choice is realized, as a radio group or as a segmented control.

radio
A list of radio buttons.
segmented
Joined segments, one selected.
Stored as
node.group
milda
part options: container {
  group segmented
}

Explained on Archetypes

See also group, group

presentation

proposal 0022
presentation accessible-name

Inside a part: a presentation intent. accessible-name means the part’s text is not drawn but becomes the accessible name - how an icon-only button keeps a label.

accessible-name
Not shown; used as the accessible name.
Stored as
node.presentation
milda
part label: text {
  presentation accessible-name
}

Explained on Behaviours

See also realize

a11y

proposal 0013
a11y { name <value>; labelled-by <part>; described-by <part> }

How assistive technology names and describes the part: a name of its own (fixed or bound), or another part’s text by path. labeled-by is read as labelled-by.

name
The accessible name: "Close" or bind label.
labelled-by
Another part supplies the name.
described-by
Another part supplies the description.
Stored as
node.a11y
milda
part label: text {
  content "Email"
}
part hint: text {
  content "We never share it."
}
part control: input {
  a11y {
    labelled-by label
    described-by hint
  }
}

Explained on Behaviours

action

proposal 0021
action <interaction> toggle <variable> | action <interaction> set <variable> <value>

A demo interaction, meaningful only inside an example: when the part is activated, flip or set one of the scene’s demo variables. It lets a demo scene open its own dialog.

toggle
Flip a boolean demo variable.
set
Write a value into a demo variable.
Stored as
node.actions[]
milda
example "Open dialog" for Dialog {
  demo {
    open : boolean = false
  }
  part trigger: control {
    action activate toggle open
  }
}

Explained on Behaviours

See also example, demo

#Parts: paint, layout, states and motion

Inside part <path> { }, and inside its state and when blocks.

<facet> <value> …

A paint facet: an abstract slot such as "background" or "text colour", pointed at a token. There are no CSS properties in the language; each target maps facets to its own primitives. A dotted value is a token reference, a number is a literal, a bare word is an intent keyword.

A facet cannot be context-aliased itself (fill alias by … is an error): point it at a token and put the alias on the token.

Edges are logical, so a design system reads the same right to left. inset.left and the other physical words are read as the logical edge they name left to right, with a warning, and never written.

fill
The surface behind the part.
ink
The foreground: text and icon colour.
border
The edge: a colour token, a width token, and solid/dashed/dotted, in any order.
border.top
One physical edge. Also border.right, border.bottom, border.left.
border.inline-start
One logical edge. Also border.inline-end, border.block-start, border.block-end.
corner
The corner radius.
inset
Padding: one token for all sides, or two for block then inline.
inset.inline
Padding on one axis only: inset.inline for the start and end edges, inset.block for the top and bottom.
inset.inline-start
Padding on one logical edge. Also inset.inline-end, inset.block-start, inset.block-end. The more specific statement wins on its edge, so inset space.2 with inset.inline-start space.1 is 2 everywhere and 1 on the leading side.
gap
Space between children.
text
The text style or size.
text.clamp
Truncate to N lines.
text.wrap
How text wraps.
weight
The font weight.
font
The font family.
slant
Italic or upright.
elevation
Depth.
overlay
A state layer, such as the hover tint.
opacity
Transparency.
ring
The focus indicator.
backdrop
A scrim or blur behind the part.
Stored as
node.facets
milda
part Button: container {
  fill color.accent
  ink color.on-accent
  border color.line border.hairline solid
  corner radius.sm
  inset space.sm space.lg
}

Explained on Facets

See also state, when

layout [ when <prop>=<value> ] { <key> <value>; … }

How the part lays out its children and how it sizes itself, in the propose/choose model. The Layout model page explains the model; this is the vocabulary. Every word here is read, stored, printed and rendered by every target (proposal 0056).

stack
stack row | column | layers - the axis children flow along (layers draws them on top of each other, the stack sizing to the largest). A part with no stack is not a layout container.
wrap
wrap nowrap | wrap | wrap-reverse - whether children start new lines when out of room.
gap
Space between children, a spacing token or a length.
align
Cross-axis: start | center | end | stretch | baseline. Vertical in a layers stack.
distribute
Main-axis: start | center | end | between | around | evenly. Horizontal in a layers stack.
inset
Padding, as the facet of the same name.
size
size fill fit (width then height), size fill (width only), or size width fill / size height fit to name one axis. Each axis is an intent, optionally followed by min(…) and max(…): size fill min(size.sm) max(size.lg) fit.
width
Names the width axis after size.
height
Names the height axis after size.
fit
Size to content.
fill
Take all the room offered. On the main axis the web keeps the siblings whole (flex: 1 with min-width: 0); across it, the whole width.
weight
weight(2) - a share of the leftover room, against the siblings’ weights.
fixed
fixed(size.lg) - exactly a token’s size, or a length.
ratio
ratio(16:9) - this axis follows the other one by the ratio: size fill ratio(16:9) is a width that fills and a height that keeps 16:9. The key form ratio 16 9 is read as "the height follows the width" and never written.
min
min(size.sm) after an intent - the axis never shrinks below it.
max
max(size.lg) after an intent - the axis never grows past it.
position
position flow (the default) | overlay (out of flow, on top of its layers stack, placed by the stack’s align and distribute) | pinned <edge>… (stays at that edge of its scroll container) | bleed <edge>… (stays in flow and cancels the parent’s inset on those edges).
pinned
position pinned block-start - takes one or more logical edges: block-start block-end inline-start inline-end block inline all.
bleed
position bleed inline - the same edges; the part extends past the parent’s padding on them. The physical words top bottom left right are read as the logical edge they name left-to-right, and never written.
grid
Reserved. grid cols 2 is read and reported; no target draws a grid yet (proposal 0056 §3.3).
Stored as
node.layout
milda
part Toolbar: container {
  layout { stack row; gap space.sm; align center; distribute between; size fill fit }
}

Explained on Layout

state

proposal 0025
state <state> [ when <prop>=<value> ] { <facet> …; layout { … } }

Paint for an interaction state. States come from behaviours, not from pseudo-classes, so the same block works whether a target highlights by hover, by keyboard or by a wheel’s centre band. With when, it applies only for that prop value.

hovered
A pointer is over it.
pressed
Being pressed.
focused
Has focus.
focus-visible
Has focus, and the focus should be shown (keyboard).
active
The browse cursor is on it.
selected
Chosen.
checked
On.
indeterminate
Neither on nor off.
expanded
Its disclosure is open.
open
Its overlay is open.
disabled
Not interactive.
readonly
Shown but not editable.
loading
Waiting for data.
error
Invalid.
success
Validated.
first
The first of its repeated siblings.
last
The last of them.
odd
An odd-numbered one.
even
An even-numbered one.
today
Calendar: today’s date.
outside-month
Calendar: a day of the neighbouring month.
range-start
Calendar: the first day of a selected range.
range-end
Calendar: the last day of a selected range.
in-range
Calendar: inside a selected range.
highlighted
Emphasised by the component (a matched search result).
Stored as
node.states[]
milda
part Button: container {
  fill color.accent
  state hovered { fill color.accent-hover }
  state hovered when variant = ghost { fill color.accent-subtle }
  state disabled { opacity 50 }
}

Explained on Facets

See also bind, when

when

proposal 0032
when <predicate> { <facet> …; layout { … } }

Paint that applies while a condition holds, with no interaction state involved: the variants of a component. The predicate can combine props, states, contexts and ancestors.

Stored as
node.states[] with a predicate
milda
part Badge: container {
  fill color.neutral
  when tone = danger { fill color.danger }
}

Explained on Facets

See also Predicates, state

motion

proposal 0017
motion { transition <what> … duration <token> [ easing <token> ] [ delay <token> ] }

How the part animates between its states. Each transition names what animates, then its timing as tokens. A transition without a duration is skipped.

A motion line directly inside a component (rather than a part) is read as a note and skipped with a warning.

transition
One animated change.
duration
How long, a duration token. Required.
easing
The curve, an easing token.
delay
How long to wait first, a duration token.
Stored as
node.motion.transitions[]
milda
part Button: container {
  motion {
    transition fill duration fast easing standard
  }
}

Explained on Facets

#Predicates

After present when, when { }, required when, a content rule’s when, and a rule’s where.

Predicates

proposal 0032
<leaf> [ <op> <value> ] { and|or <…> }   |   not <leaf>   |   not ( … )   |   ( … )

A condition. A leaf is a prop by name, or state <s>, context <Group>, ancestor <part> <state>. A leaf with no operator means "is set"; not <leaf> means "is not set". and binds tighter than or; parentheses group.

Operators: =, !=, <, <=, >, >=, contains. A value is a bare word, a number, true/false, or a quoted string.

and
Both hold.
or
Either holds.
not
Negation.
state
Leaf: the part is in this interaction state.
context
Leaf: the active context of a context group.
ancestor
Leaf: an ancestor part, by path, is in a state - "style the icon while the row is hovered".
contains
Operator: a list or text contains the value.
Stored as
node.presence, node.states[].when, prop.requiredWhen, content rules
milda
part icon: icon {
  present when icon and not loading
  when ancestor Row hovered or state focused { ink color.accent }
}

Explained on Facets

#The library around the components

At the top level.

group <path/to/group> [ "description" ]

At the top level: a category of the component library. Groups nest by path, and a group’s ancestors are implied. The description is prose the docs show for the group.

Stored as
componentGroups[]
milda
group Forms "Everything that collects input."
group Forms/Inputs

Explained on The library around the components

See also group

example

proposal 0021
example "Name" [ for <Component> ] [ "description" ] { demo { … } part … }

A demo scene: a composition shown in the docs and the preview, with no contract of its own. for names the component it demonstrates; its parts are written exactly like a component’s.

Stored as
examples[]
milda
example "Primary" for Button {
  part stage: instance {
    instance Button {
      label = "Save"
    }
  }
}

Explained on The library around the components

See also demo, action

demo

proposal 0021
demo { <name> : <type> [ = <initial> ] … }

Inside an example: the scene’s own variables, which its parts can bind and its actions can change. A separate word from state, which in a part means an interaction state.

Stored as
example.demo
milda
example "Toggle" {
  demo {
    open : boolean = false
    tone : enum(info, danger) = info
  }
}

Explained on The library around the components

docs

proposal 0018
docs { site { … } footer { … } page "Title" [ in "Section" ] [ under "Parent" ] { <block> … } }

The design system’s documentation site: its header, its footer, and its pages. A page’s blocks are prose or transclusions, and every transclusion names what it shows by name, so the docs stay current as the system changes.

site
site { name "Acme"; tagline "…"; version "2.1"; search-placeholder "…" }.
footer
footer { copyright "…"; link "Label" "https://…" }.
copyright
The footer’s copyright line.
link
A footer link: label, then address.
page
A page. in puts it in a sidebar section, under nests it below another page by title.
heading
Prose block. Any prose block may end with anchor <id>.
subheading
Prose block.
paragraph
Prose block.
list
Prose block.
quote
Prose block.
callout
Prose block.
code
Prose block.
divider
A horizontal rule.
image
image asset <name> - an image from the asset library.
component
A live preview of a component.
component-props
The component’s props table.
component-events
The component’s events table.
component-composition
The behaviours the component composes.
component-prop
One prop: component-prop Button variant.
component-event
One event: component-event Button click.
example
A demo scene, by name.
component-group
Every component of a library group.
tokens
A table of the tokens of one type: tokens color.
swatch
Swatches of the tokens of one type.
Stored as
docs
milda
docs {
  site { name "Acme"; tagline "One system, every surface" }
  page "Button" in "Components" {
    heading "Button" anchor top
    paragraph "Use one primary action per view."
    component Button
    component-props Button
  }
}

Explained on The library around the components

assets { folder <path> | <kind> "name" [ in <folder> ] { <field> <value> … } }

The asset library: fonts, images, SVGs, videos and animations, in folders. An asset says where its bytes are: url (beside the file, in a bundle) or data (inside the file, self-contained).

Every asset may also carry mime, size, uploaded and tags.

folder
A folder, by path. Ancestors are implied.
font
A font file: font-family, font-style, font-weight, formats.
image
An image: width, height, alt.
svg
A vector image: view-box, width, height.
video
A video: width, height, duration-ms, poster.
animation
An animation file: format, duration-ms, loop.
url
The bytes are at this address.
data
The bytes are in this data: URI.
Stored as
assets
milda
assets {
  folder brand
  image "brand-logo" in brand {
    mime "image/png"
    width 240
    height 64
    url "assets/brand-logo.png"
  }
}

Explained on The library around the components

icons { set <prefix> [ "name" ] { … } | glyph <prefix> <name> { … } | custom "name" { … } }

The icon library. A part names a glyph by its bare name, which resolves to a curated glyph first, then to the FIRST set’s prefix - so the order of the sets is meaning.

set
An icon set: provider, license, samples [a, b, c, d].
glyph
A curated glyph of a set: label, and svg, its vendored body.
custom
A glyph drawn by an asset of the library: asset, label.
Stored as
foundations.icons
milda
icons {
  set lucide "Lucide" { provider lucide; license ISC }
  glyph lucide check { label "Done" }
  custom "brand-mark" { asset brand-logo }
}

Explained on The library around the components