Skip to content
Component installs need the registry setup
VegaStack Design

QR Code

A QR code for a link, drawn as one crisp SVG — dark modules on a light rounded tile in both themes, with the standard quiet zone.

Status
stable
Since
0.25.86
Accessibility pattern
an image named by what scanning it does

Last updated

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for QR Code before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify qr-code

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/qr-code

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

It also adds the sanctioned engine to your package.json: uqr (QR encoder (pure; renders nothing)).

Usage

import { QrCode } from "@/components/ui/qr-code";

<QrCode value={recordUrl} label="Open this meeting on your phone" />;

QrCode hands a link to a phone. It encodes value during render — on the server or the client, with no effect and no canvas — and draws the matrix as a single SVG path, so it stays sharp at any size. The tile is light and the modules dark in both themes, because many scanners cannot read a code drawn light-on-dark; the standard 4-module quiet zone is part of the drawing, so it needs no padding around it.

Examples

Sizes

The default is size-40 (160px). Pass any size-* class; the code scales with its box. Keep a code you expect to be scanned from a laptop screen at 160px or more.

Error correction

errorCorrection trades density for robustness: L survives 7% damage, M (the default) 15%, Q 25% and H 30%. A higher level draws more, smaller modules for the same value — use M for a link on a screen, and Q or H only when the code may be printed and worn.

Empty

An empty value, or one too long for any QR version at the chosen level, never throws: it draws the empty tile (data-state="invalid") at the same size and keeps its name. Show why next to it.

API Reference

PropTypeDefaultDescription
label*string—The accessible name: what scanning the code does ("Open this meeting on your phone"). The encoded value is not read out, so say where it leads.
value*string—The text the code carries — usually a URL. An empty value, or one too long for any QR version at the chosen errorCorrection, draws the empty tile instead of throwing.
errorCorrectionQrCodeErrorCorrection"M"How much of the code can be lost and still scan: L 7%, M 15%, Q 25%, H 30%. A higher level draws more, smaller modules for the same value.
quietZonenumber4The light margin around the code, in modules. The QR standard asks for 4; scanners struggle below 2.

Data attributes and CSS variables on QrCode

AttributeValues
data-error-correctionmirrors a prop or state value
data-slot"qr-code" | "qr-code-modules"
data-state"invalid" | "ready"

QrCode also takes the SVG element's own props (className, ref, id, style, …); the root is the <svg>.

Accessibility

  • The root is role="img", named by label. Say what scanning does — "Open this meeting on your phone" — not "QR code": the encoded value is not read out.
  • A QR code is never the only way in. Show the link beside it, or a CopyButton for it, so someone without a camera — or using a screen reader — can follow it.
  • Nothing in it is focusable or interactive.
ContractStates tested
Behaviourready, invalid
Accessibilitylabeled, browser-accessibility-test
Visualdefault, invalid

Do / Don't

Do
Put the code beside the link it encodes, and label it with what scanning does.
Don't
Recolour the code to match the theme, or make it the only way to open the link.
Do
Keep the quiet zone and give the code at least 160px when it is scanned from a laptop screen.
Don't
Crop the light margin, lay the code over an image, or shrink it to an icon's size.

On this page