Authoring walkthrough
How a component comes to life in Milda - from picking an archetype in the Studio to installing generated code - told from the language's point of view. Every click in the editor is writing the model described in the previous pages; this walkthrough makes that mapping visible.
We'll build a Button end to end, then sketch a Select to show how the same steps scale to a genuinely hard component.
#1. Pick an archetype
A new component starts from a blueprint, not a blank canvas. You pick Button from the archetype catalog, and with that one choice the component already meanssomething: its contract is “label/icon, fires an action”, and its behavior bundle - activation for the action, pressability for press/hover feedback - comes along for free. You never wire a click handler; firing the action is a contract obligation the archetype carries on every platform.
#2. Anatomy appears
The archetype's published anatomy materializes as the component's structure: an optional icon part and a labelpart. Parts are platform-neutral - the Studio never shows you an HTML tag, because the model doesn't contain one; the element is the generator's decision. You can skip optional parts, add nodes within what the content model allows, and group them - structure editing is editing the anatomy tree.
#3. Shape the contract
The Interface panel is where the component's public API lives - the part consumers of your generated library will see:
- Props - bind the label part's text to a
labelprop. Names are neutral identifiers; each generator applies its own casing conventions. - Events - the archetype's
activationalready emits an action event; you surface it under the name you want. - Slots- expose a part as a consumer-fillable insertion point with an arity and a content contract. Slots are the component's children API.
- Variants & sizes - declare
variantandsizeprops typed by context groups. They are not string switches: a context-typed prop plugs into the token-resolution machinery, which is what makes step 4 pay off.
#4. Bind facets to tokens
Styling the button means setting facets on parts: fill to an accent token, ink to a foreground token, corner to a radius role, inset for padding. Because every value is a token reference, the button automatically follows color scheme, density, brand - and platform. If variant is a context group, the solid and outline looks are just token aliases keyed by it; no conditional style logic exists anywhere.
#5. States & conditions
The Style tab offers condition axes - variant, size, and state. The states on offer are exactly what the composed behaviors emit: pressability contributes pressed and hovered, the ambient gate contributes disabled. You add “when pressed, darken the fill” as a state-keyed facet override. The editor can force each state in preview so you can see every combination without hunting for it.
#6. Preview
The Stage renders the component from the model, live - the same IR the generators will consume, realized by the editor's own preview. Browse with the keyboard, force states, switch variants through the prop bar. What you are testing is the model, not a prototype that will be rewritten later.
#7. Generate & release
A release runs the generator for each of the project's targets - React first - and publishes a versioned package to your registry. Versioning is computed from the contract: a contract-preserving change is a patch/minor, a breaking contract change bumps the major. The language's “contract is the identity” rule is what makes that computable.
#The same arc, for a Select
Now the payoff. Pick SingleSelect and the hard parts arrive already solved:
- The anatomy is a tree -
trigger(withvalueandindicator) andsurface(withoption, its optionalcheck, andlabel). - Five behaviors come pre-wired: activation toggles the presentation, browse moves the highlight, selection commits the value, dismiss closes on outside/escape. Keyboard navigation, typeahead, and the open/close/commit choreography are the archetype's responsibility, not yours.
- The contract needs an
optionscollection prop and a boundvalue; thechangeevent comes from the selection atom. - Styling keys on behavior states:
optiongetsactive(the browse highlight) andselectedoverrides;triggergets anopenstate and a focusring; thesurfacegetselevation- which resolves per platform through token aliasing.
Your work is the same kind of work as for the Button - contract, tokens, states - while the interaction engineering that usually makes selects a multi-week project is carried by the language.
#What you never do
- Write platform code. No CSS, no HTML tags, no React. The Studio authors the neutral model; generators own everything platform-shaped.
- Edit generated output.Generated code is an artifact, like a compiler's. Editing it forks you from the source of truth and the next release overwrites you.
- Re-implement interaction. Behaviors come from the archetype; you configure and style them.
#Escape hatches are declared seams
No vocabulary covers everything, and Milda's answer to the last 20% is doctrine: extensibility happens through seams declared in the model, never by patching output.
- Slots - where consumers inject their own content or components, declared with arity and a content contract.
- Per-target options - realization choices (naming, emission style, output conventions) configured per target at release time, without touching the neutral model.
Because every seam is in the IR, it survives regeneration, appears in the contract diff, and works on every target - which is exactly what an edit to generated code can never promise.