DEV Community

Cover image for Mantine QR Code - A Real QR Code Generator for Mantine
Giovambattista Fazioli
Giovambattista Fazioli

Posted on

Mantine QR Code - A Real QR Code Generator for Mantine

Generate fully scannable, beautifully styled QR codes with custom dot shapes, finder patterns, image overlays, and one-click SVG/PNG download — all integrated with the Mantine design system.

Introduction

The Mantine QR Code component has been completely rebuilt from the ground up. What was previously an LED-style indicator has been transformed into a fully functional QR code generator that produces real, scannable codes from any string input. It renders pure SVG for crisp output at any resolution, follows Mantine's Styles API conventions, and ships with a dedicated download hook for exporting to SVG, PNG, JPEG, or WebP.

Mantine QR Code

✨ New Features

Real QR Code Generation

The component now encodes actual QR code data using the qrcode library. Pass any string — a URL, WiFi credentials, vCard, plain text — and get a scannable QR code rendered as optimized SVG.

import { QRCode } from '@gfazioli/mantine-qr-code';

function Demo() {
  return <QRCode value="https://mantine.dev" />;
}
Enter fullscreen mode Exit fullscreen mode

The value prop is the only required prop. Everything else has sensible defaults.

Dot Styles

Control the appearance of data modules with the dotStyle prop. Three built-in styles are available:

<QRCode value="https://mantine.dev" dotStyle="square" />   {/* Default */}
<QRCode value="https://mantine.dev" dotStyle="rounded" />
<QRCode value="https://mantine.dev" dotStyle="dots" />
Enter fullscreen mode Exit fullscreen mode

Each style generates a single combined <path> element for all data modules, keeping the DOM lightweight even for dense QR codes.

Corner Styles

The three finder patterns (the large squares in the corners) can be styled independently with cornerStyle:

<QRCode value="https://mantine.dev" cornerStyle="square" />   {/* Default */}
<QRCode value="https://mantine.dev" cornerStyle="rounded" />
<QRCode value="https://mantine.dev" cornerStyle="dots" />
Enter fullscreen mode Exit fullscreen mode

Mix and match dot and corner styles for unique designs:

<QRCode
  value="https://mantine.dev"
  dotStyle="dots"
  cornerStyle="rounded"
  color="violet"
/>
Enter fullscreen mode Exit fullscreen mode

Image Overlay with Excavation

Add a logo or image at the center of the QR code. The component automatically removes ("excavates") the data modules behind the image to keep the code scannable:

<QRCode
  value="https://mantine.dev"
  size="xl"
  image="https://example.com/logo.png"
  imageSize={0.2}
  imageRadius="md"
  imagePadding={1}
  imageExcavate={true}
  errorCorrectionLevel="H"
/>
Enter fullscreen mode Exit fullscreen mode

Tip: Use errorCorrectionLevel="H" when overlaying images — it provides 30% error correction, ensuring the code remains scannable even with a portion covered.

Error Correction Levels

Four standard error correction levels are supported via the errorCorrectionLevel prop:

Level Recovery Best for
L ~7% Dense data, minimal damage expected
M ~15% General use (default)
Q ~25% Moderate resilience
H ~30% Image overlays, printed codes

useQRCodeDownload Hook

A dedicated hook makes it easy to export the QR code in multiple formats:

import { QRCode, useQRCodeDownload } from '@gfazioli/mantine-qr-code';

function Demo() {
  const { ref, download, getDataUrl } = useQRCodeDownload({
    fileName: 'my-qr-code',
    scale: 4,          // 4x resolution for raster formats
  });

  return (
    <>
      <QRCode ref={ref} value="https://mantine.dev" />
      <button onClick={() => download({ format: 'svg' })}>Download SVG</button>
      <button onClick={() => download({ format: 'png' })}>Download PNG</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Supported formats: svg, png, jpeg, webp. The getDataUrl function returns a data URL — useful for preview thumbnails or embedding.

Theme-Aware Colors

Both foreground and background colors integrate with the Mantine theme:

<QRCode value="https://mantine.dev" color="blue" background="gray.1" />
<QRCode value="https://mantine.dev" color="white" background="dark" />
<QRCode value="https://mantine.dev" color="teal" background="transparent" />
Enter fullscreen mode Exit fullscreen mode

Full Styles API

The component exposes 8 style selectors for granular customization:

Selector Element Description
root <div> Outer container
svg <svg> SVG element
background <rect> Background rectangle
modules <path> Combined data modules path
finderPattern <g> Finder pattern group (×3)
finderOuter <path> Outer ring of finder pattern
finderInner <path> Inner square of finder pattern
image <image> Center image overlay

CSS Variables

Variable Description
--qr-code-size Width and height
--qr-code-radius Container border radius
--qr-code-color Foreground (module) color
--qr-code-background Background color

Size presets: xs (80px), sm (120px), md (160px), lg (200px), xl (256px).

🔧 Improvements

  • SVG Accessibility: The SVG element includes role="img" and an aria-label derived from the encoded value.
  • Optimized Rendering: All data modules are combined into a single <path> element, keeping the DOM minimal regardless of QR code density.
  • Memoized Computation: QR matrix generation and SVG path building are wrapped in useMemo — re-computation only happens when relevant props change.
  • SSR Compatible: No browser-only APIs (window, document) are used during rendering. The download hook uses browser APIs only when explicitly called.

📖 Complete Props Reference

interface QRCodeBaseProps {
  value: string;                              // Required — data to encode
  size?: MantineSize | string | number;       // Default: 'md'
  radius?: MantineRadius | string | number;   // Container border radius
  color?: MantineColor;                       // Default: 'dark'
  background?: MantineColor | 'transparent';  // Default: 'white'
  errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H'; // Default: 'M'
  quietZone?: number;                         // Default: 1
  dotStyle?: 'square' | 'rounded' | 'dots';  // Default: 'square'
  cornerStyle?: 'square' | 'rounded' | 'dots'; // Default: 'square'
  image?: string;                             // Center image URL
  imageSize?: number;                         // 0–1, default: 0.2
  imageRadius?: MantineRadius | string | number;
  imagePadding?: number;                      // Default: 1
  imageExcavate?: boolean;                    // Default: true
}
Enter fullscreen mode Exit fullscreen mode

Getting Started

Install the package:

npm install @gfazioli/mantine-qr-code
Enter fullscreen mode Exit fullscreen mode

Import styles at the root of your application:

import '@gfazioli/mantine-qr-code/styles.css';
Enter fullscreen mode Exit fullscreen mode

Use the component:

import { QRCode } from '@gfazioli/mantine-qr-code';

function App() {
  return (
    <QRCode
      value="https://mantine.dev"
      size="lg"
      dotStyle="rounded"
      cornerStyle="rounded"
      color="blue"
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Use Cases

Use Cases

{/* URL */}
<QRCode value="https://mantine.dev" />

{/* WiFi credentials */}
<QRCode value="WIFI:T:WPA;S:MyNetwork;P:MyPassword;;" />

{/* vCard contact */}
<QRCode value="BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL:+1234567890\nEND:VCARD" />
Enter fullscreen mode Exit fullscreen mode

Links

Top comments (0)