Using JSX
Rezi provides a JSX runtime (@rezi-ui/jsx) that lets you write widget trees using JSX syntax instead of the ui.* function API.
Rezi provides a JSX runtime (@rezi-ui/jsx) that lets you write widget trees using JSX syntax instead of the ui.* function API.
Setup
-
Install the JSX package:
npm install @rezi-ui/jsx -
Configure TypeScript (
tsconfig.json):{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@rezi-ui/jsx" } } -
Use
.tsxfile extensions.
Example
import { rgb } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";
import { Button, Column, Divider, Row, Text } from "@rezi-ui/jsx";
type State = { count: number };
const app = createNodeApp<State>({
initialState: { count: 0 },
});
app.view((state) => (
<Column p={1} gap={1}>
<Text style={{ fg: rgb(120, 200, 255), bold: true }}>Counter</Text>
<Row gap={2}>
<Text>Count: {state.count}</Text>
<Button id="inc" label="+1" />
</Row>
<Divider />
<Text style={{ dim: true }}>Press q to quit</Text>
</Column>
));
app.keys({
q: () => app.stop(),
});
await app.start();Available JSX elements
@rezi-ui/jsx exports components for all core widgets. Props match the corresponding ui.* function.
ui.* API | JSX component |
|---|---|
ui.text(...) | <Text> |
ui.box(...) | <Box> |
ui.row(...) | <Row> |
ui.column(...) | <Column> |
ui.grid(...) | <Grid> |
ui.hstack(...) | <HStack> |
ui.vstack(...) | <VStack> |
ui.button(...) | <Button> |
ui.input(...) | <Input> |
ui.slider(...) | <Slider> |
ui.tabs(...) | <Tabs> |
ui.accordion(...) | <Accordion> |
ui.breadcrumb(...) | <Breadcrumb> |
ui.pagination(...) | <Pagination> |
ui.table(...) | <Table> |
ui.modal(...) | <Modal> |
| ... | (all core widgets through <ToastContainer>) |
Lowercase intrinsic elements are also supported (for example <column>, <grid>, <hstack>, and <tabs>). These map directly to the JSX runtime factories and do not require importing components.
<HStack>/<VStack> (and <hstack>/<vstack>) follow ui.hstack/ui.vstack behavior: they emit row/column VNodes with a default gap of 1 when no gap is provided.
JSX vs ui.* API
Both APIs produce the same VNode trees. Choose based on preference:
// JSX style
<Column p={1}>
<Text style={{ bold: true }}>Hello</Text>
<Row gap={2}>
<Button id="ok" label="OK" />
<Button id="cancel" label="Cancel" />
</Row>
</Column>
// ui.* style
ui.column({ p: 1 }, [
ui.text("Hello", { style: { bold: true } }),
ui.row({ gap: 2 }, [
ui.button({ id: "ok", label: "OK" }),
ui.button({ id: "cancel", label: "Cancel" }),
]),
])The ui.* API has zero runtime overhead — it's direct function calls. The JSX runtime adds a thin createElement layer. Both are extremely fast.
Fragments
Use fragments to group elements without a container:
<>
<Text>Line 1</Text>
<Text>Line 2</Text>
</>Note: JSX vs ui.*
@rezi-ui/jsx is the native Rezi JSX runtime. It creates Rezi VNodes directly and does not use React.
If you prefer explicit function calls, use ui.*. If you prefer JSX syntax, use @rezi-ui/jsx.