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";
export function DynamicForm({ schema, uiSchema }: DynamicFormProps) {
const [data, setData] = useState({});
const [errors, setErrors] = useState<{ message?: string }[]>([]);
return (
<>
<JsonForms
schema={schema}
uischema={uiSchema}
data={data}
renderers={shadcnRenderers}
cells={shadcnCells}
onChange={({ data, errors }) => {
setData(data);
setErrors(errors ?? []);
}}
/>
<button disabled={errors.length > 0} onClick={handleSubmit}>
Submit
</button>
</>
);
}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 [errors, setErrors] = useState<{ message?: string }[]>([]);
const { data: form, loading: formLoading } = formsClient.useForm({
path: { slug: "contact" },
});
const { mutate: submit, data: responseId, loading: submitting } = formsClient.useSubmitForm();
if (formLoading || !form) return <div>Loading...</div>;
if (responseId) return <div>Thank you for your submission!</div>;
const handleSubmit = async () => {
await submit({
path: { slug: "contact" },
body: { data: formData },
});
};
return (
<>
<JsonForms
schema={form.dataSchema}
uischema={form.uiSchema}
data={formData}
renderers={shadcnRenderers}
cells={shadcnCells}
onChange={({ data, errors }) => {
setFormData(data ?? {});
setErrors(errors ?? []);
}}
/>
<button type="submit" disabled={submitting || errors.length > 0} onClick={handleSubmit}>
{submitting ? "Submitting..." : "Submit"}
</button>
</>
);
}Form Builder
We also provide a visual form builder component that generates JSON Schema and UI Schema compatible with these renderers. See the Form Builder page for installation and usage details.
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 | ✅ |