Skip to content

Solid

Terminal window
npm install @kadal/deck-solid solid-js vite-plugin-solid
// vite.config.ts — both plugins want .tsx, so each is told which files are whose
import { deckSolidFiles } from "@kadal/deck-solid/build";
import react from "@vitejs/plugin-react";
import solid from "vite-plugin-solid";
plugins: [react({ exclude: [...deckSolidFiles] }), solid({ include: [...deckSolidFiles] })];
/** @jsxImportSource solid-js */
// chart.solid.tsx — the pragma is the type-level half of the same statement
import { deckSolid } from "@kadal/deck-solid";
export const Chart = deckSolid((props: { data: number[] }) => <svg>…</svg>);
<Island load={() => import("./chart.solid.tsx").then((m) => m.Chart)} props={{ data }} />
src/main.tsx
registerLazyRenderer("solid", () => import("@kadal/deck-solid").then((m) => m.solidRenderer));

React’s JSX transform and Solid’s are mutually unintelligible, and both plugins claim .tsx. There is no detecting which file is whose — they look identical until compiled — so the convention is *.solid.tsx, exported as deckSolidFiles, handed to both plugins so the filters can’t drift apart. The same collision exists for types (the deck’s tsconfig points JSX at React), so a Solid file also opens with /** @jsxImportSource solid-js */. Both are needed; neither implies the other.

Props are getters. A Solid component body runs once, so the renderer passes a store proxy and update is a reconcile that touches only the keys that changed.