Skip to main content

Quick Start

The example below is not hand-copied into this page — it's pulled directly, at build time, from packages/react/src/quickstart.example.tsx in the repository. That file is typechecked on every CI run (packages-ci.yml's "Typecheck packages" step), so this page can never silently drift from a working example the way a copy-pasted snippet could.

import type { ReactElement } from "react";
import type { EditorPlugin } from "@rifrocket/fabricjs-design-tool";
import { Editor, useEditor } from "./index";

// Type-checked by the package's "typecheck" script on every build, so the documented Quick Start
// can never silently drift from the real public API — v1's README example didn't compile against
// real props. Not exported from index.ts, so it never reaches the published bundle.

const examplePlugin: EditorPlugin = {
name: "example",
install(engine) {
engine.registry.registerTool("select", { shortcut: "v" });
},
};

function QuickStartApp(): ReactElement {
return (
<Editor
plugins={[examplePlugin]}
theme="dark"
width={800}
height={600}
onReady={(engine) => {
engine.setZoom(1);
}}
/>
);
}

function AddRectangleButton(): ReactElement {
const engine = useEditor();
return (
<button type="button" onClick={() => engine.addObjectOfType("rect", { left: 10, top: 10 })}>
Add rectangle
</button>
);
}

export { QuickStartApp, AddRectangleButton };

A few things worth noticing:

  • plugins is construction-time only. <Editor plugins={[examplePlugin]}> reads its plugins array exactly once, when the engine is constructed — changing the array on a live, already-mounted <Editor> does nothing. There's no safe general story for hot-swapping an installed plugin set (uninstall ordering, plugin-held state), so this is deliberate, not a bug. To swap plugins, remount with a different key (e.g. key={documentId}). The same rule applies to <DesignEditor preset="..."> and its plugins override prop — see Installing Plugins for the full explanation.
  • onReady fires once, synchronously, right after the engine is constructed — it's the place to run first-time setup like engine.setZoom(1) above, or to restore a previously-saved document.
  • useEditor() (used by AddRectangleButton above) gives any descendant component access to the live CanvasEngine instance, as long as it's rendered somewhere inside <Editor> — no prop drilling required.

Batteries-included: <DesignEditor>

The example above uses <Editor> with a single, hand-written example plugin — useful for understanding the underlying contract, but not how most apps start. For a general-purpose editor, <DesignEditor preset="default"> bundles a curated, dependency-light set of plugins (shapes, clipboard, SVG import, images, effects, PDF export, QR codes) with zero configuration:

import { DesignEditor } from "@rifrocket/fdt-react";

function App() {
return <DesignEditor preset="default" theme="system" width={800} height={600} />;
}

See Choosing your entry point for how to decide between <DesignEditor>, <Editor>, and the framework-agnostic createEngine().

Next steps