QR Code
Client-side QR code renderer that encodes any string into a crisp inline SVG. Themes automatically via currentColor, with an optional contrast card for guaranteed scanability on dark backgrounds.
<arc-qr-code> Overview
>
QRCode encodes a URL, Wi-Fi credential, 2FA provisioning URI, or any other string entirely on the client and renders it as a single-path inline SVG — no canvas, no image requests, no server round-trip. All dark modules are combined into one `<path>` with crisp edges, so even large codes stay lightweight and scale cleanly at any size.
By default the modules inherit `currentColor` (falling back to `var(--text-primary)`) over a transparent background, so the code themes automatically alongside your text. Consumers can override the two custom properties `--qr-fg` (module color) and `--qr-bg` (background) for full control.
One important caveat: QR scanners are built for dark modules on a light background. On ARC's dark theme, the default rendering produces light modules on a dark surface — an "inverted" code that most modern scanners handle, but less reliably than a standard one. When scanability matters (payment links, ticket check-in, device pairing), set the `contrast` attribute: it renders the code as forced-black modules on a white rounded card, guaranteeing reliable scanning in both themes.
The component re-encodes automatically whenever `value` or `level` changes, and renders nothing when `value` is empty or exceeds QR capacity. The raw value is never exposed to assistive technology — set a meaningful `label` describing what the code does, especially since values are often secrets (2FA URIs, tokens).Guidelines
When to use
- Set the contrast attribute whenever reliable scanning matters (payments, tickets, pairing) — inverted light-on-dark codes are less reliable with some scanners
- Provide a meaningful label describing what the code does ("Scan to open the event page"), not the encoded value itself
- Use level "M" (the default) for most content; step up to "Q" or "H" only when the code may be partially obscured (e.g. a logo overlay or print wear)
- Keep encoded values short — shorter strings produce fewer modules and scan faster from further away
- Render at 160px or larger for codes meant to be scanned from another device across a desk
- Pair with visible text or a copy button showing the same link, for users who cannot scan
When not to use
- Do not rely on the default transparent rendering for scan-critical codes on the dark theme — use contrast mode instead
- Do not put the raw encoded value in the label — it is exposed to assistive technology and may be a secret (2FA URI, token)
- Do not encode very long strings (over ~1KB) — capacity runs out and density makes scanning unreliable at typical sizes
- Do not override --qr-fg/--qr-bg with low-contrast or same-lightness colors — scanners need strong dark-on-light contrast
- Do not shrink the quiet zone below 2 modules when the code sits against busy surrounding content
Features
- Fully client-side encoding via the battle-tested qrcode-generator library (MIT, zero dependencies)
- Single-path SVG output with run-length-combined modules — small DOM, crisp at any size
- Themes automatically: modules use var(`--qr-fg`, currentColor), background var(`--qr-bg`, transparent)
- Contrast mode renders a white rounded card with forced dark modules for guaranteed scanability in both themes
- Four error-correction levels (L / M / Q / H) with automatic version (size) selection
- Configurable quiet zone (border of empty modules) around the code
- `role="img"` with a consumer-provided accessible label — the raw value is never exposed by default
- Re-encodes reactively when value or level changes; renders nothing for empty values
- CSS parts (svg, card) for external style overrides
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<script type="module" src="@arclux/arc-ui"></script>
<!-- Themed code (inherits currentColor) -->
<arc-qr-code value="https://arcui.dev" label="ARC UI website"></arc-qr-code>
<!-- Guaranteed scanability in both themes -->
<arc-qr-code
value="https://arcui.dev"
label="ARC UI website"
contrast
></arc-qr-code>
<!-- High error correction + custom colors -->
<arc-qr-code
value="WIFI:T:WPA;S:Arclight;P:hunter2;;"
label="Wi-Fi network credentials"
level="H"
size="200"
style="--qr-fg: var(--accent-primary); --qr-bg: var(--surface-raised);"
></arc-qr-code> import { QrCode } from '@arclux/arc-ui-react';
export function SharePanel({ url }: { url: string }) {
return (
<QrCode value={url} label="Scan to open this page" size={200} contrast />
);
} <script setup>
import { QrCode } from '@arclux/arc-ui-vue';
</script>
<template>
<QrCode value="https://arcui.dev" label="ARC UI website" :size="200" contrast />
</template> <script>
import { QrCode } from '@arclux/arc-ui-svelte';
</script>
<QrCode value="https://arcui.dev" label="ARC UI website" size={200} contrast /> import { Component } from '@angular/core';
import { QrCode } from '@arclux/arc-ui-angular';
@Component({
imports: [QrCode],
template: `
<arc-qr-code value="https://arcui.dev" label="ARC UI website" size="200" contrast />
`,
})
export class SharePanelComponent {} import { QrCode } from '@arclux/arc-ui-solid';
export function SharePanel() {
return (
<QrCode value="https://arcui.dev" label="ARC UI website" size={200} contrast />
);
} import { QrCode } from '@arclux/arc-ui-preact';
export function SharePanel() {
return (
<QrCode value="https://arcui.dev" label="ARC UI website" size={200} contrast />
);
} API
-
valuestring'' - The content to encode (URL, text, Wi-Fi string, 2FA URI, …). Empty values render nothing. Values exceeding QR capacity for the chosen level also render nothing.
-
sizenumber160 - Rendered width and height of the SVG in pixels. The code is vector-based and stays crisp at any size.
-
level'L' | 'M' | 'Q' | 'H''M' - Error-correction level: L (~7% recovery), M (~15%), Q (~25%), H (~30%). Higher levels tolerate more damage/occlusion but produce denser codes.
-
labelstring'' - Accessible description announced to screen readers (falls back to "QR code"). Describe the purpose, not the encoded value — the value is never exposed by default since it may be a secret.
-
quiet-zonenumber2 - Width of the empty border around the code, measured in modules. Scanners rely on this margin to find the code; keep at least 2 against busy backgrounds.
-
contrastbooleanfalse - Renders the code on a white rounded card with forced dark modules, guaranteeing dark-on-light scanability in both themes. Overrides --qr-fg/--qr-bg. Recommended for scan-critical codes.
See Also
- Image Enhanced image component with shimmer loading skeleton, smooth fade-in transition, error fallback, and aspect ratio presets.
- Copy Button One-click copy-to-clipboard button with confirmation.
- OTP Input A one-time password input that renders a row of individual character boxes with auto-advance, paste support, and configurable length and input type.