Scannable QR code drawn on a canvas by the npm qrcode encoder, loaded on first render. Dark modules on a light quiet zone, in every theme, so the code always scans. Use for payment links, portal handoffs and MFA enrollment.
import { Component } from "@angular/core";
import { SuiQrCode } from "@shineui/angular";
@Component({
standalone: true,
imports: [SuiQrCode],
template: `<sui-qr-code value="https://example.com/orders/1043" label="Order link" caption="Order 1043" width="128" (suiRender)="onChange($event)"></sui-qr-code>`,
})
export class Example {
onChange(e: CustomEvent) { console.log(e.detail); }
}
Basic
The canvas is role="img" named "QR code: {value}", so the destination is readable without a camera. The modules stay dark in every theme: the element keeps the computed --ink only while it clears 4.5:1 against the white quiet zone.
width is the side of the square code in px and anything under 96 is raised to 96, because a smaller code stops scanning. Q and H survive a logo or a crease; M is the default and packs the fewest modules.
downloadable adds a Download PNG button, and the download() method saves the same file from your own control. Give each code its own file-name, or three saves land as three files with the same name.
<div style="display:flex;flex-wrap:wrap;gap:20px;align-items:flex-start">
<sui-qr-code value="https://example.com/enroll/mfa" label="MFA enrollment" caption="Scan in your authenticator" width="128" ec-level="Q" downloadable file-name="mfa-enrollment.png"></sui-qr-code>
<div style="display:grid;gap:10px">
<sui-qr-code id="qr-method" value="https://example.com/orders/1043" width="128" file-name="order-1043.png"></sui-qr-code>
<sui-button id="qr-save" variant="outline" size="sm" icon="fa-solid fa-download" label="Save from a method"></sui-button>
</div>
</div>
suiRender fires after each successful draw, including the redraw a new value, width or ecLevel triggers. It carries no detail, so read the element for the state you need.
Waiting for the first draw.
<div style="display:flex;flex-wrap:wrap;gap:20px;align-items:flex-start">
<sui-qr-code id="qr-events" value="https://example.com/orders/1043" width="128" caption="Order 1043"></sui-qr-code>
<div style="display:grid;gap:10px">
<sui-button id="qr-next" variant="outline" size="sm" label="Next order"></sui-button>
<span id="qr-log" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Waiting for the first draw.</span>
</div>
</div>
// setup(root): properties and events
setup(root) {
const el = root.querySelector('#qr-events');
const log = root.querySelector('#qr-log');
let order = 1043;
let draws = 0;
el.addEventListener('suiRender', () => {
draws += 1;
log.textContent = `Drawn ${draws} time(s). Now encoding order ${order}.`;
});
root.querySelector('#qr-next').addEventListener('click', () => {
order += 1;
el.value = `https://example.com/orders/${order}`;
el.caption = `Order ${order}`;
});
}
API
<sui-qr-code>
Properties
Property
Attribute
Type
Default
Description
caption
caption
stringstring | undefined
Caption under the code inside the light frame, in tabular numerals for references and amounts.
downloadable
downloadable
boolean
false
Adds a "Download PNG" button under the code. It calls download().
ecLevel
ec-level
"H" | "L" | "M" | "Q"
'M'
Error correction level. Q or H survive a logo or a crease; M packs the fewest modules.
fileName
file-name
string
'qr-code.png'
File name for download(). Give each code on a page its own, or three saves land as three files with the same name.
label
label
stringstring | undefined
Short label above the code.
value
value
string
''
Text to encode, usually a URL. It is also the canvas's accessible name: "QR code: {value}".
width
width
number
128
Width of the square code in px, which is also its height. Values under 96 are raised to 96, because a smaller code stops scanning.
Events
Event
Detail
React
Vue
Description
suiRender
void
onSuiRender
@sui-render
Fires after each successful draw, including the redraw a new value, width or ecLevel triggers. No detail: read the element for the state you need.
Methods
Method
Signature
Description
download()
download() => Promise<void>
Saves the current code as a PNG named fileName. Does nothing while the encoder is unavailable.
setFocus()
setFocus() => Promise<void>
Moves focus to the Download PNG button, the code's one tab stop. Without downloadable, or while the encoder is unavailable, there is none and focus stays where it is. The host's own focus() does the same.
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.