ChequeView
A cheque drawn as printed: payee, the amount in figures and in words, date, memo, signature and the MICR line.
Demo
Dana Whitfield
12 Orchard Row
Port Ellis, ME 04101
Number 1042
Date
Pay to the order ofAna Okafor
$1,234.56
One thousand two hundred thirty-four and 56/100dollars
Fernway Credit Union
40 Quay Street, Port Ellis
ForKitchen tiles
Dana WhitfieldSignature
Dana Whitfield
Number 1043
Date
Pay to the order ofHarbour Fitness
$85.00
Eighty-five and 00/100dollars
Fernway Credit Union
ForNovember
Authorised signature
Number 000318
Date
Pay to the order ofKinoshita Builders
¥1,250,000
One million two hundred fifty thousandyen
Sakuragi Shinkin
For
T. MoriSignature
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/cheque_view.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/cheque_view.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/cheque_view.qwe
view ChequeViewDemo() = <div.demo-stack> <ChequeView id="cheque-view-demo" number="1042" dated="2026-10-29" payee="Ana Okafor" amount={1234.56m} memo="Kitchen tiles" drawer={{ name: "Dana Whitfield", lines: ["12 Orchard Row", "Port Ellis, ME 04101"] }} bank={{ name: "Fernway Credit Union", lines: ["40 Quay Street, Port Ellis"] }} routing="011000015" account="40031204" signature="Dana Whitfield"/> <ChequeView id="cheque-view-demo-void" number="1043" dated="2026-11-02" payee="Harbour Fitness" amount={85} memo="November" drawer={{ name: "Dana Whitfield" }} bank={{ name: "Fernway Credit Union" }} routing="011000015" account="40031204" void={true}/> <ChequeView id="cheque-view-demo-yen" number="000318" dated="2026-12-01" payee="Kinoshita Builders" amount={1250000} currency="JPY" bank={{ name: "Sakuragi Shinkin" }} signature="T. Mori"/> </div>Source
ui/cheque_view.qwe
// ChequeView: a cheque drawn as it is printed: who draws it and their address,// the cheque's number and date, "Pay to the order of" the payee, the amount in// figures and in words ("One thousand two hundred thirty-four and 56/100"), the// bank, the memo, the signature, and the MICR line along the bottom (⑆ routing// ⑆ account ⑈ number). For a cheque image in an account's history, a payment's// confirmation, or a cheque to print.//// <ChequeView number="1042" dated="2026-10-29" payee="Ana Okafor" amount={1234.56m} memo="Kitchen tiles"// drawer={{ name: "Dana Whitfield", lines: ["12 Orchard Row", "Port Ellis PE3 9QT"] }}// bank={{ name: "Fernway Credit Union", lines: ["40 Quay Street, Port Ellis"] }}// routing="011000015" account="40031204" signature="Dana Whitfield"/>//// number: the cheque's number, printed at the top right and in the MICR line.// dated: its date, an ISO date. payee: who it is to. amount: a number or decimal;// written in figures in its currency and in English words, with the cents over// 100 (a currency without cents has none). words: other words for the amount, as// written in another language. currency ("USD"): its word at the end of the line// ("dollars", "euros", "pounds", ...; the code for others); locale: how the// figures and the date are written. memo: the "For" line. drawer: { name, lines? };// bank: { name, lines? }. routing, account: the numbers in the MICR line.// signature: the name signed, in a hand; left out, the line is blank. void: a// cheque cancelled, crossed through with VOID. id: the element's id.import ui/theme.qwe use ui_clslet cheque_view_css = css`.ui-cheque { --ink: var(--ui-fg); position: relative; display: grid; grid-template-columns: 1fr auto; gap: 14px 24px; min-width: 0; max-width: 680px; padding: 20px 24px 14px; overflow: hidden; border: 1px solid color-mix(in srgb, var(--ui-accent) 35%, var(--ui-border)); border-radius: 6px; background: repeating-linear-gradient(-45deg, transparent 0 7px, color-mix(in srgb, var(--ui-accent) 5%, transparent) 7px 8px), linear-gradient(180deg, color-mix(in srgb, var(--ui-accent-soft) 55%, var(--ui-surface)), var(--ui-surface)); color: var(--ink); font: 13px/1.35 var(--ui-font); }.ui-cheque-drawer p { margin: 0; }.ui-cheque-drawer-name { font-weight: 650; }.ui-cheque-small { color: var(--ui-muted); font-size: 11px; }.ui-cheque-corner { display: grid; justify-items: end; gap: 10px; }.ui-cheque-no { margin: 0; font: 600 14px var(--ui-mono); letter-spacing: .05em; }.ui-cheque-datebox { display: flex; align-items: baseline; gap: 8px; }.ui-cheque-cap { color: var(--ui-muted); font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; white-space: nowrap; }.ui-cheque-line { flex: 1; min-width: 0; padding: 0 4px 1px; border-bottom: 1px solid var(--ink); font: 500 15px var(--ui-font); overflow-wrap: anywhere; }.ui-cheque-datebox .ui-cheque-line { min-width: 120px; text-align: center; }.ui-cheque-pay { grid-column: 1 / -1; display: flex; align-items: flex-end; gap: 14px; }.ui-cheque-payto { display: flex; flex: 1; align-items: baseline; gap: 8px; min-width: 0; }.ui-cheque-payto .ui-cheque-cap { width: 64px; white-space: normal; line-height: 1.2; }.ui-cheque-figures { flex: none; display: flex; align-items: center; gap: 6px; padding: 4px 10px; border: 1.5px solid var(--ink); border-radius: 3px; background: var(--ui-surface); font: 600 16px var(--ui-mono); font-variant-numeric: tabular-nums; }.ui-cheque-wordsrow { grid-column: 1 / -1; display: flex; align-items: baseline; gap: 8px; overflow: hidden; }.ui-cheque-words { flex: 1; min-width: 0; padding: 0 4px 1px; overflow: hidden; border-bottom: 1px solid var(--ink); font-size: 14px; font-style: italic; white-space: nowrap; }.ui-cheque-words::after { content: " ———————————————————————————" / ""; color: var(--ui-muted); font-style: normal; letter-spacing: -.1em; }.ui-cheque-unit { flex: none; font-size: 12px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; }.ui-cheque-bank { align-self: end; }.ui-cheque-bank p { margin: 0; }.ui-cheque-bank-name { font-weight: 650; }.ui-cheque-memo { display: flex; align-items: baseline; gap: 8px; margin-top: 10px; max-width: 300px; }.ui-cheque-sign { align-self: end; display: grid; gap: 2px; width: 230px; max-width: 100%; }.ui-cheque-signature { min-height: 30px; padding: 0 6px; border-bottom: 1px solid var(--ink); font: italic 24px/30px "Snell Roundhand", "Segoe Script", "Brush Script MT", cursive; overflow: hidden; white-space: nowrap; }.ui-cheque-sign .ui-cheque-cap { text-align: center; }.ui-cheque-micr { grid-column: 1 / -1; margin: 4px 0 0; padding-top: 8px; font: 15px/1 "MICR E13B", "Apple Symbols", var(--ui-mono); letter-spacing: .14em; white-space: nowrap; overflow: hidden; }.ui-cheque-void { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }.ui-cheque-void span { padding: 2px 28px; border: 4px solid var(--ui-danger); border-radius: 8px; color: var(--ui-danger); font: 800 56px/1.1 var(--ui-font); letter-spacing: .18em; opacity: .75; transform: rotate(-14deg); }@media (max-width: 560px) { .ui-cheque { grid-template-columns: 1fr; padding: 16px; } .ui-cheque-corner { justify-items: start; } .ui-cheque-pay { flex-wrap: wrap; } }@media print { .ui-cheque { border-color: #000; background: #fff; color: #000; --ink: #000; } }`let cheque_view_ones = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]let cheque_view_tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]let cheque_view_units = { USD: "dollars", CAD: "dollars", AUD: "dollars", NZD: "dollars", SGD: "dollars", HKD: "dollars", EUR: "euros", GBP: "pounds", JPY: "yen", CHF: "francs", INR: "rupees", PHP: "pesos", MXN: "pesos", ZAR: "rand", SEK: "kronor", NOK: "kroner", DKK: "kroner", CNY: "yuan", KRW: "won", BRL: "reais" }// 0 to 999 in words: 342 is "three hundred forty-two".fn cheque_view_hundreds(n: int) -> str { let h = int(n / 100) let rest = n % 100 let tail = rest < 20 ? cheque_view_ones[rest] : cheque_view_tens[int(rest / 10)] + (rest % 10 > 0 ? "-" + cheque_view_ones[rest % 10] : "") join([h > 0 ? cheque_view_ones[h] + " hundred" : "", tail] | filter((w) => w != ""), " ")}// A whole number in words: 1234 is "one thousand two hundred thirty-four".fn cheque_view_words(n: int) -> str { if n == 0 { return "zero" } let scales = [[1000000000000, "trillion"], [1000000000, "billion"], [1000000, "million"], [1000, "thousand"], [1, ""]] let r = reduce(scales, { left: n, out: [] }, (acc, s) => { let q = int(acc.left / s[0]) q == 0 ? acc : { left: acc.left - q * s[0], out: push(acc.out, trim(`${cheque_view_hundreds(q)} ${s[1]}`)) } }) join(r.out, " ")}// An amount as a cheque writes it: "One thousand two hundred thirty-four and 56/100".fn cheque_view_amount_words(amount, currency: str) -> str { let units = money.minor_units(currency) let d = round(abs(dec(amount)), units, "half_up") let whole = int(d) let text = cheque_view_words(whole) let first = upper(slice(text, 0, 1)) + slice(text, 1) if units == 0 { return first } let minor = str(int((d - whole) * pow(10, units))) `${first} and ${repeat("0", units - len(minor))}${minor}/${pow(10, units)}`}// An amount in figures, in its currency.fn cheque_view_money(amount, currency: str, locale: str?) -> str { let m = money.of(dec(amount), currency, "half_up") if is_err(m) { return str(amount) } locale != null ? money.format(m, locale) : money.format(m)}view ChequeView(payee: str, amount, number: str = "", dated: str? = null, currency: str = "USD", locale: str? = null, words: str? = null, memo: str? = null, drawer: map? = null, bank: map? = null, routing: str? = null, account: str? = null, signature: str? = null, void: bool = false, id: str? = null, class: str? = null) { style global cheque_view_css let code = upper(currency) let figures = cheque_view_money(amount, code, locale) let in_words = words ?? cheque_view_amount_words(amount, code) let unit = cheque_view_units[code] ?? code let when = dated != null ? date.format(dated, { locale: locale ?? "en-US", style: "medium" }) : "" let micr_said = ui_cls([routing != null && `routing number ${routing}`, account != null && `account ${account}`, number != "" && `cheque ${number}`]) <figure class={ui_cls(["ui-cheque", class])} id={id} style="margin: 0" aria-label={`${void ? "Void cheque" : "Cheque"}${number != "" ? " " + number : ""} to ${payee} for ${figures}${dated != null ? ", dated " + when : ""}`}> <div.ui-cheque-drawer> {drawer != null && [<p.ui-cheque-drawer-name>{drawer.name}</p>, for l in drawer.lines ?? [] => <p.ui-cheque-small key={l}>{l}</p>]} </div> <div.ui-cheque-corner> {number != "" && <p.ui-cheque-no><span.ui-sr>Number </span>{number}</p>} <div.ui-cheque-datebox><span.ui-cheque-cap>Date</span><span.ui-cheque-line>{dated != null && <time datetime={dated}>{when}</time>}</span></div> </div> <div.ui-cheque-pay> <div.ui-cheque-payto><span.ui-cheque-cap>Pay to the order of</span><span.ui-cheque-line.ui-cheque-payee>{payee}</span></div> <div.ui-cheque-figures>{figures}</div> </div> <div.ui-cheque-wordsrow> <span.ui-cheque-words>{in_words}</span> <span.ui-cheque-unit>{unit}</span> </div> <div.ui-cheque-bank> {bank != null && [<p.ui-cheque-bank-name>{bank.name}</p>, for l in bank.lines ?? [] => <p.ui-cheque-small key={l}>{l}</p>]} <div.ui-cheque-memo><span.ui-cheque-cap>For</span><span.ui-cheque-line.ui-cheque-memo-text>{memo ?? ""}</span></div> </div> <div.ui-cheque-sign> <span.ui-cheque-signature>{signature ?? ""}</span> <span.ui-cheque-cap>{signature != null ? "Signature" : "Authorised signature"}</span> </div> {(routing != null || account != null || number != "") && <p.ui-cheque-micr aria-label={micr_said}> <span aria-hidden="true">{routing != null && `⑆${routing}⑆ `}{account != null && `${account}⑈ `}{number}</span> </p>} {void && <div.ui-cheque-void aria-hidden="true"><span>VOID</span></div>} </figure>}Related
BankStatementA monthly statement that prints: the period, opening and closing balance, totals paid in and out, and each transaction with the balance after.7 views · 6 downloadsBillListUpcoming bills soonest first, overdue and due-soon ones marked, autopay on or off, with the total to pay and a Pay button each.7 views · 5 downloadsAccountCardA bank account at a glance: type, nickname, masked number, current and available balance, what is on hold, and quick actions.8 views · 7 downloadsAccountDetailsThe details to share to get paid: account name and number, IBAN in groups of four (checked), BIC, sort code or routing number, each with a copy button.6 views · 6 downloadsAccountPickerChoose the account to pay from as radio cards with each one's masked number and available balance, those short of the amount marked.7 views · 7 downloadsCardControlsA card's controls beside its masked face: freeze it, set daily spending and cash limits, and allow online, ATM, contactless and abroad use.7 views · 6 downloads
Thread
Thread 0 posts
On ChequeView: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.