QR code

A scannable QR code for a text value on a light tile, with optional copy and download actions.

<tp-qr-code>
QR code
Default density Compact density Restart from the initial state Show the copyable source

Usage

Set value to the text to encode and label to what scanning does. The label names the image for assistive technology and titles SVG exports; the value itself is never announced, because it may be private. Show the link or the text beside the code for people who cannot scan it. The encoder is built in, so there is nothing else to install.

In context

The tile stays light in a dark theme, like a printed sticker, because many scanners cannot read a light code on a dark background.

Connect a device
Default density Compact density Restart from the initial state Show the copyable source

Connect your phone

Open the app on your phone and scan the code to sign in to this workspace.

Done

Copy and download

copyable adds a Copy button that writes the image as PNG and the value as text in one clipboard item, so an image editor pastes the picture and a text field pastes the value. downloadable adds a menu with PNG, SVG and JPG. Files are named after filename and exported at export-size pixels, 1024 by default.

Copy and download
Default density Compact density Restart from the initial state Show the copyable source

Both actions are disabled while there is no code. The copy(), download(), toBlob() and toSVG() methods do the same work without the actions row, for a button or flow of your own.

When the browser refuses images, the text alone is copied.

const code = document.querySelector('tp-qr-code'); await code.download('svg', { size: 512, filename: 'poster-code' }); const png = await code.toBlob('png', { size: 300 });

PNG and JPEG files are exactly the requested size. Every module is the same whole number of pixels, so the code never blurs; the pixels left over widen the quiet zone. JPEG has no transparency and is painted on white. Sizes are clamped between the module count and 4096 pixels.

Live value

Assign value as the source changes and the code re-encodes. status is empty, encoded or error, reflected as data-status, and the tile keeps its size while empty. The button here calls download() with a larger size of its own for printing.

Live value
Default density Compact density Restart from the initial state Show the copyable source
Download print-ready PNG

Error correction

error-correction restores about 7% (L), 15% (M, the default), 25% (Q) or 30% (H) of a damaged code. Higher levels need more modules for the same value, so the code gets denser at the same size. Use H when a logo or sticker may cover part of the code.

Error correction
Default density Compact density Restart from the initial state Show the copyable source

quiet-zone is the light border scanners need around the modules, 4 modules by default. Keep it unless the code sits on a light surface that already provides the margin.

It is drawn inside the tile and included in every export.

The value is encoded in the most compact mode: digits only, upper-case letters with digits and $%*+-./: and spaces, or any text as UTF-8 bytes. The largest code holds:

LevelDigitsUpper-case lettersUTF-8 bytesL708942962953M559633912331Q399324201663H305718521273

Sizes and colors

size is sm (128 px), default (192 px) or lg (256 px), and --tp-qr-code-size sets any other size. --tp-qr-code-foreground and --tp-qr-code-background change the colors on screen and in every export; keep dark modules on a light background with enough contrast, or the element raises a diagnostic.

The tile is square. size picks one of three sizes, and --tp-qr-code-size sets any other size; it can be set on the element or any ancestor. The tile never grows wider than the space around it. A diagnostic warns when the modules are lighter than the background or the contrast is below 3:1.

Sizes and colors
Default density Compact density Restart from the initial state Show the copyable source

Accessibility

The code is an image named by label, or by the qrCode message when label is empty. It is hidden from assistive technology while there is no code. The actions are a group named by the actions message; the Copy button and the Download menu keep their own keyboard behavior and announcements. The image never mirrors in right-to-left layouts, and in forced-colors mode it keeps its own colors so it stays scannable.

Encoding without the element

@tweakpad/ui/qr encodes without a browser, for servers, workers and build scripts:

import { encodeQr, qrPathData } from '@tweakpad/ui/qr'; const code = encodeQr('https://tweakpad.github.io', { errorCorrection: 'Q' }); const quietZone = 4; const extent = code.size + quietZone * 2; const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${extent} ${extent}"><path d="${qrPathData(code, quietZone)}"/></svg>`;

encodeQr(text, { errorCorrection, minVersion, maxVersion, mask }) returns the version, size, mask, mode and modules (row by row, 1 for dark). It throws QrCapacityError, carrying the limit, when the value does not fit. qrCapacity(mode, level, version) gives the limits above.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptionvaluevaluestring''Text to encode.error-correctionerrorCorrectionQrErrorCorrection'M'Error correction level: L, M (default), Q or H.quiet-zonequietZonenumber4The light border around the modules, in modules; scanners expect at least 4.sizesizeQrCodeSize'default'The side of the tile.labellabelstring''Accessible name and export title; the QR code message when empty.copyablecopyablebooleanfalseShows the Copy button.downloadabledownloadablebooleanfalseShows the download Menu.export-sizeexportSizenumber1024Default side of exports and of the copied image, in pixels.filenamefilenamestring'qr-code'Download file name without its extension.

Properties

PropertyTypeDefaultDescriptionmessagesQrCodeMessages{}Replacements for the built-in text, such as the action names; missing entries keep the defaults.qrCodeMessagesread-onlyRequired<QrCodeMessages>—The text in use: messages over the defaults.statusread-onlyQrCodeStatus—empty without a value, encoded, or error when the value does not fit.versionread-onlynumber | null—Version of the encoded symbol, 1 to 40; null while not encoded.moduleCountread-onlynumber | null—Modules per side of the encoded symbol, without the quiet zone; null while not encoded.

Events

EventTypeDescriptiontp-copyCustomEvent<CopyDetail>Cancelable, before copying; detail.value.tp-copiedCustomEvent<CopyResultDetail>After a successful copy; detail.value and the written detail.types.tp-copy-errorCustomEvent<CopyResultDetail>After a failed copy; detail.value.tp-downloadCustomEvent<QrDownloadDetail>Cancelable, before a download; format, size, filename, source event.tp-download-errorCustomEvent<QrDownloadErrorDetail>When the export for a download fails; the same detail and error.

Methods

MethodReturnsDescriptioncopy(sourceEvent?)Promise<boolean>Copies the PNG export (at exportSize) and the value in one clipboard item. With the copy action shown, it runs through the Copy button, which confirms and announces; otherwise it dispatches the same events. Resolves whether anything was written.download(format, options, sourceEvent?)Promise<boolean>Proposes a download with a cancelable tp-download, then hands the export to the browser as filename with the format's extension. Resolves whether the file was handed off.toBlob(format, options)Promise<Blob | null>The symbol as an image file: SVG, PNG or JPEG of size pixels per side (exportSize by default) in the colors the symbol presents; null while not encoded. Painting happens synchronously, so a call inside a click can hand the promise to the clipboard.toSVG(options)string | nullThe symbol as a standalone SVG document of size pixels; null while not encoded.

CSS parts

PartDescription::part(tile)The square light surface.::part(symbol)The SVG image, named by label.::part(background)The light fill of the symbol, quiet zone included.::part(modules)The dark modules, one path.::part(actions)The Button group of the actions.::part(copy)The Copy button.::part(download)The download Menu.::part(download-trigger)The Button that opens the download Menu.::part(download-item)A format item of the download Menu.

CSS custom properties

PropertyDefaultDescription--tp-qr-code-size—Side of the tile; the size axis by default.--tp-qr-code-foreground—Color of the dark modules.--tp-qr-code-background—Color of the light background.