Playground
Draws a QR code as a crisp SVG: every module is a pixel. It encodes with uqr (MIT), vendored unmodified from npm; vendor.json records the release it is verified against.
The code stays dark on white whatever the theme, since some scanners can't read inverted codes. Size it with CSS (inline-size), or set --sb-qr-color, --sb-qr-background and --sb-qr-accent.
Examples
Live from an input
<div data-signals="{_qr: 'https://starbase.example'}" style="display: grid; gap: 16px; justify-items: start">
<sb-input label="Text or URL" data-bind:_qr__prop.value style="inline-size: 20rem"></sb-input>
<sb-qr-code accent data-attr:value="$_qr" data-preserve-attr="value"></sb-qr-code>
</div>
Error correction
Higher levels survive more damage, like a logo over the middle, and need more modules.
<div style="display: flex; gap: 16px; flex-wrap: wrap">
<sb-qr-code value="Ad astra" ecc="L" style="inline-size: 6rem"></sb-qr-code>
<sb-qr-code value="Ad astra" ecc="H" style="inline-size: 6rem"></sb-qr-code>
</div>
Colours
<sb-qr-code value="https://github.com/zweiundeins/starbase" accent
style="inline-size: 8rem; --sb-qr-color: #2E2780; --sb-qr-accent: #E5484D"></sb-qr-code>
From the server
Server-rendered values work as they are: <sb-qr-code value="https://example.com/invite/X7Q2">. When a stream re-renders the attribute, the code follows.
Accessibility
The SVG is an img named "QR code: " plus the value (or label). Put the link or text next to the code as well, for people who can't scan it.
Installation
Add Datastar with Rocket and the Starbase autoloader once per page, then use the tag. The autoloader imports each component the first time its tag appears, including tags added later by a Datastar morph.
<!-- Once per page: Datastar with Rocket, and the Starbase autoloader.
It loads every <sb-…> component the first time its tag appears. -->
<script type="importmap">
{ "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/autoloader.js"></script>
<!-- Optional, no flash of undefined elements: class="sb-cloak" on <html>, and -->
<style>.sb-cloak :not(:defined) { visibility: hidden }</style>
<sb-qr-code value="https://data-star.dev" accent style="inline-size: 7rem"></sb-qr-code>
<!-- In production, pin today's catalog instead of the latest: the browser then
refuses any file that changed. Add "integrity" to the import map above: the
hashes from https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/importmap.json and Datastar's, below. -->
<!--
<script type="importmap">
{ "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" },
"integrity": { "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js": "sha384-vUxZojLrF1Ar3de5h7VINqhJXBgjyZS4U49pHvGa87kum6j5Xn6JRziuARNw5ELG", "…": "…from importmap.json" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/autoloader.js" integrity="sha384-IvSCUjEWPS+wwXunU+48x96KmyWDx/Y4LeCwCL8cWFqJ/zHmTsTOsSMrzTOcpW3D"></script>
-->
<!-- Or load just this component, pinned to this version: -->
<!-- <script type="module" src="https://starbase.zweiundeins.gmbh/c/qr-code@85832e2786cf/qr-code.js" integrity="sha384-Qbd/xqiS6itxRf3rqlDN7JdQ7lKNzKA5VzFsbYRzm1AOBGLL7/Aazne8G5HGmxcX"></script> -->Size
Each file compressed on its own, the way it is served (gzip -9, brotli -11). Datastar and Rocket are shared by every component and not counted.
| File | Original | gzip | brotli |
|---|---|---|---|
qr-code.js | 3.2 kB | 1.5 kB | 1.3 kB |
vendor/uqr.mjs | 27.5 kB | 7.8 kB | 6.8 kB |
| Total | 30.7 kB | 9.4 kB | 8.1 kB |
API reference
Props
| Attribute | Type | Default | Description |
|---|---|---|---|
value | string | "" | Text or URL to encode. |
ecc | "L" | "M" | "Q" | "H" | "M" | Error correction: L 7%, M 15%, Q 25%, H 30% of the code can be damaged or covered. |
border | number | 2 | Quiet zone around the code, in modules (the standard asks for 4; 2 scans fine on a plain background). |
accent | boolean | false | Colour the three corner squares with --sb-qr-accent (default: the brand colour). |
label | string | "" | Accessible name (default: "QR code: " and the value). |