shadcn/ui Renderer
Render JSONForms with shadcn/ui components
Overview
The @fragno-dev/jsonforms-shadcn-renderers package provides a JSONForms renderer built for
shadcn/ui components. Use it to render forms from the Form fragment with a consistent shadcn/ui look
and feel.
Because shadcn/ui inherently vendors components, we rely on the bundler to resolve component imports in your project.
Installation
Install the renderer package alongside JSONForms React:
npm install @fragno-dev/jsonforms-shadcn-renderers @jsonforms/reactRequired ShadCN Components
The renderers use these shadcn/ui components. Add them to your project:
npx shadcn@latest add button \
calendar \
card \
checkbox \
field \
input \
label \
popover \
radio-group \
select \
slider \
switch \
tabs \
textareaConfiguration
Vite
The renderers import shadcn components from @/components/ui/*. Configure Vite to resolve these
imports:
import { defineConfig } from "vite";
import path from "path";
export default defineConfig({
resolve: {
alias: {
"@/components": path.resolve(__dirname, "./src/components"),
"@/lib": path.resolve(__dirname, "./src/lib"),
},
},
ssr: {
noExternal: ["@fragno-dev/jsonforms-shadcn-renderers"],
},
});Tailwind CSS
Include the package in your Tailwind sources so the renderer classes are included in your build:
@source "../node_modules/@fragno-dev/jsonforms-shadcn-renderers";See the Tailwind docs on source detection for more details.
Usage
Use the shadcnRenderers and shadcnCells with the JSONForms component:
import { useState } from "react";
import { JsonForms } from "@jsonforms/react";
import { shadcnRenderers, shadcnCells } from "@fragno-dev/jsonforms-shadcn-renderers";
interface DynamicFormProps {
schema: Record<string, unknown>;
uiSchema: Record<string, unknown>;
onSubmit: (data: Record<string, unknown>) => void;
}
export function DynamicForm({ schema, uiSchema, onSubmit }: DynamicFormProps) {
const [data, setData] = useState({});
return (
<form
onSubmit={(e) => {
e.preventDefault();
onSubmit(data);
}}
>
<JsonForms
schema={schema}
uischema={uiSchema}
data={data}
renderers={shadcnRenderers}
cells={shadcnCells}
onChange={({ data }) => setData(data)}
/>
<button type="submit">Submit</button>
</form>
);
}With the Form Fragment
Combine the renderer with the Form fragment client:
import { useState } from "react";
import { JsonForms } from "@jsonforms/react";
import { shadcnRenderers, shadcnCells } from "@fragno-dev/jsonforms-shadcn-renderers";
import { formsClient } from "@/lib/forms-client";
export function ContactForm() {
const [formData, setFormData] = useState({});
const { data: form, loading: formLoading } = formsClient.useForm({
pathParams: { slug: "contact" },
});
const { mutate: submit, loading: submitting } = formsClient.useSubmitForm();
if (formLoading || !form) return <div>Loading...</div>;
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await submit({
pathParams: { slug: "contact" },
body: { data: formData },
});
};
return (
<form onSubmit={handleSubmit}>
<JsonForms
schema={form.dataSchema}
uischema={form.uiSchema}
data={formData}
renderers={shadcnRenderers}
cells={shadcnCells}
onChange={({ data }) => setFormData(data ?? {})}
/>
<button type="submit" disabled={submitting}>
{submitting ? "Submitting..." : "Submit"}
</button>
</form>
);
}Supported Features
JSONforms primitives supported by this renderer.
Controls
| Feature | Status |
|---|---|
| Boolean (checkbox) | ✅ |
| Boolean (toggle/switch) | ✅ |
| Text | ✅ |
| Textarea (multi-line) | ✅ |
| Integer | ✅ |
| Number | ✅ |
| Slider | ✅ |
| Date | ✅ |
| Time | ✅ |
| DateTime | ✅ |
| Enum (select) | ✅ |
| Enum (radio) | ✅ |
| OneOf Enum (select) | ✅ |
| OneOf Enum (radio) | ❌ |
| Object (nested) | ✅ |
| Array (table) | ❌ |
| Array (expandable panels) | ❌ |
| AllOf | ❌ |
| AnyOf | ❌ |
| OneOf (polymorphic) | ❌ |
| Enum Array (multi-select) | ❌ |
| AnyOf String/Enum | ❌ |
| Native inputs | ❌ |
Layouts
| Feature | Status |
|---|---|
| Vertical | ✅ |
| Horizontal | ✅ |
| Group | ✅ |
| Categorization (tabs) | ✅ |
| Categorization (stepper) | ✅ |
| Array Layout | ❌ |
Additional Renderers
| Feature | Status |
|---|---|
| Label | ✅ |
| ListWithDetail | ❌ |
Cells
| Feature | Status |
|---|---|
| Boolean | ✅ |
| Boolean Toggle | ✅ |
| Text | ✅ |
| Integer | ✅ |
| Number | ✅ |
| Number Format | ❌ |
| Date | ✅ |
| Time | ✅ |
| DateTime | ✅ |
| Enum | ✅ |
| Enum Radio | ✅ |
| OneOf Enum | ✅ |
| Slider | ✅ |