QR Code
spell-ui/qr-codeFreeComponent
QR code generator with rounded finder patterns and dot-style data modules.
Live preview
live · rendered by the registry
Rendered by spell-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://spell.sh/r/qr-code.jsonSource
1"use client";23import * as React from "react";4import QRCodeLib from "qrcode";5import { cn } from "@/lib/utils";67interface QRCodeProps extends React.SVGProps<SVGSVGElement> {8 value: string;9 size?: number;10 fgColor?: string;11 bgColor?: string;12 errorCorrectionLevel?: "L" | "M" | "Q" | "H";13 className?: string;14}1516function isInFinderPattern(row: number, col: number, size: number): boolean {17 return (18 (row < 7 && col < 7) ||19 (row < 7 && col >= size - 7) ||20 (row >= size - 7 && col < 7)21 );22}2324export function QRCode({25 value,26 size = 268,27 fgColor = "var(--foreground)",28 bgColor = "var(--background)",29 errorCorrectionLevel = "M",30 className,31 ...props32}: QRCodeProps) {33 const qrData = React.useMemo(() => {34 try {35 return QRCodeLib.create(value, { errorCorrectionLevel });36 } catch {37 return null;38 }39 }, [value, errorCorrectionLevel]);4041 if (!qrData) {42 return null;43 }4445 const moduleCount = qrData.modules.size;46 const moduleSize = size / moduleCount;47 const totalSize = size;48 const circleRadius = moduleSize * (1 / 3);4950 const finderPositions: [number, number][] = [51 [0, 0],52 [0, moduleCount - 7],53 [moduleCount - 7, 0],54 ];5556 const finderSize = 7 * moduleSize;57 const innerPadding = moduleSize;58 const innerWhiteSize = 5 * moduleSize;59 const innerBlackSize = 3 * moduleSize;6061 const circles: { cx: number; cy: number }[] = [];6263 for (let row = 0; row < moduleCount; row++) {64 for (let col = 0; col < moduleCount; col++) {65 if (qrData.modules.get(row, col) && !isInFinderPattern(row, col, moduleCount)) {66 circles.push({67 cx: (col + 0.5) * moduleSize,68 cy: (row + 0.5) * moduleSize,69 });70 }71 }72 }7374 return (75 <svg76 width={totalSize}77 height={totalSize}78 viewBox={`0 0 ${totalSize} ${totalSize}`}79 xmlns="http://www.w3.org/2000/svg"80 aria-label={`QR code for ${value}`}81 className={cn("block", className)}82 {...props}83 >84 <rect width={totalSize} height={totalSize} fill={bgColor} rx="12" ry="12" />85 {finderPositions.map(([r, c]) => {86 const x = c * moduleSize;87 const y = r * moduleSize;88 return (89 <g key={`${r}-${c}`}>90 <rect91 x={x}92 y={y}93 width={finderSize}94 height={finderSize}95 fill={fgColor}96 rx="12"97 ry="12"98 />99 <rect100// … truncated
What it pulls in
npm packages
Files it writes
More from spell-ui
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Checkboxanimated-checkbox | spell-ui | Components | Free | 1 dep | |
| Animated Gradientanimated-gradient | spell-ui | Components | Free | no deps | |
| Badgebadge | spell-ui | Components | Free | 2 deps | |
| Bars Spinnerbars-spinner | spell-ui | Components | Free | no deps | |
| Blur Revealblur-reveal | spell-ui | Components | Free | 1 dep | |
| Chartchart | spell-ui | Components | Free | no deps | |
| Color Selectorcolor-selector | spell-ui | Components | Free | no deps | |
| Copy Buttoncopy-button | spell-ui | Components | Free | 1 dep |
