Skip to main content

QR Codes

Adding an editable QR code to the canvas is a high-frequency need for coupons, invitations, business cards, etc. The recipe:

  1. Use qrcode to generate an SVG string
  2. Use svgToURL to convert to dataURL, insert as an Image
  3. Stash the original text in the element's custom field so you can re-generate later

Add a QR code

import QRCode from 'qrcode';
import { svgToURL } from '@ydesign/react-editor/utils/svg';
import { generateObjectId } from '@ydesign/core';

async function addQRCode(store: any, text: string) {
const svgStr = await QRCode.toString(text, {
type: 'svg',
color: { dark: '#000', light: '#fff' },
width: 400,
margin: 2,
});

const src = svgToURL(svgStr);

store.addElement({
id: generateObjectId(),
type: 'Image',
src,
left: 100,
top: 100,
width: 400,
height: 400,
custom: { qrText: text }, // 👈 store the original text
});
}

addQRCode(store, 'https://ydesign.com');

Edit the content

import { observer } from 'mobx-react-lite';
import { Input } from 'antd';
import QRCode from 'qrcode';
import { svgToURL } from '@ydesign/react-editor/utils/svg';

const QRCodeEditor = observer(({ store }) => {
const el = store.selectedElements[0];
if (!el?.custom?.qrText) return null;

const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value;
const svgStr = await QRCode.toString(text, {
type: 'svg',
color: { dark: '#000', light: '#fff' },
width: el.width,
margin: 2,
});

store.set(
{
src: svgToURL(svgStr),
custom: { qrText: text },
},
el,
);
};

return (
<div style={{ padding: 12 }}>
<div>QR content:</div>
<Input value={el.custom.qrText} onChange={handleChange} />
</div>
);
});

Bundle as a custom Section

Combine addQRCode + QRCodeEditor into a side panel section (see Custom Section):

import type { Section } from '@ydesign/react-editor/side-panel';
import { QrCode } from 'lucide-react';

const QRCodeSection: Section = {
name: 'qrcode',
Tab: /* ... SectionTab with QrCode icon ... */,
Panel: observer(({ store }) => (
<div>
<Button onClick={() => addQRCode(store, 'https://ydesign.com')}>Add QR code</Button>
<QRCodeEditor store={store} />
</div>
)),
};

<SidePanel store={store} sections={[...DEFAULT_SECTIONS, QRCodeSection]} />;

Key points

  • custom field: Fabric's extension slot. It serializes with store.toJSON(), so re-opening the design still lets you edit the QR
  • SVG + dataURL: vector output, stays sharp at any export multiplier
  • Error correction: qrcode defaults to level M. For logo-in-QR designs, use errorCorrectionLevel: 'H'

See also