Skip to content

cv-qr-code

Display-only QR code renderer for short strings, URLs, and app-owned setup payloads.

Use cv-qr-code when an interface needs a scannable handoff from screen to device: public links, pairing/setup URLs, recovery flows, or other app-owned payloads. The component keeps the QR data path separate from visual branding so sensitive values can still be passed through the .value property without reflecting back to markup.

Usage

Live Examples

The examples below show the intended presentation range: a default high-contrast QR, a shaped variant for visual hierarchy, a token-colored variant, and a branded variant with the ChromVoid mark in the center.

View source
html
<div class="qr-demo-shell" data-demo="qr-code" data-live-demo-height="680">
  <section class="qr-demo-hero" aria-labelledby="qr-demo-title">
    <div class="qr-demo-copy">
      <span class="qr-demo-kicker">Screen to device handoff</span>
      <h3 id="qr-demo-title">Make the transfer scannable without exposing sensitive payloads</h3>
      <p>
        Use the attribute form for public URLs. For setup secrets and recovery payloads, write
        <code>.value</code> from app state so the encoded data never has to be reflected in markup.
      </p>
      <div class="qr-demo-signal-row" aria-label="QR code reliability guidance">
        <span class="qr-demo-signal">High contrast</span>
        <span class="qr-demo-signal">Quiet zone kept</span>
        <span class="qr-demo-signal">Logo requires H</span>
      </div>
    </div>

    <figure class="qr-demo-feature">
      <span class="qr-demo-feature-label">Public pairing URL</span>
      <cv-qr-code
        class="qr-demo-featured"
        value="https://chromvoid.com/pair?device=vault"
        error-correction="H"
        module-shape="rounded"
        aria-label="ChromVoid pairing URL QR code"
      >
        <img slot="logo" src="/assets/landing/icon-64x64-tight.png" alt="" />
      </cv-qr-code>
      <figcaption>Branded handoff with visible quiet zone and high error correction.</figcaption>
    </figure>
  </section>

  <div class="qr-demo-board" aria-label="QR code rendering variants">
    <figure class="qr-demo-card">
      <cv-qr-code value="https://chromvoid.com" aria-label="ChromVoid website QR code"></cv-qr-code>
      <figcaption>
        <strong>Standard link</strong>
        <span>Default square modules for public, non-secret URLs.</span>
      </figcaption>
    </figure>

    <figure class="qr-demo-card">
      <cv-qr-code
        value="https://chromvoid.com"
        error-correction="H"
        module-shape="dot"
        aria-label="ChromVoid dotted QR code"
      ></cv-qr-code>
      <figcaption>
        <strong>Custom shape</strong>
        <span>Dot modules keep the payload readable while softening the surface.</span>
      </figcaption>
    </figure>

    <figure class="qr-demo-card">
      <cv-qr-code
        class="qr-demo-colored"
        value="https://chromvoid.com"
        error-correction="H"
        module-shape="dot"
        aria-label="ChromVoid colored QR code"
      ></cv-qr-code>
      <figcaption>
        <strong>Token color</strong>
        <span>Use QR-specific custom properties and preserve scanner contrast.</span>
      </figcaption>
    </figure>

    <figure class="qr-demo-card">
      <cv-qr-code
        class="qr-demo-branded"
        value="https://chromvoid.com"
        error-correction="H"
        module-shape="rounded"
        aria-label="ChromVoid branded QR code"
      >
        <img slot="logo" src="/assets/landing/icon-64x64-tight.png" alt="" />
      </cv-qr-code>
      <figcaption>
        <strong>Branded handoff</strong>
        <span>Use high error correction when a centered logo overlays modules.</span>
      </figcaption>
    </figure>
  </div>
</div>

Markup Patterns

html
<!-- Non-secret declarative value -->
<cv-qr-code value="https://chromvoid.com" aria-label="ChromVoid website QR code"></cv-qr-code>

<!-- Higher error correction -->
<cv-qr-code value="https://chromvoid.com" error-correction="H"></cv-qr-code>

<!-- Branded QR with centered logo -->
<cv-qr-code value="https://chromvoid.com" error-correction="H" module-shape="rounded">
  <img slot="logo" src="/assets/landing/icon-64x64-tight.png" alt="" />
</cv-qr-code>

<!-- Token-backed color customization -->
<cv-qr-code
  class="brand-qr"
  value="https://chromvoid.com"
  error-correction="H"
  module-shape="dot"
></cv-qr-code>

<!-- Decorative QR when nearby copy already names the action -->
<cv-qr-code value="https://chromvoid.com" decorative></cv-qr-code>
css
.brand-qr {
  --cv-qr-code-background: var(--cv-color-qr-background);
  --cv-qr-code-foreground: var(--cv-color-primary-darker);
  --cv-qr-code-logo-backdrop-background: var(--cv-qr-code-background);
}
ts
// Preferred for sensitive payloads.
const qrCode = document.querySelector('cv-qr-code')!
qrCode.value = 'otpauth://totp/ChromVoid?secret=...'

Anatomy

<cv-qr-code> (host)
└── <span part="base">
    ├── <svg part="svg" role="img">
    │   ├── <rect part="background">
    │   └── <path part="modules">
    └── <span part="logo" aria-hidden="true">
        ├── <span part="logo-backdrop">
        └── <span part="logo-content">
            └── <slot name="logo">

For module-shape="rounded" and module-shape="dot", modules is rendered as a <g> containing repeated module elements:

<g part="modules">
└── <rect|circle part="module">

When the component has no value or cannot generate a QR code, it renders:

<cv-qr-code> (host)
└── <span part="base" aria-hidden="true">
    └── <span part="placeholder">

Attributes

AttributeTypeDefaultDescription
valueString''Non-secret declarative payload. For sensitive payloads, set the .value property instead of attribute.
error-correctionString"M"Error correction level: "L", "M", "Q", or "H". Unknown runtime values fall back to "M".
quiet-zoneNumber4Number of light modules around the generated QR matrix.
module-shapeString"square"Module renderer: "square", "rounded", or "dot". Unknown runtime values fall back to "square".
logo-sizeString"medium"Center logo overlay size: "small", "medium", or "large". Unknown runtime values fall back to medium styling.
decorativeBooleanfalseHides the rendered SVG from assistive technology.
aria-labelString"QR code"Accessible label for the generated QR image when decorative is not set.

Property-only guidance:

PropertyTypeDescription
valueStringPreferred path for sensitive payloads such as OTP setup URLs. Property updates do not reflect to the host attribute.

Slots

SlotDescription
logoOptional centered brand artwork. Use error-correction="H" when a logo is present and keep it modest.

Accessibility

  • Valid, non-decorative QR output renders as role="img" with aria-label.
  • decorative removes role and aria-label and sets aria-hidden="true" on the SVG.
  • Slotted logo content is rendered inside an aria-hidden="true" overlay and is not exposed as a separate accessible image.
  • Empty or invalid state renders a placeholder wrapper with aria-hidden="true".
  • The encoded payload is never used as the default accessible label.

CSS Parts

PartElementDescription
base<span>Root visual wrapper
svg<svg>Square SVG QR surface
background<rect>Light background and quiet-zone surface
modules<path> / <g>Dark QR modules
module<rect> / <circle>Individual module for rounded and dot renderers
logo<span>Centered logo overlay
logo-backdrop<span>Logo background that preserves contrast over QR modules
logo-content<span>Wrapper around the logo slot
placeholder<span>Empty/invalid placeholder inside base wrapper

CSS Custom Properties

PropertyDefaultDescription
--cv-qr-code-size192pxHost inline and block size
--cv-qr-code-backgroundvar(--cv-color-qr-background)QR background and quiet-zone color
--cv-qr-code-foregroundvar(--cv-color-qr-foreground)QR module color
--cv-qr-code-logo-backdrop-backgroundvar(--cv-qr-code-background)Center logo backdrop color
--cv-qr-code-logo-radiusvar(--cv-radius-md)Border radius for the logo backdrop

Custom colors should point to existing ChromVoid --cv-* tokens and must preserve strong contrast between foreground and background so scanners can read the generated QR code.

Visual States

Host selectorDescription
:host([empty])No payload is available
:host([invalid])Payload could not be encoded within QR capacity
:host([has-logo])The logo slot currently has assigned content
:host([decorative])Rendered QR is hidden from assistive technology

Events

None. The component is display-only.

Scan Reliability

  • Use error-correction="H" whenever a logo overlays the QR matrix.
  • Keep the quiet zone visible and avoid setting quiet-zone below the default for branded QR codes.
  • Keep the background light unless the custom color pair is manually scan-verified across common camera apps.
  • Keep logo content modest; logo-size="large" should be reserved for short payloads with manual scan verification.
  • Custom foreground/background colors must remain high contrast in both light and dark themes.

ChromVoid UIKit documentation