QR Code
Dependency-free QR Code encoder and headless SVG renderer.
| Package | @vizejs/ui/qr-code |
| Maturity | stable |
| Own the source | vize lib pull qr-code |
| Requires | — |
| Aliases | qr-code, qr, qrcode, 2d barcode, matrix code |
| Covers | ISO/IEC 18004 QR Code model 2, Project Nayuki QR Code generator, Ark UI QR Code, Mantine QR code examples |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { QrCode } from "@vizejs/ui/qr-code";
Or copy the source into your project with vize lib pull qr-code (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- QR code SVG that encodes a URL with an explicit accessible name. -->
<script setup lang="ts">
import { QrCode } from "@vizejs/ui/qr-code";
</script>
<template>
<figure>
<QrCode value="https://vizejs.dev" label="QR code linking to vizejs.dev" error-correction="Q" />
<figcaption>Scan to open the Vize documentation.</figcaption>
</figure>
</template>
API
QrCode
Source: src/families/media/qr-code/qr-code.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value (required) |
QrCodeValue |
required |
Text (segmented automatically; byte runs are UTF-8), bytes, or explicit segments from the createQrCode*Segment helpers. |
errorCorrection |
QrCodeErrorCorrection |
"M" |
Minimum error correction level. Prefer "H" when an overlay covers the center. |
boostErrorCorrection |
boolean |
false |
Raise the error correction level while the data still fits the chosen version. |
version |
QrCodeVersion | "auto" |
"auto" |
Fixed symbol version, or "auto" for the smallest fitting version. |
mask |
QrCodeMask | "auto" |
"auto" |
Fixed data mask, or "auto" for the lowest-penalty mask. |
mode |
QrCodeMode | "auto" |
"auto" |
Forced single encoding mode, or "auto" to follow segmentation. |
segmentation |
QrCodeSegmentation |
"optimal" |
Automatic segmentation: "optimal" mixes modes for the fewest bits, "single" keeps the most compact single mode. |
kanji |
QrCodeKanjiEncoder |
undefined |
Shift_JIS mapping enabling Kanji segments, e.g. qrCodeKanjiEncoder imported from the opt-in Kanji table module. |
eci |
number |
undefined |
ECI designator written before the data (26 = UTF-8, 20 = Shift_JIS). |
utf8Eci |
boolean |
false |
Declare UTF-8 byte data with ECI 26. |
quietZone |
number |
4 |
Light margin in modules around the symbol. Scanners expect 4. |
label |
string |
undefined |
Accessible name. Defaults to the text value; byte values need an explicit label. |
decorative |
boolean |
false |
Hide the symbol from assistive technology when adjacent text already conveys it. |
foreground |
string |
"currentColor" |
SVG fill for dark modules. Consumer CSS on [part="modules"] can override it. |
background |
string |
"none" |
SVG fill for the light background. Consumer CSS on [part="background"] can override it. |
Slots
| Slot | Slot props | Description |
|---|---|---|
overlay |
QrCodeSlotState |
SVG content drawn above the modules, in module coordinates (for example a centered <image> logo). Only rendered while the value encodes. |
fallback |
QrCodeSlotState |
Content rendered instead of the symbol when the value cannot be encoded. |
Exposed
| Member | Type | Description |
|---|---|---|
state |
QrCodeState |
Whether the value encoded successfully. |
matrix |
QrCodeMatrix | null |
Encoded symbol, or null when encoding failed. |
error |
QrCodeEncodeErrorLike | null |
Encoding diagnostic, or null when the value encoded successfully. |
dimension |
number |
Rendered viewBox side length in modules, including the quiet zone. |
quietZone |
number |
Quiet zone width in modules. |
element |
SVGSVGElement | null |
Rendered <svg> element, or null while encoding fails. |
Behavior
Normative state x input -> outcome table for qr-code.vue and the pure encoder
exported from @vizejs/ui/qr-code (encodeQrCode, qrCodeToSvgPath,
qrCodeCapacity, isQrCodeModuleDark). Every row is proven by the named test.
The encoder implements ISO/IEC 18004 model 2 symbols without dependencies:
optimally mixed numeric, alphanumeric, UTF-8 byte, and (with the opt-in
qrCodeKanjiEncoder table from qr-code-kanji.ts) Kanji segments, optional ECI
headers, explicit segment arrays, versions 1-40, levels L/M/Q/H with optional boost, Reed-Solomon over
GF(256) with block interleaving, finder/timing/alignment/format/version
patterns, and all eight masks with the standard penalty score. With
segmentation: "single", output is identical to Project Nayuki's reference
generator; the default optimal segmentation is the same symbol whenever it
settles on one segment, and otherwise never needs a larger version.
| ID | State | Input | Outcome | Evidence |
|---|---|---|---|---|
| Q1 | byte text, level L | encodeQrCode("Hello, world!") |
produces the reference version 1, mask 2 module grid | matches the reference byte-mode symbol for Hello, world! at level L |
| Q2 | numeric / alphanumeric | auto mode | selects the compact mode and produces the reference grids | matches reference numeric and alphanumeric symbols |
| Q3 | multi-block, v7+ | long URL at level H | interleaves blocks, draws version information, and matches the reference version 9 grid | matches a multi-block reference symbol with version information |
| Q4 | spec worked example | 01234567 at 1-M |
emits the standard data codewords, Reed-Solomon codewords, and interleaved stream | reproduces the ISO/IEC 18004 worked example codewords for 01234567 at 1-M |
| Q5 | alphanumeric segment | AC-42 |
packs character pairs into 11 bits and a trailing character into 6 bits | encodes alphanumeric pairs from the standard AC-42 example |
| Q6 | Reed-Solomon | field multiply, generator degree | GF(256) arithmetic and generator polynomials match the standard; invalid degrees throw | implements GF(256) arithmetic and Reed-Solomon generators |
| Q7 | format information | every level x mask | emits the 32 masked BCH format strings from table C.1 | computes format information for every level and mask |
| Q8 | version information | versions 7, 21, 40 | emits the standard 18-bit BCH version strings | computes version information for versions 7 through 40 |
| Q9 | alignment patterns | versions 1-40 | centers match the standard table, including the irregular version 32 | places alignment patterns at the standard centers |
| Q10 | capacity | version x level x mode | codeword and character capacities match the standard tables | matches the standard codeword capacity tables |
| Q11 | auto version | data at and over each capacity boundary | picks the smallest fitting version and moves up exactly one byte past capacity | selects the smallest version at the exact capacity boundary |
| Q12 | invalid input | overflow, forced mode, bad options | throws QrCodeEncodeError with VIZE_UI_QR_DATA_TOO_LONG, VIZE_UI_QR_INVALID_MODE, or …INVALID_OPTION |
throws typed diagnostics for data overflow and invalid options |
| Q13 | explicit options | fixed version/mask, forced mode, boost | honors each option; boost raises the level only while the data still fits | honors fixed version, fixed mask, forced mode, and error correction boost |
| Q14 | text encodings | Unicode text, bytes, empty string | Unicode text equals its UTF-8 bytes; empty values encode a version 1 symbol with mode: null |
encodes UTF-8 text and empty values |
| Q15 | auto mask | encode | applies the lowest-penalty mask; output is frozen and deterministic | picks the mask with the lowest penalty and returns frozen output |
| Q16 | penalty rules | synthetic grids | runs, 2x2 blocks, finder-like patterns, and balance follow the standard weights | scores the four standard penalty rules |
| Q17 | SVG path | module rows | merges each horizontal dark run into one rectangle | merges horizontal dark runs into one rectangle per run |
| Q18 | SVG path, quiet zone | quietZone |
offsets every coordinate by the quiet zone | offsets every coordinate by the quiet zone |
| Q19 | SVG path coverage | encoded symbol | rasterized path covers exactly the dark modules with no overlap | covers exactly the dark modules of an encoded symbol |
| Q20 | SVG path options | invalid quiet zone | rejects negative, fractional, or oversized quiet zones | rejects invalid quiet zones |
| Q21 | ready | render | renders <svg role="img"> named by label or text, <title>, viewBox with quiet zone, and data hooks |
renders an accessible SVG symbol with a quiet zone and data hooks |
| Q22 | ready | prop change | forwards encoder props and re-encodes reactively | forwards encoder options and re-encodes when props change |
| Q23 | labelled / decorative | render | byte values use label; decorative symbols drop role, name, and title and set aria-hidden; fills apply |
supports explicit labels, byte values, decorative symbols, and colors |
| Q24 | ready + overlay | render | overlay slot renders inside the SVG with dimension and matrix slot state | renders the overlay slot inside the SVG with module coordinates |
| Q25 | error | unencodable value or invalid quiet zone | renders <span data-state="error" data-error> with the fallback slot, and recovers when props become valid |
renders the fallback slot with a typed diagnostic when encoding fails |
| Q26 | exposed instance | ref access | exposes element, matrix, state, error, quiet zone, and dimension | exposes the encoded matrix, state, and element |
| Q27 | SSR | two isolated requests | byte-identical markup, computed purely from props | renders byte-identical QR code markup across isolated SSR requests |
| Q28 | SSR + hydration | mount over server HTML | keeps server nodes and emits no warnings | hydrates the QR code without replacing server nodes or warning |
| Q29 | optimal segmentation | random text, versions 1/10/27 | segment bit length equals an exhaustive search over every split and legal mode | optimal segmentation matches an exhaustive search for every version range |
| Q30 | mixed text | alphanumeric URL with digits | mixes modes to use fewer bits than single mode, re-optimizes per count-width range, reports mixed |
mixes modes to beat single-mode encoding and re-optimizes per version range |
| Q31 | round trip | random text, Kanji, UTF-8 ECI | the encoded data stream decodes back to the text; summaries match the emitted segments | encodes segments whose data stream decodes back to the original text |
| Q32 | auto version | long mixed text | the chosen version fits its range's segments and the version below does not | chooses the smallest version using the segments of each version range |
| Q33 | Kanji table | JIS X 0208, spec examples | 点/茗 pack to 0x0D9F/0x1AAA; every JIS X 0208 character round-trips; JIS aliases encode; others do not | maps JIS X 0208 characters to Shift_JIS and packs 13-bit Kanji values |
| Q34 | Kanji mode | encoder present / absent, forced mode | Kanji is used only with an encoder; forced Kanji without one or with unmappable text throws; capacity table | uses Kanji mode only with an encoder and validates Kanji input |
| Q35 | ECI segment | designators | 8/16/24-bit designators, validated range, and header bits in the data stream | writes ECI headers with 8, 16, and 24 bit designators |
| Q36 | eci / utf8Eci |
encode | prefixes the header, counts it toward capacity, reports eci, and rejects conflicting options |
utf8Eci and eci prefix the data and count toward capacity |
| Q37 | explicit segments | segment array value | encodes the given segments verbatim with frozen helper output; invalid helper input throws | encodes explicit segment arrays as given |
| Q38 | component options | segmentation, kanji, ECI, segments |
forwards every encoder option reactively and accepts explicit segments with a label | forwards segmentation, Kanji, and ECI options and accepts explicit segments |
Colors are SVG presentation attributes (foreground defaults to
currentColor, background to none), so consumer CSS on
[part="modules"] and [part="background"] always wins. Scanners need a light
background and a 4-module quiet zone; use level H when an overlay covers the
center.