BESBanking Experience System
Docs Components Journey Showcase
Draft — not yet human-verified. Every gate passing here is automated. No screen-reader, Arabic native-speaker or usability testing has been carried out yet, and all Arabic UI copy is machine-drafted. What has and hasn't been verified
Financial components

14 — Financial Components: Accounts Family

Banking Experience System (BES) · Financial Components · v2.0.0-draft

Live example

Current account
••4521 · Personal
AED 25,000.00
Available · AED 500.00 reserved
Code
<div class="bes-card bes-acct" style="max-width:400px">
  <div class="row1">
    <div>
      <div class="name">Current account</div>
      <div class="meta"><bdi class="bes-amount">••4521</bdi> · Personal</div>
    </div>
    <button class="bes-iconbtn" aria-label="Hide balance" data-bes-mask="doc-bal" aria-pressed="false">
      <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M2 10s3-5.5 8-5.5S18 10 18 10s-3 5.5-8 5.5S2 10 2 10z" stroke="currentColor" stroke-width="1.5"/><circle cx="10" cy="10" r="2.4" stroke="currentColor" stroke-width="1.5"/></svg>
    </button>
  </div>
  <bdi class="bes-amount bes-amount--lg" id="doc-bal"><span class="cur">AED</span> 25,000.00</bdi>
  <div class="sub">Available · <bdi class="bes-amount">AED 500.00</bdi> reserved</div>
  <div class="actions">
    <button class="bes-btn bes-btn--primary bes-btn--sm">Send</button>
    <button class="bes-btn bes-btn--secondary bes-btn--sm">Details</button>
  </div>
</div>

Components: Account Card · Account Selector · Balance Display · Balance Set · Account Details · IBAN Display · Account Status · Product Header · Spaces/Goal Card.


Account Card

Purpose: one account at a glance — the dashboard workhorse.

Anatomy: account name (user-renamable: "Rent account") · product type label ("Current account" / "حساب جاري") · masked number (••4521) · available balance (Amount lg, maskable) · optional pending indicator ("AED 500.00 pending") · optional status badge · primary quick actions (≤2: Send, Details).

Variants: full (dashboard) · compact (lists, pickers) · multi-currency (currency tabs or stacked balances per currency) · joint (co-holder indicator) · ✦ Islamic (product label carries structure: "Mudarabah savings"; profit-rate metadata instead of interest).

States: default · loading (skeleton — no zero flash) · stale (timestamp) · masked · restricted (financial.blocked treatment + "Why?" path) · dormant (reactivation path) · closed (read-only history access).

Usage: available balance is the headline number always (doc 07 §3); current balance relegated to Details. One tap → account home. Cards never show promotional content inside the account object.

A11y: single named control: "Current account ending 4521, AED 25,000.00 available"; quick actions as discrete stops.

RTL: name/labels mirror; number and balance LTR runs; actions at inline-end.


Account Selector

Purpose: choose source/destination account in flows.

Anatomy: Select/Combobox specialization — trigger shows selected account (name + ••number + available balance); options show the same triple; groups: "Your accounts / Joint / Business".

States: default · open · insufficient (option visible but flagged: "AED 120.00 available — not enough for this transfer"; selectable only where partial funding is a real flow, otherwise disabled with reason) · single-account (renders as static confirmation line, not a dropdown).

Financial: in transfer flows, selecting a source re-validates amount + limits instantly; balance shown is available; hidden accounts (user preference) still listed under "More accounts".

A11y: option announced with full triple; insufficient state part of the announcement.


Balance Display

Purpose: a single balance figure with its label and freshness.

Anatomy: label ("Available balance") · Amount · freshness/timestamp when not real-time · optional info affordance explaining the balance type.

Rule: never a bare number — the type of balance is always labeled, because "balance" is ambiguous by definition (doc 07 §3).


Balance Set

Purpose: the full picture — available / current / pending / reserved in one structure.

Anatomy: primary row (available, amount.lg) · secondary rows (current, pending in/out, reserved) · "Why is my available balance different?" explainer link when current ≠ available · holds drill-down (list of reservations with merchant, amount, release date).

Example:

Available balance         AED 23,750.00
Current balance           AED 25,000.00
Pending out               −AED 750.00   (2 transactions)
Reserved (card holds)     −AED 500.00   → View holds

A11y: rendered as a definition list; explainer reachable by keyboard.


Account Details

Purpose: the reference sheet — everything needed to receive money or verify the account.

Anatomy: rows for: holder name (legal, as registered) · IBAN Display · account number · branch/bank identifiers (SWIFT/BIC) · currency · product name & terms link · opened date. Each row: label + value + copy button. "Share details" action exports a clean payload (text/PDF) excluding anything not needed for receiving money.

States: default · restricted-view (joint/delegated users see per-permission subsets).

Security: details screens require an authenticated session but not step-up; screenshots allowed (users legitimately share IBANs) — but the share action is the promoted path.


IBAN Display

Purpose: render the 23-character UAE IBAN (and foreign IBANs) reliably.

Anatomy: grouped display AE07 0331 2345 6789 0123 456 · copy button (copies unspaced canonical form; toast confirms "IBAN copied") · always dir="ltr" in an isolated run.

States: default · verifying (payee-side lookups) · invalid (entry-side pairing with the IBAN input, doc 09).

A11y: announced in groups of four, not as one 23-character blur; copy announces success.


Account Status

Purpose: account-level states surfaced honestly.

Vocabulary: active · restricted (with reason class: verification-needed / compliance-hold — tipping-off-safe copy) · dormant (with reactivation steps) · frozen (with support path) · pending-closure · closed.

Anatomy: Status Badge + explanation block + the recovery path (every non-active status names its exit).

Rule: a restricted account's balance remains visible — restriction of action never becomes concealment of the user's own money.


Product Header

Purpose: top-of-screen identity for any financial product page (account, card, loan, deposit).

Anatomy: product name · identifying suffix (••4521) · status badge · headline figure (available balance / outstanding amount / card limit) · tab bar into sections (Transactions / Details / Statements).

RTL: headline figure LTR run; tabs mirror.


Spaces / Goal Card

Purpose: sub-account earmarking (savings goals, VAT set-aside, rent).

Anatomy: goal name + icon/emoji slot · saved amount / target ("AED 6,500 of AED 20,000") · Progress bar · optional auto-rule summary ("Saves AED 500.00 every payday") · quick add/withdraw.

States: on-track · paused · reached (celebration allowed — savings context is the sanctioned celebratory surface, doc 05 §2) · behind (neutral framing: "AED 500 to stay on track" — never shame).

Financial: money in spaces is part of balance.current but excluded from spendable balance.available presentation — the set explains this ("AED 6,500.00 set aside in Spaces").


All components in this family — live

Every component from this specification, rendered by the coded library. Expand "Code" to copy the markup.

Balance set — the full truth

Available balanceAED 23,750.00
Current balanceAED 25,000.00
Pending out−AED 750.00 (2)
Card holds−AED 500.00
Why is my available balance different?
Code
<div class="bes-card" style="max-width:420px">
  <div class="bes-rows">
    <div class="bes-row"><span class="k" style="color:var(--bes-text-primary);font-weight:600">Available balance</span><span class="v"><bdi class="bes-amount bes-amount--md">AED 23,750.00</bdi></span></div>
    <div class="bes-row"><span class="k">Current balance</span><span class="v"><bdi class="bes-amount">AED 25,000.00</bdi></span></div>
    <div class="bes-row"><span class="k">Pending out</span><span class="v"><bdi class="bes-amount">−AED 750.00</bdi> <span style="color:var(--bes-text-secondary);font-weight:400">(2)</span></span></div>
    <div class="bes-row"><span class="k">Card holds</span><span class="v" style="color:var(--bes-financial-reserved)"><bdi class="bes-amount">−AED 500.00</bdi></span></div>
  </div>
  <a href="#" style="font-size:13.5px;font-weight:500">Why is my available balance different?</a>
</div>

Account selector

Options always show name, masked number and available balance.
Code
<div class="bes-field" style="max-width:380px;margin-bottom:0">
  <label class="bes-label" for="da-src">From account</label>
  <div class="bes-select"><select id="da-src">
    <option>Current account ••4521 — AED 23,750.00 available</option>
    <option>Savings ••8102 — AED 46,200.00 available</option>
    <option disabled>Joint account ••3377 — AED 120.00 (not enough for this transfer)</option>
  </select></div>
  <div class="bes-help">Options always show name, masked number and available balance.</div>
</div>

IBAN display with copy

AE07 0331 2345 6789 0123 456 Displays grouped; copies unspaced; always an LTR run — flip a doc-demo direction and it holds.
Code
<div class="demo-row">
  <bdi class="bes-amount" style="font-size:15px;font-weight:600;letter-spacing:.04em">AE07 0331 2345 6789 0123 456</bdi>
  <button class="bes-iconbtn" aria-label="Copy IBAN" data-bes-copy="AE070331234567890123456" data-bes-copied="IBAN copied">
    <svg width="18" height="18" viewBox="0 0 18 18" fill="none"><rect x="6" y="6" width="9" height="9" rx="1.5" stroke="currentColor" stroke-width="1.5"/><path d="M12 6V4.5A1.5 1.5 0 0 0 10.5 3H4.5A1.5 1.5 0 0 0 3 4.5v6A1.5 1.5 0 0 0 4.5 12H6" stroke="currentColor" stroke-width="1.5"/></svg>
  </button>
  <span style="font-size:13px;color:var(--bes-text-secondary)">Displays grouped; copies unspaced; always an LTR run — flip a doc-demo direction and it holds.</span>
</div>

Spaces / goal card

🏠 Rent — SeptemberOn track
AED 6,500.00 of AED 10,000.00 · saves AED 500.00 every payday
Code
<div class="bes-card bes-goal" style="max-width:380px">
  <div class="head"><span class="name">🏠 Rent — September</span><span class="bes-badge bes-badge--success">On track</span></div>
  <div class="bes-progress"><div class="fill" style="inline-size:65%"></div></div>
  <div class="figs"><b><bdi class="bes-amount">AED 6,500.00</bdi></b> of <bdi class="bes-amount">AED 10,000.00</bdi> · saves <bdi class="bes-amount">AED 500.00</bdi> every payday</div>
  <div class="demo-row" style="margin-top:12px">
    <button class="bes-btn bes-btn--secondary bes-btn--sm">Add money</button>
    <button class="bes-btn bes-btn--ghost bes-btn--sm">Withdraw</button>
  </div>
</div>