<!-- Protocore Design System — QRCode -->
# QRCode

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/qr-code`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { QRCode } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/qr-code

> Renders a string as a crisp monochrome QR code (inline SVG) from a hand-rolled encoder — no dependency.

## The encoder

The QR matrix is produced by a small, self-contained encoder (byte mode, versions 1–10, all four ECC levels) — Reed–Solomon error correction over GF(256), block interleaving, and automatic mask selection by penalty score. There is no runtime dependency, and because encoding is deterministic the component is server-safe: SSR and hydration produce the identical SVG.

Versions 1–10 hold up to roughly 270 bytes at level L, which covers any URL and most tokens. A payload beyond that throws during encode; the component catches it and renders an invalid marker rather than a broken code — that's the point to reach for a dedicated library.

For reliable scanning across every reader, place the code on a plain, light surface and keep the quiet zone clear.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `ecc` | `enum` | no | `L` | Error-correction level. Use `"M"` or higher when adding a `logo`. |
| `label` | `string` | no | — | Accessible name describing what the code encodes. |
| `logo` | `ReactNode` | no | — | Optional centre mark. Reserves a light patch in the matrix — pair with `ecc="M"`+. |
| `margin` | `number` | no | `4` | Quiet-zone width in modules (the standard is 4). |
| `size` | `number` | no | `160` | Rendered width/height in px. |
| `style` | `CSSProperties` | no | — | — |
| `value` | `string` | yes | — | The string to encode (a URL, token, or any UTF-8 text). |

## Examples

### Encoding a URL

Pass a `value` — a URL, token, or any UTF-8 string — and it renders as a sharp inline-SVG QR code. Dark modules paint in `currentColor` over a transparent quiet zone, so the code inherits the ink color and stays crisp at any `size`.

```tsx
import { QRCode, Text } from "@protocore/pds";

export default function QRCodeBasics() {
  return (
    <div style={{ display: "flex", gap: 24, alignItems: "center", flexWrap: "wrap" }}>
      <div style={{ background: "#fff", padding: 12, display: "inline-flex" }}>
        <QRCode value="https://pds.protocore.io" label="Open pds.protocore.io" size={148} />
      </div>
      <Text size="sm" color="muted">
        pds.protocore.io — encoded at version 1, level L. Placed on a light patch for reliable
        scanning.
      </Text>
    </div>
  );
}
```

### Error correction and a centre logo

`ecc` sets the error-correction level (`L`/`M`/`Q`/`H`). A `logo` slot reserves a light patch in the centre and overlays your mark — raise `ecc` to `"M"` or higher first, since the logo occludes data modules that the redundancy then recovers.

```tsx
import { QRCode } from "@protocore/pds";

export default function QRCodeLogo() {
  return (
    <div style={{ display: "flex", gap: 24, flexWrap: "wrap" }}>
      <div style={{ background: "#fff", padding: 12, display: "inline-flex" }}>
        <QRCode
          value="https://protocore.io"
          ecc="Q"
          size={168}
          label="Open protocore.io"
          logo={
            <svg viewBox="0 0 24 24" width="100%" height="100%" aria-hidden="true">
              <rect x="2" y="2" width="20" height="20" fill="#000" />
              <path d="M7 17V7h5a3 3 0 0 1 0 6H7" fill="none" stroke="#fff" strokeWidth="2" />
            </svg>
          }
        />
      </div>
    </div>
  );
}
```

## Usage

**Do**

- Encode URLs and short tokens; keep payloads compact.
- Raise `ecc` to `M`+ whenever you add a centre `logo`.
- Give it a `label` describing where the code leads.
- Place it on a plain, light surface with the quiet zone intact.

**Don't**

- Encode very long strings; versions cap at 10 and it will fail.
- Add a logo at ECC `L`; the occlusion can break scanning.
- Recolor it to low contrast; scanners need a clear dark/light split.
- Crop the quiet-zone margin; readers rely on it.

## Accessibility

**Notes**

- The code is `role="img"` with an `aria-label` from the `label` prop; the SVG itself is `aria-hidden` so it isn't announced as decorative graphics.
- A QR code is not a substitute for a link — offer the underlying URL as selectable text or a real anchor alongside it for users who can't scan.

## Related

`masked-value`, `copy-button`, `code`, `image`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
