Components · Data Display
QR code
A scannable QR code — a join link, a deck URL, a Wi-Fi handoff — rendered through the shared QRCode.
Examples
<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.
QR code is a COMPOSITE (antd, no framework-free element), so its HTML form is a
CDN-React page — React + antd load from a CDN (esm.sh) and mount on open. It
consumes the SAME shared `qrCodeTheme` the React/Vue wrappers use, so it renders
the DS V3 look (ink modules on white, 1px radius-8 frame).
No JSX here (JSX needs a compiler) — we use React.createElement via the `h` alias. -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/tokens.css">
<style>
.aha-qr { display:inline-block; box-sizing:border-box; padding:16px; background:var(--aha-bg-container);
border:1px solid var(--aha-border); border-radius:var(--aha-radius-default); }
</style>
<div id="root"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { ConfigProvider, QRCode } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';
import { qrCodeTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/qr-code-theme.js';
const h = React.createElement;
// Same shared theme the React/Vue wrappers pass to ConfigProvider.
// Matrix: size 120/160/200 · errorLevel L/M/Q/H · status active/expired/loading/scanned · bordered off.
createRoot(document.getElementById('root')).render(
h(ConfigProvider, { theme: qrCodeTheme },
h('div', { className: 'aha-qr' },
h(QRCode, {
value: 'https://ahaslides.com/join',
size: 160,
errorLevel: 'M',
status: 'active',
bordered: false, // the .aha-qr container owns the DS frame
color: '#1A1A1A',
bgColor: '#FFFFFF'
})
)
)
);
</script>
import { ConfigProvider, QRCode } from 'antd'; // antd v6
import { qrCodeTheme } from '@ahaslides-product/design/qr-code-theme';
<ConfigProvider theme={qrCodeTheme}>
<div className="aha-qr">
<QRCode
value="https://ahaslides.com/join"
size={160} // 120 / 160 / 200
errorLevel="M" // L / M / Q / H — raise for a logo overlay
status="active" // active / expired / loading / scanned
bordered={false} // the .aha-qr container owns the DS frame
color="#1A1A1A" // ink modules
bgColor="#FFFFFF" // on white, per DS
/>
</div>
</ConfigProvider>
// One shared qrCodeTheme → the DS V3 look. Frame the code with the .aha-qr container
// (1px --aha-border, radius --aha-radius-default) and show the join link/code alongside.
// Add a centre logo with icon="…" and bump errorLevel to Q/H so it still scans.
<script setup>
import { ConfigProvider, QRCode } from 'ant-design-vue'; // ant-design-vue v4
import { qrCodeTheme } from '@ahaslides-product/design/qr-code-theme';
</script>
<template>
<a-config-provider :theme="qrCodeTheme">
<div class="aha-qr">
<a-qrcode
value="https://ahaslides.com/join"
:size="160"
error-level="M"
status="active"
:bordered="false"
color="#1A1A1A"
bg-color="#FFFFFF"
/>
</div>
</a-config-provider>
</template>
<!-- The SAME qrCodeTheme as React → one DS V3 look across both vendor libraries.
Matrix: size 120/160/200 · error-level L/M/Q/H · status active/expired/loading/scanned. -->
// @ahaslides-product/design/qr-code-theme — declared ONCE, consumed by both tiers.
import { qrCodeTheme } from '@ahaslides-product/design/qr-code-theme';
export const qrCodeTheme = {
token: {
colorPrimary: '#6A1EBB',
borderRadius: 8,
colorText: '#1A1A1A', // QR module ink
colorBorderSecondary: '#E3E3E3', // framing border
fontFamily: 'var(--aha-font-product, "Plus Jakarta Sans", sans-serif)',
},
};
API
| Prop | Type | Default | Notes |
|---|---|---|---|
value | string | — | The URL or text to encode |
size | number | 160 | Rendered pixel size |
errorLevel | L | M | Q | H | M | Error-correction level |
status | active | expired | loading | scanned | active | Render state — expired/scanned overlay a mask, loading shows a spinner |
icon | string | — | Optional centre logo URL |
color | string | #1A1A1A | Module colour (defaults to ink) |
bgColor | string | #FFFFFF | Module background (kept white per DS) |
bordered | boolean | false | antd's own 1px frame — off, so the .aha-qr container owns the DS frame |
Install
# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} # a GitHub token with read:packages
npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css'; // once, at the app root
import '@ahaslides-product/design/qr-code-theme'; // registers <qr-code>
Agent feed for this component (absolute, fetchable anywhere): qr-code.agent.json · qr-code.md · qr-code.llms.txt
When to use
When to use
- QR code — a link people scan from a screen with a phone — a join code, a deck URL, an app download
- a plain link — the destination is clicked, not scanned
Keep the encoded value short so the code stays low-density and scans fast. Always show the human-readable link or join code beside it as a fallback.
Surfaces
audience editor dashboard
Spec
Modules ink #1A1A1A on white #FFFFFF (color / bgColor) · Frame 1px #E3E3E3 border · radius 8 · padding 16 · Size 160 default (set via size) · Error level M default (L / M / Q / H) · Status active default (active / expired / loading / scanned) · Bordered off — the .aha-qr frame supplies the DS border (antd's own bordered defaults on)