shadimage
bits-ui
componentjson-formattersource: ok · refreshed

JSON Formatter

A simple, fast tool to format, minify, copy, or download JSON payloads for debugging and sharing.

npx shadcn add "https://bits-ui.netlify.app/r/json-formatter.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Files1 · source cached 10/8/2026, 11:23:41 AM

registry/new-york/ui/json-formatter.tsx
"use client";

import * as React from "react";

export const JSONFormatter: React.FC<{ className?: string }> = ({ className }) => {
  const [raw, setRaw] = React.useState<string>(`{\n  "hello": "world"\n}`);
  const [pretty, setPretty] = React.useState<string>("null");
  const [error, setError] = React.useState<string | null>(null);

  const format = () => {
    try {
      const parsed = JSON.parse(raw);
      const out = JSON.stringify(parsed, null, 2);
      setPretty(out);
      setError(null);
    } catch (e) {
      setError((e as Error).message);
    }
  };

  const minify = () => {
    try {
      const parsed = JSON.parse(raw);
      const out = JSON.stringify(parsed);
      setPretty(out);
      setError(null);
    } catch (e) {
      setError((e as Error).message);
    }
  };

  const copy = async () => {
    await navigator.clipboard.writeText(pretty);
  };

  const download = () => {
    const blob = new Blob([pretty], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "data.json";
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div className={className}>
      <div className="grid gap-2 md:grid-cols-2">
        <div>
          <label className="text-sm font-medium">Input JSON</label>
          <textarea
            spellCheck={false}
            className="mt-2 w-full rounded-lg border p-2 font-mono text-sm min-h-[160px]"
            value={raw}
            onChange={(e) => setRaw(e.target.value)}
          />
          <div className="mt-2 flex gap-2">
            <button onClick={format} className="rounded-2xl px-3 py-1 border">
              Format
            </button>
            <button onClick={minify} className="rounded-2xl px-3 py-1 border">
              Minify
            </button>
          </div>
          {error && <p className="mt-2 text-sm text-red-600">{error}</p>}
        </div>

        <div>
          <label className="text-sm font-medium">Output</label>
          <pre className="mt-2 max-h-[280px] overflow-auto rounded-lg border bg-muted p-2 text-sm font-mono whitespace-pre-wrap">
            {pretty}
          </pre>
          <div className="mt-2 flex gap-2">
            <button onClick={copy} className="rounded-2xl px-3 py-1 border">
              Copy
            </button>
            <button onClick={download} className="rounded-2xl px-3 py-1 border">
              Download
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default JSONFormatter;

More from bits-ui

Browse all components in this library →