Claude
Skills
Sign in
Back

ecosystem-integrations

Included with Lifetime
$97 forever

MUI ecosystem — FormEngine, react-jsonschema-form, Uniforms, schema-driven forms, Tailwind interop, Framer Motion, and third-party component libraries

Design

What this skill does


# MUI Ecosystem Integrations

Third-party libraries, schema-driven form builders, styling interop, and animation
integrations that extend MUI's capabilities.

---

## Schema-Driven Form Builders

### FormEngine with MUI

JSON config renders live MUI forms with validation and event wiring.

```bash
npm install @react-form-builder/core @react-form-builder/components-material-ui
```

```tsx
import { FormViewer } from '@react-form-builder/core';
import { view as muiView } from '@react-form-builder/components-material-ui';

const contactForm = {
  tooltipType: 'MuiTooltip',
  errorType: 'MuiErrorWrapper',
  form: {
    key: 'Screen',
    type: 'Screen',
    children: [
      {
        key: 'name',
        type: 'MuiTextField',
        props: { label: { value: 'Full Name' } },
        schema: { validations: [{ key: 'required' }] },
      },
      {
        key: 'email',
        type: 'MuiTextField',
        props: { label: { value: 'Email' } },
        schema: { validations: [{ key: 'required' }, { key: 'email' }] },
      },
      {
        key: 'role',
        type: 'MuiSelect',
        props: {
          label: { value: 'Role' },
          options: { value: [
            { value: 'admin', label: 'Admin' },
            { value: 'user', label: 'User' },
          ]},
        },
      },
      {
        key: 'submit',
        type: 'MuiButton',
        props: {
          children: { value: 'Submit' },
          variant: { value: 'contained' },
        },
        events: {
          onClick: [
            { name: 'validate', type: 'common', args: { failOnError: true } },
            { name: 'onSubmit', type: 'custom' },
          ],
        },
      },
    ],
  },
};

function DynamicForm() {
  return (
    <FormViewer
      view={muiView}
      getForm={() => JSON.stringify(contactForm)}
      actions={{
        onSubmit: (e) => console.log('Form data:', e.data),
      }}
    />
  );
}
```

**MUI Components Pack** maps JSON types to real MUI components:
`MuiTextField`, `MuiSelect`, `MuiCheckbox`, `MuiSwitch`, `MuiButton`,
`MuiDialog`, `MuiCard`, `MuiAutocomplete`, `MuiDatePicker`, etc.

**Conditional Rendering** with `renderWhen`:
```json
{
  "key": "discountCode",
  "type": "MuiTextField",
  "props": { "label": { "value": "Discount Code" } },
  "renderWhen": { "value": "form.data.hasDiscount === true" }
}
```

### react-jsonschema-form with MUI

JSON Schema → MUI form rendering.

```bash
npm install @rjsf/core @rjsf/mui @rjsf/validator-ajv8
```

```tsx
import Form from '@rjsf/mui';
import validator from '@rjsf/validator-ajv8';

const schema = {
  type: 'object',
  required: ['name', 'email'],
  properties: {
    name: { type: 'string', title: 'Full Name' },
    email: { type: 'string', title: 'Email', format: 'email' },
    age: { type: 'integer', title: 'Age', minimum: 18 },
    role: {
      type: 'string',
      title: 'Role',
      enum: ['admin', 'editor', 'viewer'],
      enumNames: ['Administrator', 'Editor', 'Viewer'],
    },
    bio: { type: 'string', title: 'Biography' },
  },
};

const uiSchema = {
  bio: { 'ui:widget': 'textarea', 'ui:options': { rows: 4 } },
  role: { 'ui:widget': 'select' },
  'ui:order': ['name', 'email', 'age', 'role', 'bio'],
};

function JsonSchemaForm() {
  return (
    <Form
      schema={schema}
      uiSchema={uiSchema}
      validator={validator}
      onSubmit={({ formData }) => console.log(formData)}
    />
  );
}
```

**Custom Widgets and Templates**:
```tsx
const widgets = {
  DateWidget: (props) => (
    <DatePicker value={dayjs(props.value)} onChange={(d) => props.onChange(d?.toISOString())} />
  ),
};

const templates = {
  ObjectFieldTemplate: (props) => (
    <Grid container spacing={2}>
      {props.properties.map((prop) => (
        <Grid key={prop.name} size={{ xs: 12, md: 6 }}>
          {prop.content}
        </Grid>
      ))}
    </Grid>
  ),
};

<Form schema={schema} widgets={widgets} templates={templates} validator={validator} />
```

### Uniforms with MUI Bridge

Multi-schema form engine with pluggable styling bridges.

```bash
npm install uniforms uniforms-bridge-json-schema uniforms-mui
```

```tsx
import { AutoForm, AutoField, SubmitField } from 'uniforms-mui';
import { JSONSchemaBridge } from 'uniforms-bridge-json-schema';
import Ajv from 'ajv';

const ajv = new Ajv({ allErrors: true });
const schema = {
  type: 'object',
  properties: {
    name: { type: 'string' },
    email: { type: 'string', format: 'email' },
  },
  required: ['name', 'email'],
};

const bridge = new JSONSchemaBridge({ schema, validator: ajv.compile(schema) });

<AutoForm schema={bridge} onSubmit={(data) => save(data)}>
  <AutoField name="name" />
  <AutoField name="email" />
  <SubmitField />
</AutoForm>
```

### When to Use What

| Tool | Best For |
|------|----------|
| **FormEngine + MUI** | Admin builders, dynamic forms from metadata, runtime JSON config |
| **react-jsonschema-form + MUI** | JSON Schema-driven forms, API-defined schemas |
| **Uniforms + MUI** | Multi-schema support, rapid prototyping |
| **React Hook Form + MUI** | Hand-coded forms with type-safe validation (Zod) |
| **Formik + MUI** | Legacy projects already using Formik |

---

## Tailwind CSS + MUI Interop

### Using MUI with Tailwind

MUI and Tailwind can coexist. Key: Tailwind's preflight conflicts with MUI's CssBaseline.

**Setup** (`tailwind.config.ts`):
```ts
export default {
  // Important: disable preflight to avoid conflicts with CssBaseline
  corePlugins: {
    preflight: false,
  },
  // Scope Tailwind to avoid class conflicts
  important: '#root', // or use selector strategy
  content: ['./src/**/*.{ts,tsx}'],
};
```

**Emotion + Tailwind ordering** — ensure Emotion styles take precedence:
```tsx
import createCache from '@emotion/cache';
import { CacheProvider } from '@emotion/react';

const cache = createCache({
  key: 'css',
  prepend: true, // Emotion styles inserted BEFORE Tailwind → Tailwind can override
});

<CacheProvider value={cache}>
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <App />
  </ThemeProvider>
</CacheProvider>
```

**Using Tailwind classes on MUI components**:
```tsx
// Tailwind classes work alongside sx prop
<Button className="rounded-full shadow-lg" sx={{ px: 4 }}>
  Mixed styling
</Button>

// Use Tailwind for layout, MUI for component styles
<Box className="flex items-center gap-4 p-6">
  <TextField label="Name" fullWidth />
  <Button variant="contained">Save</Button>
</Box>
```

### Base UI + Tailwind (Headless + Utility)

The cleanest integration: Base UI hooks for logic/a11y, Tailwind for all visuals.

```tsx
import { useButton } from '@mui/base/useButton';
import clsx from 'clsx';

function TailwindButton({ children, variant = 'primary', ...props }) {
  const { getRootProps, active, disabled, focusVisible } = useButton(props);

  return (
    <button
      {...getRootProps()}
      className={clsx(
        'rounded-lg px-4 py-2 font-medium transition-all duration-150',
        variant === 'primary' && 'bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800',
        variant === 'secondary' && 'bg-slate-200 text-slate-900 hover:bg-slate-300',
        disabled && 'opacity-50 cursor-not-allowed',
        focusVisible && 'ring-2 ring-blue-400 ring-offset-2',
        active && 'scale-95',
      )}
    >
      {children}
    </button>
  );
}
```

---

## Framer Motion + MUI

### AnimatePresence with MUI Dialog

```tsx
import { AnimatePresence, motion } from 'framer-motion';
import Dialog from '@mui/material/Dialog';

function AnimatedDialog({ open, onClose, children }) {
  return (
    <AnimatePresence>
      {open && (
        <Dialog
          open={open}
          onClose={onClose}
          PaperComponent={motion.div}
          PaperProps={{
            initial: { opacity: 0, scale: 0.9, y: 20 },
            animate: { opacity: 1, scale: 1, y: 0 },
            exit: { opacity: 0, scale: 0.95, y: -10 },
            transition: { type: 'spring', stiffness: 300, damping: 25 },
          }}
     

Related in Design