Skip to main content
Copy for LLM

QR Code

The <x-wirekit::qr-code> component generates a QR code as inline SVG from any string value. It uses the bacon/bacon-qr-code PHP library for server-side generation — no JavaScript required.

Basic Usage

Basic QR Code

Custom Size

The size prop controls both width and height in pixels:

Different Sizes

Custom Colors

Use color for the foreground modules and background for the quiet zone. Both accept a CSS hex color in any of its four forms, #rgb, #rgba, #rrggbb or #rrggbbaa; an alpha becomes the fill's opacity:

Colored QR Codes
{{-- Blue on light blue --}}
<x-wirekit::qr-code value="..." color="#1e40af" background="#dbeafe" />

{{-- Inverted: white on dark --}}
<x-wirekit::qr-code value="..." color="#ffffff" background="#18181b" />

Error Correction Level

Higher error correction allows the QR code to remain scannable even when partially obscured (e.g. by a logo overlay). The trade-off is a denser pattern with more modules:

Error Correction Levels
L (7%)
M (15%)
Q (25%)
H (30%)

Use H (30% correction) when you plan to overlay a logo on the QR code.

Margin (Quiet Zone)

The margin prop controls the white border around the QR code in module units. The QR standard recommends at least 4 modules, but you can reduce it for tight layouts:

Margin (Quiet Zone)
margin=0
margin=2
margin=4

Complex Examples

WiFi Network

Encode WiFi credentials using the standard WiFi QR format. Scanning this QR connects the device automatically:

WiFi Network QR
GuestNetwork
Security: WPA/WPA2
Password: welcome2024
Scan to connect automatically

vCard Contact

Encode contact information as a vCard — scanning adds the contact to the phone's address book:

vCard Contact QR
Jane Smith
Acme Inc.
+1-555-123-4567
[email protected]
Scan to add contact

Branded with Logo Overlay

Use high error correction (H) so the QR remains scannable with a logo on top:

Branded with Logo Overlay

Keep the logo under ~30% of the QR area so the error correction can recover the obscured modules.

<div class="relative inline-block">
    <x-wirekit::qr-code
        value="https://wirekit.app"
        :size="250"
        errorCorrection="H"
    />
    <img
        src="/logo.svg"
        alt=""
        aria-hidden="true"
        class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-12 h-12 bg-white p-1 rounded"
    />
</div>

Dynamic Values

Use Blade expressions to encode dynamic content:

{{-- Route URL --}}
<x-wirekit::qr-code :value="route('invite', $token)" />

{{-- Email mailto --}}
<x-wirekit::qr-code :value="'mailto:' . $user->email" />

{{-- Coupon code --}}
<x-wirekit::qr-code :value="$couponCode" :size="150" />

SVG Output

The component always renders SVG — never a raster image. This means:

  • Infinitely scalable — looks sharp on any screen density (Retina, 4K)
  • Styleable — the SVG respects the color and background props
  • Printable — vector output at any resolution
  • Lightweight — typically 2–5 KB inline SVG, no external requests
  • Accessible — wrapped in role="img" with aria-label

The SVG is rendered inline in the DOM (not as <img src="...">) so it's part of the page's DOM tree and can be styled with CSS if needed.

Requirements

This component requires the bacon/bacon-qr-code PHP package:

composer require bacon/bacon-qr-code

The package is a suggested dependency of WireKit, not a required one. If the package is not installed, the component renders a styled placeholder instead of a QR code.

Fallback Behavior

When bacon/bacon-qr-code is not installed or the value is empty, the component renders a placeholder <div> with the text "QR code" — styled with WireKit design tokens (muted background, border, rounded corners). This ensures the layout does not break.

Props

Prop Type Default Description
value string '' The text or URL to encode
size int 200 Width and height in pixels
color string '#000000' Foreground (module) color as hex: #rgb, #rgba, #rrggbb or #rrggbbaa
background string '#ffffff' Background color as hex, in the same four forms
errorCorrection string 'L' Error correction level: L (7%), M (15%), Q (25%), H (30%)
margin int 4 Quiet zone width in QR modules
accessibleLabel string|null null Accessible name announced by screen readers. Defaults to "QR code" when omitted — pass a purpose-describing label like "Scan to install WireKit" rather than letting the encoded URL leak as the announcement.
scope string|null null Scoped personalization key

Accessibility

  • Container: role="img" — identifies the element as an image to assistive technology
  • aria-label — carries accessibleLabel when you pass one, otherwise the constant "QR code". The encoded value is never part of the accessible name, so an API key or an opaque token in the code is not announced
  • The QR code is purely visual — screen readers announce the label instead of attempting to parse the SVG paths

Name the code by its purpose rather than its contents: accessibleLabel="Scan to install WireKit". The default "QR code" is accurate and says nothing useful, and the encoded value stays out of the announcement either way — so a screen-reader user learns what the code is for only if you say it.

Keyboard Interaction

This component is purely presentational and does not respond to keyboard input.

Pitfalls

  • Don't QR-encode personally identifiable data. QR codes are public — anyone within camera range can capture them. Encode opaque tokens and resolve server-side.

Design Tokens

The rendered QR code takes its two colors from the color and background props, which default to #000000 on #ffffff — deliberately hex rather than design tokens, because a scanner reads luminance contrast and a themed code that follows dark mode stops scanning. Token usage is therefore concentrated on the placeholder fallback and the surrounding container:

Token Used for
--text-wk-sm Placeholder label font size
--color-wk-text-muted Placeholder label text
--color-wk-bg-muted Placeholder background
--color-wk-border Placeholder border
--border-wk-width Placeholder border width
--radius-wk-md Placeholder border radius

Personalization

Override classes globally via WireKit::personalize():

use Pushery\WireKit\WireKit;

WireKit::personalize('qr-code', [
    // The code's own light quiet zone comes from the `background` prop and the SVG,
    // so the wrapper does not need one — give it a themed surface instead, or a
    // scanner on a dark page reads a white card the theme never asked for.
    'base' => 'inline-block p-[var(--padding-wk-x-md)]'
        .' bg-[var(--color-wk-bg-elevated)]'
        .' rounded-[var(--radius-wk-lg)] shadow-[var(--shadow-wk-sm)]',
]);

Further Reading

Updated in WireKit v2.65.0 (2026-10-05)

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store