Skip to content

roman01la/react-imgui-wasm

Repository files navigation

React ImGui WASM

A React renderer for Dear ImGui that compiles to WebAssembly using Emscripten.

Write ImGui UIs using React components with JSX syntax.

Features

  • React 19 with custom reconciler for ImGui
  • JSX Components for windows, text, buttons, tables, and more
  • Custom Drawing with shapes (rect, circle, line) on the background canvas
  • Watch Mode for fast development iteration
  • Modular WASM with explicit initialization

Quick Start

Prerequisites

  • macOS/Linux: CMake, SDL2, Emscripten, Bun
  • Install dependencies via Homebrew:
    brew install cmake sdl2 emscripten bun

Building

WebAssembly - Development Build

./build-wasm-dev.sh
cd dist && python3 -m http.server 8000
# Open http://localhost:8000

WebAssembly - Development with Watch Mode

./build-wasm-dev.sh --watch
# Rebuilds automatically when src/ files change

WebAssembly - Production Build

./build-wasm-prod.sh
cd dist && python3 -m http.server 8000

Example

import React, { useState } from "react";
import { createRoot, renderRoot } from "./react-imgui-reconciler";

function App() {
  const [count, setCount] = useState(0);

  return (
    <root>
      {/* Background shapes */}
      <rect x={10} y={10} width={100} height={50} color="#3030A0" filled />

      {/* ImGui window */}
      <window title="Hello React!" defaultX={100} defaultY={100}>
        <text color="#00FFFF">Welcome to React + ImGui!</text>
        <separator />
        <button onClick={() => setCount(count + 1)}>
          Clicked {count} times
        </button>
      </window>
    </root>
  );
}

const root = createRoot();
renderRoot(<App />, root);

Available Components

Layout

  • <root> - Root component (required, renders to fullscreen canvas)
  • <window> - ImGui window with title, position, size props
  • <child> - Scrollable child region
  • <group> - Group elements together
  • <indent> / <unindent> - Indentation
  • <sameline> - Put next element on same line
  • <separator> - Horizontal separator
  • <dummy> - Invisible spacer

Text

  • <text> - Text with optional color and wrapped props
  • <textdisabled> - Grayed out text

Widgets

  • <button> - Clickable button with onClick
  • <collapsingheader> - Collapsible section

Tables

  • <table> - Table container with columns prop
  • <tablecolumn> - Column definition
  • <tableheader> - Header row
  • <tablerow> - Table row
  • <tablecell> - Table cell with index prop

Drawing (Background Canvas)

  • <rect> - Rectangle with x, y, width, height, color, filled
  • <circle> - Circle with x, y, radius, color, filled, segments
  • <line> - Line with x1, y1, x2, y2, color, thickness

Window Props

// Uncontrolled (initial position/size)
<window
  title="My Window"
  defaultX={100}
  defaultY={100}
  defaultWidth={400}
  defaultHeight={300}
/>

// Controlled (React manages position/size)
<window
  title="Controlled Window"
  x={windowState.x}
  y={windowState.y}
  width={windowState.width}
  height={windowState.height}
  onWindowState={(x, y, width, height) => setWindowState({ x, y, width, height })}
/>

Project Structure

.
├── src/
│   ├── main.cpp                  # C++ ImGui bindings (EMSCRIPTEN_KEEPALIVE exports)
│   ├── app.jsx                   # React application entry point
│   ├── react-imgui-reconciler.js # Custom React reconciler for ImGui
│   └── index.html                # HTML template with cwrap bindings
├── external/
│   └── imgui/                    # Dear ImGui library
├── dist/                         # Build output (index.html, bundle.js)
├── build.js                      # esbuild configuration
├── CMakeLists.txt                # CMake/Emscripten configuration
├── build-wasm-dev.sh             # Development build script
└── build-wasm-prod.sh            # Production build script

Build Configuration

Development Build

  • Optimization: -O0 (fast compilation)
  • Watch Mode: --watch flag for auto-rebuild
  • Output: dist/ directory

Production Build

  • Optimization: -O3 with Closure compiler
  • Output: dist/ directory

Architecture

  • React 19 with custom reconciler (react-reconciler)
  • Dear ImGui for immediate-mode UI
  • Emscripten compiles C++ to WebAssembly
  • SDL2 + WebGL for rendering
  • esbuild bundles JavaScript/JSX

The reconciler translates React's declarative component tree into ImGui's immediate-mode API calls every frame via the buildUI() callback.

License

MIT. Dear ImGui is also MIT licensed - see external/imgui/LICENSE.txt.