React componentsadalah cara yang kuat untuk membuat elemen interaktif dan dapat digunakan kembali dalam dokumentasi Anda.

Anda dapat menggunakan React langsung dalam file MDX Anda tanpa pengaturan tambahan.

Menggunakan Komponen React

Anda dapat membangun komponen langsung dalam file MDX Anda menggunakanReact hooks.

Contoh Dasar

Berikut adalah contoh dasar komponen penghitung:

export const Counter = () => {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Current count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
    </div>
  );
}

KomponenCounterkemudian dapat digunakan dalam file MDX Anda seperti ini:

<Counter />

Dan komponen tersebut akan dirender sebagai komponen React dalam file MDX.

Mengimpor Komponen

Sama seperti di React biasa, Anda dapat mengimpor komponen dari file lain.

import { ColorGenerator } from "/snippets/color-generator.mdx"

Tetapi tidak seperti React biasa, Anda tidak dapat mengimpor komponen dari setiap file MDX. Komponen yang dapat digunakan kembali hanya dapat direferensikan dari file MDX dalam foldersnippets.

Setelah mengimpor komponen, Anda dapat menggunakannya dalam file MDX Anda seperti ini:

<ColorGenerator />

Pelajari lebih lanjut tentangreusable snippets.

Contoh Kompleks

Anda juga dapat membangun komponen yang jauh lebih kompleks. Berikut adalah contoh komponen pembuat warna yang menggunakan beberapa React hooks:

/snippets/color-generator.mdx
export const ColorGenerator = () => {
  const [hue, setHue] = useState(180)
  const [saturation, setSaturation] = useState(50)
  const [lightness, setLightness] = useState(50)
  const [colors, setColors] = useState([])

  useEffect(() => {
    const newColors = []
    for (let i = 0; i < 5; i++) {
      const l = Math.max(10, Math.min(90, lightness - 20 + i * 10))
      newColors.push(`hsl(${hue}, ${saturation}%, ${l}%)`)
    }
    setColors(newColors)
  }, [hue, saturation, lightness])

  const copyToClipboard = (color) => {
    navigator.clipboard
      .writeText(color)
      .then(() => {
        console.log(`Copied ${color} to clipboard!`)
      })
      .catch((err) => {
        console.error("Failed to copy: ", err)
      })
  }

  return (
    <div className="p-4 border dark:border-zinc-950/80 rounded-xl not-prose">
      <div className="space-y-4">
        <div className="space-y-2">
          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Hue: {hue}°
            <input
              type="range"
              min="0"
              max="360"
              value={hue}
              onChange={(e) => setHue(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(0, ${saturation}%, ${lightness}%), 
                  hsl(60, ${saturation}%, ${lightness}%), 
                  hsl(120, ${saturation}%, ${lightness}%), 
                  hsl(180, ${saturation}%, ${lightness}%), 
                  hsl(240, ${saturation}%, ${lightness}%), 
                  hsl(300, ${saturation}%, ${lightness}%), 
                  hsl(360, ${saturation}%, ${lightness}%))`,
              }}
            />
          </label>

          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Saturation: {saturation}%
            <input
              type="range"
              min="0"
              max="100"
              value={saturation}
              onChange={(e) => setSaturation(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(${hue}, 0%, ${lightness}%), 
                  hsl(${hue}, 50%, ${lightness}%), 
                  hsl(${hue}, 100%, ${lightness}%))`,
              }}
            />
          </label>

          <label className="block text-sm text-zinc-950/70 dark:text-white/70">
            Lightness: {lightness}%
            <input
              type="range"
              min="0"
              max="100"
              value={lightness}
              onChange={(e) => setLightness(Number.parseInt(e.target.value))}
              className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
              style={{
                background: `linear-gradient(to right, 
                  hsl(${hue}, ${saturation}%, 0%), 
                  hsl(${hue}, ${saturation}%, 50%), 
                  hsl(${hue}, ${saturation}%, 100%))`,
              }}
            />
          </label>
        </div>

        <div className="flex space-x-1">
          {colors.map((color, idx) => (
            <div
              key={idx}
              className="h-16 rounded flex-1 cursor-pointer transition-transform hover:scale-105"
              style={{ backgroundColor: color }}
              title={`Click to copy: ${color}`}
              onClick={() => copyToClipboard(color)}
            />
          ))}
        </div>

        <div className="text-sm font-mono text-zinc-950/70 dark:text-white/70">
          <p>
            Base color: hsl({hue}, {saturation}%, {lightness}%)
          </p>
        </div>
      </div>
    </div>
  )
}

Komponen di atas kemudian dapat digunakan dalam file MDX Anda seperti ini:

<ColorGenerator />

Dan komponen tersebut akan dirender sebagai komponen React dalam file MDX.

Pertimbangan