QR Code
A themeable QR code that derives its colors from the active theme, drops an icon in the middle, and can fall back to guaranteed-scannable black-on-white.
Live demo
QR Code encodes any string into a scannable symbol with a self-contained encoder that runs at build and in the browser alike, so a themed code costs no runtime and no network. It follows ISO/IEC 18004: automatic mode selection (numeric, alphanumeric, or byte over UTF-8), the full error-correction tables for versions 1-40, Reed-Solomon parity, and the eight data masks scored for the cleanest read.
Because the modules ink themselves from the theme (--fg-0 on --bg-0 by default, overridable through the --qr-module / --qr-bg custom properties), a QR that matches the surrounding UI is the default, not a manual export. Drop an icon in the center with icon (any xtyle icon name) or a bitmap with logo, sized by icon-scale to the conventional logo fraction; the component bumps error correction to level H so the mark never costs a byte the scanner needs. By default it knocks a clean hole in the modules and pads the mark against the background; set icon-overlay to instead lay the mark straight over the code the way a printed logo does, letting error correction recover the covered modules, and icon-outline for a background-colored halo so the mark stays distinct against the pattern. module-shape renders squares, dots, or rounded cells; frame wraps the code and prints the payload beneath it so a human can read the link a camera would follow. The load-bearing rule is scannability: mode="theme" inks from the theme and flags a low-contrast pairing, mode="bitonal" forces the guaranteed black-on-white a reader never misses, and mode="auto" measures the live theme and silently falls back to bitonal only when the theme's own colors drop below the scannable floor. The floor is xtyle's own contrast infrastructure pointed at a new surface, so a themed code that would fail to scan is caught, not shipped.
When to use
How this component composes with the rest of the set.
Props
16 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
States
low-contrast
Set on the figure when the theme colors fall below the scannability floor (in theme mode, or auto before it falls back), so a failing pairing is visible to a linter or a designer.
Anatomy
The named parts that make up the component, with their selectors.
code
The square that holds the symbol; sized by size and rounded off the radius scale.
background
The full-bleed background rect behind the modules; inks from --qr-bg (defaulting to --bg-0).
modules
The single path drawing every dark module; inks from --qr-module (defaulting to --fg-0).
logo
The centered icon or bitmap; knocked out of the grid on a background pad, or (overlay) laid over it with an optional halo.
caption
The payload printed beneath the symbol when frame is set, in the mono type; a real link when the payload is one, plain text otherwise.
toggle
The optional button on the frame that swaps between the themed and bitonal renderings.
frame
The optional surrounding surface that groups the code, its caption, and the toggle.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--bg-0
--bg-1
--fg-0
--fg-1
--font-mono
--radius-lg
--radius-md
--ring
--space-2
--space-3
--text-sm
Accessibility
Code
A themed link
The default: encode a URL and let the modules ink themselves from the active theme.
<xtyle-qr data="https://xtyle.dev"></xtyle-qr>
<script lang="ts">
import { QrCode } from "@xtyle/svelte";
</script>
<QrCode data="https://xtyle.dev" />
---
import QrCode from "@xtyle/astro/Qr.astro";
---
<QrCode data="https://xtyle.dev" />
Centered icon, framed
Drop an xtyle icon in the middle (error correction bumps to H) and frame the code so the link prints beneath it.
<xtyle-qr
data="https://xtyle.dev"
icon="palette"
frame
size="240"
></xtyle-qr>
<script lang="ts">
import { QrCode } from "@xtyle/svelte";
</script>
<QrCode data="https://xtyle.dev" icon="palette" frame size={240} />
---
import QrCode from "@xtyle/astro/Qr.astro";
---
<QrCode data="https://xtyle.dev" icon="palette" frame size={240} />
Overlay logo with an outline
icon-overlay lays the mark straight over the code the way a printed logo does; icon-outline gives it a halo so it stays distinct while error correction recovers the covered modules.
<!-- Lay the mark over the code (error correction recovers the covered modules) -->
<xtyle-qr
data="https://xtyle.dev"
icon="palette"
icon-overlay
icon-outline
icon-scale="0.26"
></xtyle-qr>
<script lang="ts">
import { QrCode } from "@xtyle/svelte";
</script>
<QrCode data="https://xtyle.dev" icon="palette" iconOverlay iconOutline iconScale={0.26} />
---
import QrCode from "@xtyle/astro/Qr.astro";
---
<QrCode data="https://xtyle.dev" icon="palette" iconOverlay iconOutline iconScale={0.26} />
Framed with a live link and swap
frame renders the payload as a real followable link beneath the code, and mode-toggle adds a button that swaps between the themed and bitonal renderings on the spot.
<!-- The caption is a real link; the button swaps themed <-> bitonal live -->
<xtyle-qr data="https://xtyle.dev" frame mode-toggle></xtyle-qr>
<script lang="ts">
import { QrCode } from "@xtyle/svelte";
</script>
<QrCode data="https://xtyle.dev" frame modeToggle />
---
import QrCode from "@xtyle/astro/Qr.astro";
---
<QrCode data="https://xtyle.dev" frame modeToggle />
Bitonal fallback
Force guaranteed-scannable black-on-white regardless of theme, for print or an uncertain background.
<!-- Guaranteed-scannable black-on-white, whatever the theme -->
<xtyle-qr data="https://xtyle.dev" mode="bitonal"></xtyle-qr>
<script lang="ts">
import { QrCode } from "@xtyle/svelte";
</script>
<QrCode data="https://xtyle.dev" mode="bitonal" />
---
import QrCode from "@xtyle/astro/Qr.astro";
---
<QrCode data="https://xtyle.dev" mode="bitonal" />
Auto scannability
mode="auto" keeps the theme colors while they clear the scannability floor and silently drops to bitonal when they don't.
<!-- Theme colors when they clear the scannability floor, bitonal when they don't -->
<xtyle-qr data="https://xtyle.dev" mode="auto" module-shape="dot"></xtyle-qr>