Bank UI Kit
The Flutter front-end for digital banking.
Every surface a retail, Islamic, or business bank ships: onboarding to servicing: as composable, bank-grade Flutter widgets. One codebase, four built-in themes, your backend.
140+ components · 22 banking domains · 4 built-in themes · built toward WCAG 2.1 AA · RTL + Arabic-Indic numerals
| Heritage | Studio | Voltage | Bloom |
![]() |
![]() |
![]() |
![]() |
The same widgets, four built-in themes. Rebrand in minutes, not quarters.
Contents
- Why Bank UI Kit
- Install
- Quick start
- Design presets
- Custom themes
- Journeys, not just widgets
- Component catalogue
- Full API reference
- Cross-cutting features
- Architecture & principles
- Running the example
- Contributing
- License
Why Bank UI Kit
Coverage that reads like a banking platform. Accounts, payments, cards, onboarding and KYC, PFM and insights, lending, rewards, Islamic banking, business-banking approvals, disputes, secure messaging, statements: 140+ components across 22 domains, benchmarked against 21 of the world's leading banking apps so every surface they ship, you can too.
Compliance-ready patterns. PSD2-style dynamic-linking approval, open-banking consent management, deposit-protection notices, IBAN and PAN checksum validation, semantics on every control, 44 px touch targets, and first-class RTL with Arabic-Indic numeral rendering. The kit implements the UX pattern; your bank provides the regulated controls behind it. The division of responsibility is written down in doc/enterprise/compliance-matrix.md, and the accessibility position (verified vs on the roadmap) in doc/enterprise/accessibility-conformance.md.
Four built-in themes, one theming engine. Every widget reads its
colour, shape, depth, and numeral typography from BankThemeData
tokens. Ship the included presets, or derive a complete brand theme
from a single primary colour.
Backend-agnostic by design. Pure props and callbacks; headless flow
controllers (ChangeNotifier state machines) that never touch the
network. Your core banking APIs stay yours. One caveat, stated plainly:
widgets that accept image URLs resolve them with Flutter's standard
network image provider; injectable image resolution is on the roadmap
so fully air-gapped builds need no source changes.
How it compares
| Bank UI Kit | Typical screen-template kits | |
|---|---|---|
| Integration model | Compose into any existing app | Copy-paste whole screens |
| Theming | 4 presets + fully custom themes, runtime-switchable | Fork the package |
| RTL support | First-class, every widget | Mirror-on-demand or none |
| Accessibility | Built toward WCAG 2.1 AA: 44×44 targets, semantics, documented conformance | Not specified |
| State management | Agnostic (pure props + callbacks) | Tied to the template's choice |
| Money | Lossless Decimal-backed Money type |
double |
| Tests | Unit + widget tests across presets | None |
One token change rebrands every surface
Tokens set color, shape, depth, and numeral typography once. Presets are just token sets: swap one and every component follows, light and dark, LTR and RTL. Your rebrand is a constructor argument, not a quarter.
Install
dependencies:
bank_ui_kit:
git:
url: https://github.com/sayed3li97/bank-ui-kit.git
Import only the modules you use:
import 'package:bank_ui_kit/core.dart'; // accounts, transactions, transfers, cards, auth, states, insights…
import 'package:bank_ui_kit/saving.dart'; // pots, round-ups, income sorter
import 'package:bank_ui_kit/social.dart'; // joint accounts, shared goals, peer payments
import 'package:bank_ui_kit/investing.dart'; // wallets, holdings, buy/sell, charts
import 'package:bank_ui_kit/credit.dart'; // installments, credit gauges, subscriptions, perks
Quick start
Wrap your app in a BankUiScope and apply a preset to your ThemeData:
import 'package:bank_ui_kit/core.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return BankUiScope(
initialData: const BankUiScopeData(preset: BankPreset.studio),
child: MaterialApp(
theme: BankPreset.studio.apply(ThemeData.light(useMaterial3: true)),
darkTheme: BankPreset.studio.apply(ThemeData.dark(useMaterial3: true)),
home: const Dashboard(),
),
);
}
}
Then compose with the widgets:
BankBalanceText(money: account.balance, size: BankBalanceSize.hero),
BankVirtualCardWidget(account: account, cardholderName: 'ALEX MORGAN'),
BankTransactionListTile(transaction: tx, onTap: () { /* open detail */ }),
Design presets
Four first-class presets ship in the box. Each defines a complete BankThemeData
(colours, shape radii, elevation/glow, brand font, numeral typography) in light and dark.
| Preset | Personality | Signature |
|---|---|---|
| Studio | Restrained, editorial | Petrol-green, soft-shadow depth, Space Grotesk |
| Voltage | Electric, dark-native | Violet→cyan gradient, pill shapes, glow depth |
| Bloom | Warm, consumer-friendly | Coral primary, fully-rounded, Nunito |
| Heritage | Institutional, Islamic-banking ready | Deep forest green + muted gold, pairs with BankShariahBadge and profit-rate labels |
Switch presets at runtime by changing the ThemeData you pass to MaterialApp -
every widget re-themes itself because it reads tokens from BankThemeData.of(context).
| Accounts · Studio | Accounts · Voltage | Accounts · Bloom |
![]() |
![]() |
![]() |
Heritage: the Islamic-banking preset
A complete demo app (HeritageDashboard in the example) built on the Heritage
preset: SAR balances, profit-rate labels via islamicFinanceMode,
BankShariahBadge on eligible products, and gold-accent virtual cards.
| Heritage · light | Heritage · dark | Home · Heritage |
![]() |
![]() |
![]() |
Every component is also captured under all four presets: see
doc/screenshots/components/ (Studio at the top level, plus
heritage/, voltage/, and bloom/ sub-folders for theme-specific decks).
Custom themes
Not limited to the four presets: build a fully custom theme from your brand colour.
Only primary and brightness are required; every other token has a sensible default.
final myTheme = BankThemeData.custom(
primary: const Color(0xFF0052CC),
brightness: Brightness.light,
// optionally override any token:
cardRadius: const BorderRadius.all(Radius.circular(20)),
useGlow: true,
glowColor: const Color(0x440052CC),
accentGradient: const LinearGradient(
colors: [Color(0xFF0052CC), Color(0xFF00B8D9)],
),
);
MaterialApp(
theme: ThemeData.light(useMaterial3: true).withBankTheme(myTheme),
darkTheme: ThemeData.dark(useMaterial3: true).withBankTheme(
BankThemeData.custom(
primary: const Color(0xFF4D9DFF),
brightness: Brightness.dark,
),
),
);
withBankTheme() registers the theme extension and synchronises the Material
ColorScheme, so Material widgets and Bank UI Kit widgets stay consistent.
You can also start from a preset and override just the fields that differ:
final tweaked = BankPreset.bloom
.apply(ThemeData.light(useMaterial3: true))
.extension<BankThemeData>()!
.copyWith(primary: const Color(0xFFE91E63));
Journeys, not just widgets
Components are designed to chain into complete, compliant banking journeys. Below, a payment travels through five kit widgets while one headless controller owns the state machine:
The same composition pattern covers every core journey. The full catalogue of 25 journey blueprints (triggers, steps, variants, error states) lives in docs/banking-journeys.md.
| Journey | Chain of kit components |
|---|---|
| Onboard a customer | BankOnboardingCarousel → BankStepProgressIndicator → BankDocumentCaptureOverlay → BankLivenessCheckOverlay → BankAsyncVerificationState → BankSuccessAnimation |
| Pay a bill | BankBillForecastList → BankBillPayTile → BankAmountInputField → BankTransferReviewCard → BankScaApprovalSheet → BankReceiptView |
| Send money to a friend | BankBeneficiaryPicker → BankAmountKeypad → BankTransferReviewCard → BankTransactionPinSheet → BankTransferResultScreen |
| Recover a lost card | BankPanicFreezeButton → BankCardControlsPanel → BankDisposableCardTile → BankPhysicalCardMaterialPicker → BankStatusTracker |
| Grow savings | BankFinancialHealthScore → BankSavingsPotCard → BankRoundUpSettingsSheet → BankSavingsChallengeCard → BankSharedPotInvite |
| Dispute a charge | BankTransactionDetailSheet → BankDisputeWizardSheet → BankSecureMessageThread → BankStatusTracker → BankInAppNotificationCenter |
Component catalogue
140+ widgets across 22 modules. Each screenshot below is a live render of that module's showcase screen (Studio preset, light mode) from the example app.
For the full parameter-level API reference (every constructor argument, type, required/optional status, and default value) see docs/component-reference.md.
States & feedback
BankSkeletonLoader · BankEmptyStateView · BankErrorStateView · BankSuccessAnimation · BankToastBanner · BankFraudAlertBanner · BankAppGateScreen (11 gate reasons: maintenance, force update, root/VPN blocks, waiting room) · BankConnectivityBanner · BankServiceStatusList · BankUpdatePromptSheet
Accounts & balances
BankAccountCard · BankAccountSwitcher · BankBalanceText (privacy-aware) · BankProductItemTile · BankAccountNumberText · BankPeekBalance (pre-login peek) · BankEarlyPaydayCard
Transactions
BankTransactionListTile · BankTransactionGroupHeader · BankTransactionDetailSheet · BankTransactionFilterSheet · BankReceiptView · BankTransactionCostSplitSheet · BankTransactionCategorySplitSheet
| Transactions | Transfers | Cards |
|---|---|---|
![]() |
![]() |
![]() |
Transfers & payments: BankAmountKeypad · BankBeneficiaryPicker · BankTransferReviewCard · BankTransactionPinSheet · BankScheduledTransferToggle · BankPaymentRequestCard · BankTransferResultScreen · BankContactPaymentSheet
Cards: BankFlipCard · BankHorizontalAccountCard · BankVirtualCardWidget (flat / gradient / mesh / metallic / image) · BankCardControlsPanel · BankCardPinManager · BankPhysicalCardMaterialPicker · BankDisposableCardTile (single-use) · BankMerchantBlockList (self-exclusion) · BankFamilyCardTile (teen cards)
Flip cards
Smooth 3-D perspective flip animation revealing the account details on the back face. Three trigger modes, two flip axes, three front-face layouts, and three background modes ship in the box: all backward-compatible and opt-in.
| Cards · Studio | Cards · Voltage | Cards · Bloom |
![]() |
![]() |
![]() |
BankFlipCard: generic flip container
Wraps any two widgets in a perspective flip. Use it for any two-sided surface.
BankFlipCard(
trigger: BankFlipTrigger.tapToFlip, // tapToFlip · builtInButton · external
flipAxis: BankFlipAxis.horizontal, // horizontal (Y-axis) · vertical (X-axis)
flipDuration: const Duration(milliseconds: 400),
flipCurve: Curves.easeInOutCubic,
frontBuilder: (ctx, _) => MyFront(),
backBuilder: (ctx, _) => MyBack(),
)
BankHorizontalAccountCard: landscape account card with flip
A landscape-format bank card showing balance, masked number, and account-type icon on the front. The back reveals the full IBAN / account number and sort code / BIC with tap-to-copy actions.
BankHorizontalAccountCard(
account: myAccount,
cardholderName: 'Alice Johnson',
// Front-face layout
layout: BankHorizontalCardLayout.centred, // balanceLeft · centred · balanceBottom
// Background
background: BankHorizontalCardBackground.image, // themeGradient · solidColor · image
backgroundImage: const AssetImage('assets/card_bg.jpg'),
backgroundImageOverlay: Colors.black54,
// Flip
trigger: BankFlipTrigger.builtInButton,
flipAxis: BankFlipAxis.horizontal,
)
External (host-controlled) flip: pair isFlipped with onFlip:
bool _flipped = false;
BankHorizontalAccountCard(
account: myAccount,
trigger: BankFlipTrigger.external,
isFlipped: _flipped,
onFlip: () => setState(() => _flipped = !_flipped),
)
Enhanced BankVirtualCardWidget
The existing virtual-card widget now accepts an image background and an explicit flip trigger. All new parameters are optional: existing code compiles unchanged.
BankVirtualCardWidget(
account: account,
cardholderName: 'ALEX MORGAN',
// new: image background
backgroundImage: const NetworkImage('https://example.com/card.jpg'),
// new: flip trigger (default: tapToFlip: same as before)
flipTrigger: BankFlipTrigger.builtInButton,
// new: optional custom flip button
flipButtonBuilder: (ctx, flip) => IconButton(
icon: const Icon(Icons.flip),
onPressed: flip,
),
)
| Auth & security | Onboarding & KYC | Saving |
|---|---|---|
![]() |
![]() |
![]() |
Auth & security: BankPinKeypad · BankPinDots · BankBiometricPromptButton · BankPrivacyToggle · BankDeviceTrustBanner · BankSessionTimeoutDialog · BankAppSwitcherPrivacyOverlay · BankOtpInput · BankScaApprovalSheet (PSD2 dynamic linking) · BankDeviceSessionTile · BankCallVerificationScreen (anti-vishing) · BankEidLoginButton (national eID) · BankPanicFreezeButton
Onboarding & KYC: BankStepProgressIndicator · BankDocumentCaptureOverlay · BankLivenessCheckOverlay · BankAsyncVerificationState · BankConsentModal · BankConsentManagementList (open-banking dashboard) · BankOnboardingCarousel · BankAddressForm
Saving: BankSavingsPotCard · BankRoundUpSettingsSheet · BankPotContributionSheet · BankIncomeSorterSheet · BankSharedPotInvite · BankSavingsChallengeCard (streaks + stamps) · BankSavingsProjectionCard (earnings calculator)
| Social | Investing | Credit |
|---|---|---|
![]() |
![]() |
![]() |
Social: BankJointTransactionListTile · BankAccountOwnershipBadge · BankSharedGoalProgressCard · BankMoneyCircleCard (Jamiyah saving circle)
Investing: BankPortfolioPerformanceChart · BankHoldingsListTile · BankWatchlistCard · BankBuySellSheet · BankAssetPriceTicker · BankLiveExchangeConverter · BankCurrencyWalletTabBar
Credit: BankCreditLimitGauge · BankFlexEligibleBadge · BankInstallmentPlanSelector · BankRepaymentScheduleView · BankCreditScoreGauge · BankLoanCalculatorCard · BankCreditLimitAdjuster (user-set limit) · BankPreapprovedLoanCard · BankOverdraftCushionMeter
| Subscriptions | Insights | Notifications |
|---|---|---|
![]() |
![]() |
![]() |
Subscriptions: BankPlanComparisonTable · BankPaywallSheet · BankPerksMarketplaceCard · BankReferralInviteCard
Insights: BankSpendingBreakdownChart (donut) · BankBudgetGaugeWidget · BankInsightCard · BankCashflowChart (history + forecast) · BankRecurringMerchantTile (subscription detection) · BankFinancialHealthScore · BankFoundMoneyList
Notifications: BankInAppNotificationCenter · BankAlertPreferencesPanel
Forms & input
BankTextField · BankAmountInputField (currency-aware) · BankMaskedInputField (IBAN / PAN / sort code, mod-97 + Luhn) · BankPhoneInputField (E.164) · BankCountryPicker (236 countries) · BankPeriodSelector
Payments & billing
BankBillPayTile + BankBillCalendarStrip · BankStandingOrderTile · BankTransferLimitManager (SCA-gated) · BankQrScannerOverlay + BankMyQrCard (local QR encoding) · BankBillForecastList (bill prediction) · BankAtmLocatorTile + BankCardlessCashCode
Rewards & engagement
BankPointsHubCard (earn/burn) · BankOffersRail (card-linked offers) · BankCashbackCategoryPicker (quarterly picks) · BankStoriesCarousel (stories + full-screen viewer) · BankPrizeDrawCard (prize-linked savings)
Islamic banking
BankZakatCalculator (nisab-aware) · BankDonationHubCard (verified charities) · BankShariahBadge · profit-rate labeling via islamicFinanceMode · Murabaha cost-plus math in BankLoanCalculatorCard · the Heritage preset
The Zakat calculator applies the widely used 2.5% rate on zakatable wealth above a bank-supplied nisab threshold; the calculation method, threshold, and the charity verification flag are inputs your Shariah board controls, not rulings the kit makes.
Business banking
BankApprovalRequestTile (maker-checker) · BankBatchPaymentReviewSheet · BankValueDiffRow
Documents & deposits
BankStatementListTile · BankChequeCaptureOverlay + BankChequeDepositSummary (remote deposit capture)
Support & servicing
BankDisputeWizardSheet (+ headless BankDisputeFlowController) · BankSecureMessageThread · BankHelpFaqList · BankAssistantPanel (named AI assistant entry)
Scaffolding & display
BankAppBar · BankBottomNavBar · BankEmblem · BankSummaryStack · BankStatusTracker · BankQuickActionsGrid · BankMoneyProtectionBanner · BankShariahBadge · BankWalletProvisioningButton · BankTravelNoticeForm
Cross-cutting features
Privacy mode
BankPrivacyToggle flips BankUiScope.privacyEnabled; every BankBalanceText masks itself automatically.
BankBalanceText(money: account.balance) // shows '••••' when privacy is on
BankAppSwitcherPrivacyOverlay blurs the app-switcher snapshot at the
widget level. It is defense in depth, not capture protection: pair it
with platform FLAG_SECURE (Android) and screen-capture protection
(iOS) per the recipes in
docs/enterprise/integration-playbook.md.
Currency-correct money display
Every amount renders through a currency engine that knows each
currency's official symbol, minor units, and symbol placement: the
Saudi riyal symbol, three-decimal Gulf currencies (OMR, KWD, BHD),
zero-decimal JPY/KRW, and crypto precision all follow their own
guidelines. Register your own with BankCurrencies.register.
BankBalanceText(money: Money.fromDouble(1250.5, 'OMR')) // ر.ع. 1,250.500
Numeral styles
Western or Eastern Arabic-Indic digits, independent of locale: ideal for GCC apps.
BankUiScope(
initialData: BankUiScopeData(numeralStyle: NumeralStyle.easternArabicIndic),
child: ...,
)
Islamic finance mode
Swaps interest/APR labels for profit-rate equivalents wherever a widget renders label text.
BankUiScope(initialData: BankUiScopeData(islamicFinanceMode: true), child: ...)
Localization
Ships English strings; override any subset via BankUiStrings: no gen-l10n dependency.
RTL
Every widget is built RTL-first with directional geometry throughout;
widget-test coverage runs under TextDirection.rtl and automated RTL
golden screenshots are on the release roadmap
(docs/enterprise/versioning-and-releases.md).
Architecture & principles
- Tokens, not magic numbers. Widgets read colours, radii, spacing, elevation, and
numeral typography from
BankThemeData/BankTokens: never hard-coded. - State-management agnostic. Pure widgets: data in via the constructor, events out
via callbacks. No provider/bloc/riverpod coupling in
lib/. - Lossless money. The
Moneytype wrapsDecimal; nodoubleever touches an amount. - Headless flow controllers.
BankKycFlowController,BankTransferFlowController, andBankIncomeSorterControllerown multi-step flow state so you can swap the visual layer. - Bring your own imagery. Widgets expose
Widget? illustrationslots; the kit bundles no raster/vector art.
lib/
core.dart · saving.dart · social.dart · investing.dart · credit.dart # barrels
src/
theme/ # BankTokens, BankThemeData, presets, custom theming
scope/ # BankUiScope + BankUiStrings
models/ # Money, Transaction, BankAccount, … (==, hashCode, copyWith)
<feature>/ # one folder per module
controllers/# headless flow controllers
Running the example
The example app ships two entry points:
| Entry point | Launch command | What it shows |
|---|---|---|
| Component gallery | flutter run -t lib/gallery_main.dart |
119 components with live parameter controls, preset/dark-mode switching, and search |
| Demo dashboard | flutter run |
Revolut-style demo app under the Studio preset |
cd example
flutter pub get
flutter run -t lib/gallery_main.dart # interactive gallery
flutter run # demo dashboard
Regenerating the screenshots
Screenshots in this README are produced from the real widgets via Flutter web:
cd example
flutter build web -t lib/screenshot_harness.dart --release --no-web-resources-cdn --no-tree-shake-icons
cd ..
node tool/screenshots.mjs # requires playwright + a Chromium
See it, then ship it
Ten minutes to conviction. Run the gallery and switch presets live:
git clone https://github.com/sayed3li97/bank-ui-kit.git
cd bank-ui-kit/example && flutter run -t lib/gallery_main.dart
Building a bank? Start from the journey blueprints, compose the widgets, wire your APIs to the callbacks, and read the integration playbook. Your core banking stays yours.
Contributing
See CONTRIBUTING.md and our Code of Conduct.
In short: flutter analyze and flutter test must be green, and every change must work
across all four presets, both brightnesses, and RTL.
License
MIT © 2026 Sayed Ali and Bank UI Kit contributors.
Fonts bundled with the kit: Space Grotesk, Fredoka, and Nunito - are licensed under the SIL Open Font License.
Libraries
- bank_ui_kit
- Bank UI Kit: convenience re-export of
core.dart. - core
- Core Bank UI Kit library.
- credit
- Bank UI Kit: Credit sub-library.
- investing
- Bank UI Kit: Investing sub-library.
- saving
- Bank UI Kit: Saving sub-library.
- Bank UI Kit: Social sub-library.






















