bank landing: QR_Taler blue ring on page QR codes

Page-level withdraw and bank-UI QRs were plain white boxes. Align them with
the merchant shop pay popup (taler-merchant-webui QR_Taler / web-util):

  • animated conic ring (#0042B3 / #F1F1F4)
  • off-DOM encode to PNG <img>
  • center qr-logo.svg plate

Reuses shop-pay.css classes already loaded on the bank intro page.
This commit is contained in:
Hernâni Marques 2026-07-10 20:37:30 +02:00
parent 265a7fa3eb
commit ae38882c7c
No known key found for this signature in database

View file

@ -215,28 +215,25 @@
align-self: stretch;
}
.step-body li { margin: 0.4rem 0; }
.qr-box {
background: #fff;
padding: 0.85rem;
border-radius: 14px;
/* Page QRs: QR_Taler blue ring (same classes as shop-pay / merchant webui) */
.qr-taler-wrap {
text-align: center;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
width: 100%;
max-width: 280px;
}
.qr-box img, .qr-box canvas, .qr-box svg {
display: block;
width: 220px;
height: 220px;
margin: 0 auto;
.qr-taler-wrap .goa-pay-taler-qr {
margin-bottom: 0.55rem;
}
.qr-label {
margin-top: 0.6rem;
margin-top: 0.15rem;
font-size: 0.85rem;
color: #3a342c;
color: var(--muted);
font-weight: 700;
max-width: 240px;
max-width: 260px;
margin-left: auto;
margin-right: auto;
}
.more-card .qr-label { color: #c9b8a0; }
.cta {
display: inline-block;
text-align: center;
@ -447,10 +444,9 @@
justify-content: center;
margin: 1rem 0 0.25rem;
}
.more-qr .qr-box {
.more-qr .qr-taler-wrap {
transform: scale(0.92);
transform-origin: center top;
opacity: 0.95;
}
.stats {
background: rgba(18, 28, 28, 0.55);
@ -719,8 +715,11 @@
<h2 id="step2-title"><span class="step-num">2</span> Withdraw from shared account</h2>
<p class="step-tagline">One QR · shared community bank account · no registration</p>
<div class="step-body">
<div class="qr-box">
<div id="qr-withdraw-demo"></div>
<div class="qr-taler-wrap">
<div class="goa-pay-taler-qr" id="qr-withdraw-demo-wrap">
<div class="goa-pay-taler-qr__inner" id="qr-withdraw-demo"></div>
<img class="goa-pay-taler-qr__logo" id="qr-withdraw-demo-logo" alt="" />
</div>
<div class="qr-label">Shared account · scan or open in wallet</div>
</div>
<a class="cta teal" id="open-withdraw-demo" href="#">
@ -769,8 +768,11 @@
<h2>Own bank account?</h2>
<p>Register in the bank UI for your own balance (separate from the shared pool).</p>
<div class="more-qr">
<div class="qr-box">
<div id="qr-webui"></div>
<div class="qr-taler-wrap">
<div class="goa-pay-taler-qr" id="qr-webui-wrap">
<div class="goa-pay-taler-qr__inner" id="qr-webui"></div>
<img class="goa-pay-taler-qr__logo" id="qr-webui-logo" alt="" />
</div>
<div class="qr-label">Bank UI · register / login</div>
</div>
</div>
@ -908,23 +910,48 @@
/* Secondary: own-account path (register first) */
var WITHDRAW_EXCHANGE = "taler://withdraw-exchange/exchange.hacktivism.ch/";
function makeQr(el, text) {
/* QR_Taler: off-DOM encode → PNG img + center logo (same as shop-pay / merchant) */
function logoSrc() {
try {
var b = document.querySelector("base");
if (b && b.href) return new URL("qr-logo.svg", b.href).href;
} catch (e) {}
return "/intro/qr-logo.svg";
}
function setQrLogo(imgEl) {
if (!imgEl) return;
imgEl.src = logoSrc();
imgEl.onerror = function () {
imgEl.style.display = "none";
};
imgEl.style.display = "";
}
function makeQr(el, text, logoEl) {
if (!el) return;
el.innerHTML = "";
var size = 220;
if (!text) {
el.textContent = "…";
el.innerHTML = '<p style="padding:1rem;color:#666;font-size:0.85rem"></p>';
return;
}
if (typeof QRCode === "undefined") {
el.textContent = "QR lib missing";
el.innerHTML = '<p style="padding:1rem;color:#b91c1c;font-size:0.85rem">QR lib missing</p>';
return;
}
// Encode off-DOM so QR is visible (canvas/img not collapsed)
var size = 220;
var level =
QRCode.CorrectLevel && QRCode.CorrectLevel.M != null
? QRCode.CorrectLevel.M
: 1;
var scratch = document.createElement("div");
scratch.setAttribute("aria-hidden", "true");
scratch.style.cssText =
"position:fixed;left:-9999px;top:0;width:" + size + "px;height:" + size + "px;opacity:0";
"position:fixed;left:-9999px;top:0;width:" +
size +
"px;height:" +
size +
"px;overflow:hidden;opacity:0;pointer-events:none";
document.body.appendChild(scratch);
var dataUrl = "";
try {
new QRCode(scratch, {
text: String(text),
@ -932,26 +959,39 @@
height: size,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M
correctLevel: level
});
var canvas = scratch.querySelector("canvas");
var dataUrl = canvas ? canvas.toDataURL("image/png") : "";
if (dataUrl) {
var libImg = scratch.querySelector("img");
if (canvas && canvas.width > 0) {
try {
dataUrl = canvas.toDataURL("image/png");
} catch (e1) {}
}
if (!dataUrl && libImg && libImg.src && libImg.src.indexOf("data:") === 0) {
dataUrl = libImg.src;
}
} catch (err) {
dataUrl = "";
}
if (scratch.parentNode) scratch.parentNode.removeChild(scratch);
if (!dataUrl) {
el.innerHTML = '<p style="padding:1rem;color:#b91c1c;font-size:0.85rem">QR encode failed</p>';
return;
}
var img = document.createElement("img");
img.alt = "QR code";
img.width = size;
img.height = size;
img.src = dataUrl;
img.style.display = "block";
img.style.width = size + "px";
img.style.height = size + "px";
img.style.maxWidth = "100%";
img.style.margin = "0 auto";
img.style.background = "#fff";
el.appendChild(img);
} else {
el.appendChild(scratch.firstChild || document.createTextNode("QR failed"));
}
} catch (e) {
el.textContent = "QR encode failed";
}
if (scratch.parentNode) scratch.parentNode.removeChild(scratch);
setQrLogo(logoEl);
}
function setDemoWithdraw(uri, amount) {
@ -972,7 +1012,11 @@
amtEl.hidden = true;
}
}
makeQr(document.getElementById("qr-withdraw-demo"), uri);
makeQr(
document.getElementById("qr-withdraw-demo"),
uri,
document.getElementById("qr-withdraw-demo-logo")
);
}
function loadDemoWithdraw() {
@ -1047,7 +1091,11 @@
var webuiPainted = false;
wireFold("more-fold", "more-fold-toggle", "more-fold-body", function () {
if (webuiPainted) return;
makeQr(document.getElementById("qr-webui"), WEBUI);
makeQr(
document.getElementById("qr-webui"),
WEBUI,
document.getElementById("qr-webui-logo")
);
webuiPainted = true;
});
})();