UI Components
JOEL provides a React-like component system for building user interfaces.
Component Declaration
[Compiled]
[target wasm32]
import ui
component Counter() {
signal count = 0
view (
<Panel>
<H1>Count: {count}</H1>
<Button onClick={() => count++}>Increment</Button>
</Panel>
)
}Signals (Reactive State)
component Counter() {
signal count = 0
signal name = "JOEL"
view (
<div>
<p>Hello, {name}!</p>
<p>Count: {count}</p>
</div>
)
}Component Props
component Greeting(name: str, age: i32) {
view (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age} years old</p>
</div>
)
}
# Usage
<Greeting name="JOEL" age={24} />Event Handlers
component Button() {
signal clicked = false
fn handle_click() {
clicked = true
}
view (
<Button onClick={handle_click}>
{clicked ? "Clicked!" : "Click me"}
</Button>
)
}Conditional Rendering
component UserProfile(user: Option[User]) {
view (
<div>
{match user {
Some(u) => <div>Welcome, {u.name}</div>,
None => <div>Please log in</div>
}}
</div>
)
}Lists and Loops
component TodoList(items: list[str]) {
view (
<ul>
{for item in items {
<li>{item}</li>
}}
</ul>
)
}Examples
Counter Component
[Compiled]
[target wasm32]
import ui
component Counter() {
signal count = 0
view (
<Panel>
<H1>{count}</H1>
<Button onClick={() => count++}>+</Button>
<Button onClick={() => count--}>-</Button>
<Button onClick={() => count = 0}>Reset</Button>
</Panel>
)
}
export default CounterForm Component
component ContactForm() {
signal name = ""
signal email = ""
signal message = ""
fn handle_submit() {
# Submit form data
print("Submitting:", name, email, message)
}
view (
<Form onSubmit={handle_submit}>
<Input
value={name}
onChange={(e) => name = e.value}
placeholder="Name"
/>
<Input
value={email}
onChange={(e) => email = e.value}
placeholder="Email"
/>
<Textarea
value={message}
onChange={(e) => message = e.value}
placeholder="Message"
/>
<Button type="submit">Send</Button>
</Form>
)
}SSR/SSG Support
# Server-side rendering
component BlogPost(slug: str) {
# Fetch data on server
let post = await fetch_post(slug)
view (
<Article>
<H1>{post.title}</H1>
<Content>{post.body}</Content>
</Article>
)
}Cross-Platform
JOEL UI components compile to:
- Web: React/Next.js
- Mobile: React Native (via WASM)
- Desktop: Electron/Tauri