JsonInput

Capture json data from user

PackageIcon

Usage

JsonInput is based on the Textarea component. It includes JSON validation logic and an option to format the input value on blur:

import { JsonInput } from '@mantine/core';

function Demo() {
  return (
    <JsonInput
      label="Your package.json"
      placeholder="Textarea will autosize to fit the content"
      validationError="Invalid JSON"
      formatOnBlur
      autosize
      minRows={4}
    />
  );
}

Loading state

Set loading prop to display a loading indicator. By default, the loader is displayed on the right side of the input. You can change the position with the loadingPosition prop to 'left' or 'right'. This is useful for async operations like API calls, searches, or validations:

import { JsonInput } from '@mantine/core';

function Demo() {
  return <JsonInput placeholder="Enter JSON" formatOnBlur autosize minRows={4} loading />;
}

Controlled

import { useState } from 'react';
import { JsonInput } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState('');
  return <JsonInput value={value} onChange={setValue} />;
}

Uncontrolled

JsonInput can be used with uncontrolled forms the same way as a native textarea element. Set the name attribute to include json input value in FormData object on form submission. To control the initial value in uncontrolled forms, use the defaultValue prop.

Example usage of uncontrolled JsonInput with FormData:

import { JsonInput } from '@mantine/core';

function Demo() {
  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);
        console.log('JSON input value:', formData.get('data'));
      }}
    >
      <JsonInput
        label="Enter JSON"
        name="data"
        defaultValue="{}"
        formatOnBlur
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Custom serialization

You can provide custom serialize and deserialize functions to support data formats beyond standard JSON. This is useful when you need to handle types like Date, Map, Set, undefined, or other non-JSON-serializable values.

The example below shows how to use superjson library to handle extended data types:

import { useState } from 'react';
import { JsonInput } from '@mantine/core';
import superjson from 'superjson';

function Demo() {
  const [value, setValue] = useState(
    superjson.stringify(
      {
        name: 'John Doe',
        createdAt: new Date(),
        tags: new Set(['admin', 'user']),
        metadata: new Map([['role', 'developer']]),
      },
      null,
      2
    )
  );

  return (
    <JsonInput
      label="Extended JSON with superjson"
      description="Supports Date, Map, Set, BigInt, RegExp, and more"
      placeholder="Enter extended JSON"
      value={value}
      onChange={setValue}
      serialize={(val) => superjson.stringify(val, null, 2)}
      deserialize={superjson.parse}
      validationError="Invalid extended JSON format"
      formatOnBlur
      autosize
      minRows={6}
    />
  );
}

The deserialize function must throw an error when the input is invalid. Both serialize and deserialize functions are used for formatting when formatOnBlur is enabled.

Input props

JsonInput component supports Input and Input.Wrapper component features and all textarea element props. The JsonInput documentation does not include all features supported by the component – see the Input documentation to learn about all available features.

Input description

Variant
Size
Radius
import { JsonInput } from '@mantine/core';

function Demo() {
  return (
    <JsonInput
      label="Input label"
      description="Input description"
      placeholder="Input placeholder"
    />
  );
}

Disabled state

import { JsonInput } from '@mantine/core';

function Demo() {
  return (
    <JsonInput disabled defaultValue='{ "a": 1, "B": 2 }' label="Disabled" placeholder="Disabled" />
  );
}

Styles API

JsonInput supports the Styles API; you can add styles to any inner element of the component with the classNames prop. Follow the Styles API documentation to learn more.

Description

Error

Component Styles API

Hover over selectors to highlight corresponding elements

/*
 * Hover over selectors to apply outline styles
 *
 */

Get element ref

import { useRef } from 'react';
import { JsonInput } from '@mantine/core';

function Demo() {
  const ref = useRef<HTMLTextAreaElement>(null);
  return <JsonInput ref={ref} />;
}

Accessibility

If JsonInput is used without the label prop, it will not be announced properly by screen readers:

import { JsonInput } from '@mantine/core';

// Inaccessible input – screen reader will not announce it properly
function Demo() {
  return <JsonInput />;
}

Set aria-label to make the input accessible. In this case the label will not be visible, but screen readers will announce it:

import { JsonInput } from '@mantine/core';

// Accessible input – it has aria-label
function Demo() {
  return <JsonInput aria-label="My input" />;
}

If the label prop is set, the input will be accessible and it is not required to set aria-label:

import { JsonInput } from '@mantine/core';

// Accessible input – it has associated label element
function Demo() {
  return <JsonInput label="My input" />;
}