QR code
A scannable QR code for a text value on a light tile, with optional copy and download actions.
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 your phone
Open the app on your phone and scan the code to sign in to this workspace.
Connect your phone
Open the app on your phone and scan the code to sign in to this workspace.
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.
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.
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.
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.
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:
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.
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:
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
valuevaluestring''error-correctionerrorCorrectionQrErrorCorrection'M'quiet-zonequietZonenumber4sizesizeQrCodeSize'default'labellabelstring''copyablecopyablebooleanfalsedownloadabledownloadablebooleanfalseexport-sizeexportSizenumber1024filenamefilenamestring'qr-code'Properties
messagesQrCodeMessages{}qrCodeMessagesread-onlyRequired<QrCodeMessages>messages over the defaults.statusread-onlyQrCodeStatusempty without a value, encoded, or error when the value does not fit.versionread-onlynumber | nullmoduleCountread-onlynumber | nullEvents
tp-copyCustomEvent<CopyDetail>detail.value.tp-copiedCustomEvent<CopyResultDetail>detail.value and the written detail.types.tp-copy-errorCustomEvent<CopyResultDetail>detail.value.tp-downloadCustomEvent<QrDownloadDetail>tp-download-errorCustomEvent<QrDownloadErrorDetail>error.Methods
copy(sourceEvent?)Promise<boolean>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>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>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 | nullsize pixels; null while not encoded.CSS parts
::part(tile)::part(symbol)label.::part(background)::part(modules)::part(actions)::part(copy)::part(download)::part(download-trigger)::part(download-item)CSS custom properties
--tp-qr-code-sizesize axis by default.--tp-qr-code-foreground--tp-qr-code-background