Markup

The HTML that a component outputs is declared within a @render block. There can only be one @render block per component. Each @render block must contain a single root element:

export default function Component() {
	@render {
		<p>Hello!</p>
	}
}

Dynamic content

You can include dynamic content in text and attributes using braces:

export default function Component() {
	const className = "extravagant"
	const name = "Torpor"

	@render {
		<p class={className}>
			Hello, {name}!
		</p>
	}
}

Use this shortcut syntax to set the value of an attribute to a value of the same name:

export default function Component() {
	const id = "main"

	@render {
		<p {id}>
			Hello, {name}!
		</p>
	}
}

If statements

Use an @if statement to show certain markup when a condition is met:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>
			<button onclick={() => $state.counter--}>Decrement</button>
			{$state.counter}
			<button onclick={() => $state.counter++}>Increment</button>

			@if ($state.counter < 0) {
				<p>The count is negative.</p>
			} else if ($state.counter > 0) {
				<p>The count is positive.</p>
			} else {
				<p>The count is zero.</p>
			}
		</div>
	}
}

For loops

Use a @for loop to show multiple elements:

export default function Component() {
	let $state = $watch({
		stock: [
			{ code: "W1", name: "Widgets", quantity: 5 }
			{ code: "B2", name: "Boxes", quantity: 12 }
			{ code: "D3", name: "Doodads", quantity: 3 }
		]
	})

	@render {
		<div>
			<button onclick={() => $state.stock.sort((a, b) => a - b)}>
				Sort by quantity
			</button>

			@for (let $item of $state.stock) {
				@key $item.code
				<p>{$item.name}: {$item.quantity}</p>
			}
		</div>
	}
}

Note the use of the (optional) @key statement to store a unique value for each loop item. If set, when the list is updated (e.g. when sorting), the @key value will be used to recycle the DOM elements rather than destroying and recreating each one.

Switch statements

Use a @switch statement to show one of many options:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>
			{$state.counter}
			<button onclick={() => $state.counter++}>Increment</button>

			@switch ($state.counter) {
				case 0: {
					<p>It's zero.</p>
				}
				case 1: {
					<p>It's one.</p>
				}
				case 2: {
					<p>It's two.</p>
				}
				case 3: {
					<p>It's three.</p>
				}
				case 4: {
					<p>It's four.</p>
				}
				default: {
					<p>It's bigger than four.</p>
				}
			}
		</div>
	}
}

Note that the switch statement differs from the JavaScript switch statement in that each case statement must be surrounded by braces and no fallthroughs are allowed (meaning that the break statement can be omitted).

Await statements

Use an @await statement to show the result of an asynchronous function:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>

		</div>
	}
}

Replace statements

Use a @replace statement to re-render markup when a value is changed:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>

		</div>
	}
}

This can be used to re-run component $mount statements and to re-play transition animations.

@const, @console and @debugger

The @const keyword can be used to declare a constant value within markup, the @console keyword can be used to log information within markup, and the @debugger keyword can be used to break code execution during markup rendering:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>

		</div>
	}
}

Function declarations

Use the @function statement to declare a function within markup. This can be useful for keeping logic close together, e.g. for moving a large onclick handler out of an onclick attribute, but still keeping it next to the button it is called from:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>

		</div>
	}
}

HTML rendering

Use a @html statement to render plain HTML within markup, e.g. from a database:

export default function Component() {
	let $state = $watch({ counter: 0 })

	@render {
		<div>

		</div>
	}
}

Note that when rendering HTML you should ensure that it is properly escaped to prevent script injection and other attacks.

Playground

Input

Output