UI element reference
Everything inside a screen's sections, a layout slot or a component root is an element: a JSON object with a type. IWC has 45 element types. This reference is generated from the compiler's own schema (iwc/docs/schemas/ui.schema.json) and validator, and every example on these pages was compiled and rendered by IWC — the HTML shown under Output is what it produced.
An unknown type is a compile error, and so is a property that does not apply to a type: "source" does not apply to text elements (it is used by: image, video, audio, svg, icon). Form controls (text, select, checkbox, radio, textarea…) are inputs of a form — see the form input reference.
45 elements
Layout & containers
containernativeA generic wrapper that groups other elements so they can be styled, laid out or shown together.sectionnativeA thematic band of a page — a hero, a feature list, a footer call to action.boxnativeA generic block, interchangeable with container; use whichever name reads better.rownativePlaces children side by side in a flex row.columnnativeStacks children vertically in a flex column.gridA CSS grid. Use it for card grids, galleries and dashboards.stacknativeSame as column: children stacked vertically. Often used for repeated records.spacernativeEmpty space of a size you choose.dividernativeA horizontal rule between groups of content.headernativeIntroductory content for a page or a section; often the site header inside a component.footernativeClosing content: links, legal text, contact details.navnativeA group of navigation links, such as a sidebar menu or footer links.sidebarA side panel of supplementary content or navigation.mainnativeA generic wrapper (rendered as a div; the page's own <main> comes from the layout).asidenativeContent related to, but separate from, the main content — a tip, a related-links box.Text & media
textnativeHeadings, paragraphs, labels, quotes and formatted values — literal or bound to data.imagenativeA picture from your assets, a URL, or a record.videoA video file with optional poster and controls.audioAn audio file with player controls.svgnativeAn SVG file shown as an image.iconnativeA built-in line icon by name, or your own icon file.placeholderA neutral block standing in for media you do not have yet.badgeA short label: New, Sale, a status.reviewOne or more customer reviews: stars, quote and author.ratingA star rating from 0 to 5.Buttons & links
Data display
Forms & search
formCollects input and submits it as JSON to a POST/PUT/PATCH/DELETE API, showing the server's validation errors next to each field.phoneSignInPhone-number sign-in with a one-time code through Firebase, then an IWC session.searchA search box or a filter bar that writes its values into the URL's query string.Interactive
navbarA responsive site header: brand and actions always visible, menu links that fold behind a menu button on small screens, and dropdowns nested to any depth.dropdownA button that opens a menu of links or any content (a mega menu).modalA dialog over the page, opened by a button.drawerA panel that slides in from an edge: filters, a cart, a mobile menu.tabsSwitches between panels of related content.accordionExpandable sections — FAQs, specifications.carouselSlides with previous/next buttons and swipe; each child (or each record) is a slide.sliderAnother name for carousel.Properties every element accepts
| Property | Type | Description |
|---|---|---|
type | "container""section""box""row""column""grid""stack""spacer""divider""header""footer""nav""navbar""sidebar""main""aside""text""image""video""audio""svg""icon""placeholder""button""link""badge""card""list""table""form""review""rating""dropdown""modal""drawer""tabs""accordion""carousel""slider""chart""slot""component""phoneSignIn""search""widget" | |
id | stringexpression (=…) | |
className | string | extra CSS classes from your stylesheets (utility-framework syntax such as md:grid-cols-2 is allowed) |
style | object {name: stringnumber} | CSS properties in camelCase or kebab-case, e.g. {"padding": "80px"} |
responsive | object {name: object {name: stringnumber}} | per-breakpoint styles: {"mobile": {"padding": "24px"}} |
states | object |
|
transition | string | CSS transition, e.g. "all 200ms ease" |
animation | object |
|
visible | expression (=…)object | |
ariaLabel | string | |
attributes | object {name: string} | extra HTML attributes: data-, aria-, role, title, lang, dir, width, height, hidden, download (others are ignored) |
styleSource | string | a stylesheet to load with this element |
platforms | array of "web""android""ios" | the platforms this is built for, e.g. ["web"]; omitted: every platform |
All element properties
The complete property list of the element definition. Properties marked Only on are rejected by the compiler on other element types.
| Property | Type | Description |
|---|---|---|
action | "navigate""open""close""toggle""submit""state""api""logout""scroll""share""install""notifications""sync""pay""tracking""native" | share: the system share sheet (web: Web Share, else copies the link) for target (default: this page) with value as the message; install: the browser's install prompt (pwa; hidden until the app can be installed); notifications: ask for notification permission and send the push subscription to pwa.push; sync: open the list of changes waiting to sync (offline); pay: call api for a payment, open the provider's payment sheet in a native app (hosted checkout on the web) and check it with confirm; tracking: value "start"/"stop" background location (platforms.*.background.location); native: call your own Kotlin/Swift extension named by target ("Scanner.scan") with value, and post its result to apiOnly on: button, link |
alt | string | Only on: image, svg |
animation | object |
|
api | string | the api file to call (phoneSignIn: the auth.exchange api)Only on: button, phoneSignIn |
ariaLabel | string | |
attributes | object {name: string} | extra HTML attributes: data-, aria-, role, title, lang, dir, width, height, hidden, download (others are ignored) |
author | string | Only on: review |
autofocus | boolean | search: put the cursor in the box when the screen opensOnly on: search |
autoplay | boolean | Only on: video, audio, carousel, slider |
bind | string | take content from data: a field of the current item, or props.x, user.x, params.x, state.store.path |
binds | object {name: string} | bind attributes: {"source": "image", "target": "slug"} |
cells | array of object | Only on: table |
chart | object |
|
className | string | extra CSS classes from your stylesheets (utility-framework syntax such as md:grid-cols-2 is allowed) |
collapse | "links""all" | navbar: what folds behind the menu button on small screens (default links) |
collapseAt | "mobile""tablet" | navbar: the breakpoint below which it folds (default mobile) |
columns | integer (1–24)string | |
confirm | string | pay: the api that checks the payment on the server (it receives {id, provider, paymentId, signature, status}); the screen shows success only when it answers 2xx |
content | string | literal text, or an expression starting with = ("=product.name") |
controls | boolean | Only on: video, audio |
currency | string | ISO currency for format=currency |
data | object |
|
elements | array of element | |
empty | element | |
error | element | |
fields | object {name: string} | card mapping: title, subtitle, text, price, image, badge, linkOnly on: card |
fit | "cover""contain""fill""none" | Only on: image, video |
format | "text""number""currency""percent""date""datetime""date-long""date-short""time""markdown" | markdown (text elements): the value is user-written Markdown, rendered safely (no HTML passes through) |
gap | string | |
id | stringexpression (=…) | |
inputs | array of input | Only on: form, search |
instant | boolean | search: search again as the visitor types (debounced; the results screen is patched in place and the box keeps focus) |
interval | duration (500ms, 6s…) | durations look like 500ms, 30s, 5m, 1h or 7dOnly on: carousel, slider |
item | element | |
items | array of item | Only on: accordion, list, dropdown, navbar, nav, review |
label | string | |
layout | object |
|
loading | "lazy""eager""priority" | image: lazy (default) waits until it nears the screen; eager loads at once; priority also asks for it first — use it for the picture people see first (often the largest paint)Only on: image |
loop | boolean | Only on: video, audio |
mutation | string | identifiers use letters, digits and '_' and do not start with a digitOnly on: button, link |
muted | boolean | Only on: video, audio |
name | string | icon name; search: the query parameter (default q) |
newTab | boolean | |
open | boolean | accordion/details: start openOnly on: accordion, dropdown |
opensOn | "click""hover" | dropdown/navbar: how menus open (hover falls back to click on touch screens) |
placeholder | string | search: the hint inside the boxOnly on: search |
platforms | array of "web""android""ios" | the platforms this is built for, e.g. ["web"]; omitted: every platform |
poster | string | Only on: video |
prefix | string | |
props | object {name: any} | Only on: component, widget |
rating | number | |
ratio | string | ratios look like 16/9 |
responsive | object {name: object {name: stringnumber}} | per-breakpoint styles: {"mobile": {"padding": "24px"}} |
responsiveColumns | object {name: integer (1–24)} | grid columns per breakpoint |
side | "left""right""top""bottom" | Only on: drawer, sidebar |
slot | string | in a component: the prop holding child elementsOnly on: slot |
source | string | image/video/audio/svg URL or assets pathOnly on: image, video, audio, svg, icon |
states | object |
|
store | string | state store for action=stateOnly on: button, link |
style | object {name: stringnumber} | CSS properties in camelCase or kebab-case, e.g. {"padding": "80px"} |
styleSource | string | a stylesheet to load with this element |
submit | object |
|
success | object | api buttons: what happens after a 2xx answer
|
suffix | string | |
tabs | array of object | Only on: tabs |
tag | "div""span""p""section""article""aside""header""footer""nav""main""figure""figcaption""ul""ol""li""dl""dt""dd""blockquote""address""time""small""strong""em""b""i""s""u""mark""cite""q""abbr""sub""sup""del""ins""code""pre""kbd""label""hgroup""h1""h2""h3""h4""h5""h6""details""summary""button" | the HTML tag a container or text element renders as, e.g. "ul", "li", "article", "figure" |
target | string | route, element id, or URL |
transition | string | CSS transition, e.g. "all 200ms ease" |
type | "container""section""box""row""column""grid""stack""spacer""divider""header""footer""nav""navbar""sidebar""main""aside""text""image""video""audio""svg""icon""placeholder""button""link""badge""card""list""table""form""review""rating""dropdown""modal""drawer""tabs""accordion""carousel""slider""chart""slot""component""phoneSignIn""search""widget" | |
use | string | component: the component file to render; widget: the widget fileOnly on: component, widget |
value | any | value passed to a state mutation; strings starting with item. or props. are bound |
variant | string | text: heading, h1-h6, subheading, paragraph, caption, label, quote, code; button: primary, secondary, ghost |
vars | object {name: string} | CSS custom properties set from data, per record: {"--accent": "=color", "--progress": "=concat(pct, '%')"}; your stylesheet uses var(--accent) |
visible | expression (=…)object |