bkey_uikit 0.0.1
bkey_uikit: ^0.0.1 copied to clipboard
BMoni design system for Flutter — typography, colour tokens, themes and a curated set of reusable UI primitives shared across Bkey products.
bkey_uikit #
A shared Flutter UI component library for Bkey products, built on top of the BMoni design system.
bkey_uikit provides design tokens, typography, theming, and reusable UI primitives that are used across Bkey Flutter apps. It has no dependency on any specific app's business logic, state management, routing, or localisation framework.
📋 What's Inside #
| Layer | Contents |
|---|---|
| Design Tokens | BMoniColors — full colour palette + semantic light/dark tokensBMoniTextStyles — complete type scale (display, heading, body, label)BMoniTheme — Flutter ThemeData factory + TextTheme wiring |
| Enums | Button, text-field, display, and status enums shared by all components |
| Components | Buttons, text fields, text widgets, avatars, toasts, bottom sheets, empty states, loaders, layout primitives, and wallet cards |
| Fonts | Rethink Sans (400–800, regular + italic) bundled in assets/fonts/ |
| Wallet Assets | Default wallet background art (USD/NGN/EUR/GBP/CAD/MXN/consolidated) plus 6 colour variants per currency, and shared SVG icons (logo_alt, info, eye_alt, eye_closed) bundled in assets/images/wallets/ and assets/svgs/ |
🚀 Installation #
Add bkey_uikit as a dependency in your pubspec.yaml:
dependencies:
bkey_uikit: ^0.0.1
(Note: Adjust the installation instructions based on whether the package is published publicly or via a private git repository/path).
🛠️ Setup #
Wrap your app with BMoniTheme.darkTheme() (or the appropriate theme) to apply the full design system:
import 'package:bkey_uikit/bkey_uikit.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
theme: BMoniTheme.darkTheme(),
home: const MyHomePage(),
),
);
}
Import everything from a single barrel file:
import 'package:bkey_uikit/bkey_uikit.dart';
🎨 Design Tokens #
Colours #
Container(color: BMoniColors.brand500)
Container(color: context.colors.bg.greySubtle) // theme-aware extension
Typography #
Text('Hello', style: BMoniTextStyles.h4Semibold)
Text('Body', style: BMoniTextStyles.p2Regular)
🧩 Components Reference #
Every component below is exported from the single package:bkey_uikit/bkey_uikit.dart barrel.
Buttons & Actions #
BMoniButton
Primary action button with four visual variants and five sizes. Supports leading/trailing icons, loading state, and per-instance colour overrides. Triggers a light haptic on press.
BMoniButton(
onPressed: () {},
text: 'Confirm',
variant: BMoniButtonVariant.primary, // primary | secondary | outline | ghost
size: BMoniButtonSize.large, // extraSmall | small | medium | large | custom
icon: Icons.check,
iconPosition: BMoniButtonIconPosition.leading,
isLoading: false,
isDisabled: false,
)
// Convenience factories
BMoniButton.primary(onPressed: () {}, text: 'Save')
BMoniButton.secondary(onPressed: () {}, text: 'Edit')
BMoniButton.outline(onPressed: () {}, text: 'Cancel')
BMoniButton.ghost(onPressed: () {}, text: 'Skip')
UtilityButton
Square icon-only button used for compact toolbar actions.
UtilityButton(
onTap: () {},
size: 36,
backgroundColor: BMoniColors.brand600,
icon: const Icon(Icons.add, color: Colors.white, size: 24),
)
SwipeableActionRow
Row that reveals an action button when swiped left. A shared ValueNotifier<String?> ensures only one row is open at a time within a list.
final openItemId = ValueNotifier<String?>(null);
SwipeableActionRow(
itemId: 'item-1',
openItemId: openItemId,
actionWidth: 72,
actionColor: Colors.red,
actionIcon: const Icon(Icons.delete, color: Colors.white),
onActionPressed: () {/* delete */},
onTap: () {/* open detail */},
child: ListTile(title: Text('Swipe me left')),
)
Text & Typography #
Helper widgets that wrap Text with the BMoni type scale.
DisplayText('Welcome', level: 2, weight: DisplayWeight.bold)
HeadingText('Page title', level: 3, weight: HeadingWeight.semibold)
BodyText('Lorem ipsum', size: BodySize.medium, weight: BodyWeight.regular)
LabelText('Caption', size: LabelSize.small, weight: LabelWeight.medium)
// Domain-specific helpers
AmountText(1234.56, currency: r'$', decimalPlaces: 2)
StatusText('Pending', status: StatusType.warning)
ReadMoreText
Collapsible text widget with length- or line-based trimming, custom toggle labels, RegExp-based annotations, and rich-text support.
ReadMoreText(
longString,
trimMode: TrimMode.line,
trimLines: 3,
trimCollapsedText: 'read more',
trimExpandedText: 'show less',
onExpandChanged: (isExpanded) {},
)
Inputs & Forms #
BMoniTextFormField
Form field with two variants (filled and outlined), three sizes, label/helper/error slots, and prefix/suffix widgets.
BMoniTextFormField.filled(
label: 'Email',
hintText: 'you@example.com',
keyboardType: TextInputType.emailAddress,
size: BMoniTextFieldSize.medium,
prefixIcon: const Icon(Icons.mail_outline),
validator: (value) => value!.isEmpty ? 'Required' : null,
)
BMoniTextFormField.outlined(
label: 'Reference',
hintText: 'INV-001',
)
BMoniTextAreaField
Multiline note input with a built-in grapheme-aware character counter.
BMoniTextAreaField(
controller: _noteController,
label: 'Add a note',
hintText: 'Optional message',
maxLength: 120,
maxLines: 4,
)
FileUploadWidget
Dotted-border upload area. Switches between placeholder, loading, and uploaded states.
FileUploadWidget(
fileBytes: bytes,
fileName: 'invoice.pdf',
isLoading: false,
onTap: pickFile,
onRemove: () => setState(() => bytes = null),
errorMessage: validationError,
)
Avatars & Images #
ProfileAvatar & ChatAvatar
ProfileAvatar(imageUrl: user.avatarUrl, name: user.fullName, size: 48)
ChatAvatar(
imageUrl: null,
name: 'Alice Doe',
userId: 'u_123',
size: 40,
)
ProfileImageWidget
Tap-aware profile image that supports network URLs, asset paths, and local files. Caches network images.
ProfileImageWidget(
imageUrl: profile.imageUrl,
radius: 40,
onTap: pickNewAvatar,
)
Layout & Containers #
ActivitySectionCard & SectionHeader
ActivitySectionCard(
header: const SectionHeader(
title: 'Recent activity',
trailing: Text('View all'),
),
child: const Padding(
padding: EdgeInsets.all(16),
child: Text('Section content'),
),
footer: const Divider(),
)
InfoCard
Inline informational/warning/tip card.
InfoCard(
message: 'Your KYC is being reviewed.',
title: 'In review',
icon: Icons.info_outline,
)
CustomAppBar
Scaffold(
appBar: CustomAppBar(
title: 'Settings',
showBackButton: true,
actions: [IconButton(onPressed: () {}, icon: const Icon(Icons.help))],
),
)
Sheets & Overlays #
BMoniBottomSheet.show & BMoniTitledBottomSheet
final result = await BMoniBottomSheet.show<String>(
context: context,
child: const BMoniTitledBottomSheet(
title: 'Choose option',
children: [/* ... */],
),
);
BMoniOptionsBottomSheet
BMoniOptionsBottomSheet(
title: 'More actions',
options: [
BMoniBottomSheetOption(icon: 'assets/svgs/edit.svg', title: 'Edit', onTap: () {}),
BMoniBottomSheetOption(icon: 'assets/svgs/delete.svg', title: 'Delete', onTap: () {}),
],
)
SelectorBottomSheet<T> & SearchableSelectorBottomSheet<T>
final picked = await BMoniBottomSheet.show<Currency>(
context: context,
child: SelectorBottomSheet<Currency>(
items: currencies,
selected: current,
title: 'Choose currency',
label: (c) => c.name,
value: (c) => c.code,
icon: (c) => c.flagAsset,
showIcon: true,
),
);
Feedback & Status #
BMoniToast and BMoniToastOverlay
BMoniToastOverlay.showSuccess(
context: context,
message: 'Payment sent!',
title: 'Success',
);
BMoniToastOverlay.showError(context: context, message: 'Network error');
EmptyState, FailureWidget, & InProgressWidget
EmptyState(
svgAsset: 'assets/svgs/empty_box.svg',
message: 'No transactions yet',
subtitle: 'Send or receive funds to get started',
buttonText: 'Add money',
onButtonPressed: () {},
)
Loaders
const ProgressLoaderWidget() // Square branded loading container
const ChasingDots() // Three small white dots animating
Wallet Cards #
BMoniWalletCard
A 250px-tall card with a configurable background, a top-left logo slot, an optional bottom-right info button, a centred balance slot, and a built-in scale-down press animation.
BMoniWalletCard(
background: const BMoniWalletCardBackground.type(BMoniWalletType.usd),
onInfoTap: () => showWalletDetails(),
reserveBottomSpaceForPageIndicator: hasMultiplePages,
balanceChild: BMoniWalletCardBalance(
wholePart: r'$1,234',
decimalPart: '.56',
isHidden: isBalanceHidden,
onToggleHidden: toggleHideBalance,
),
)
🧪 Testing #
Run the tests using the standard Flutter test command:
flutter test
💡 Example #
A complete component gallery lives in the example/ directory.
It boots straight into a navigable list of every widget grouped by category
(buttons, inputs, sheets, wallet cards, feedback, …) and is themed with
BMoniTheme.darkTheme().
cd example
flutter pub get
flutter run
📄 License #
Copyright 2026 Bkey, Inc.
Licensed under the Apache License, Version 2.0 — you may use, modify, and distribute the SDK (including in proprietary applications) provided you preserve the copyright and license notices and comply with the terms in the LICENSE file.
For commercial support or enterprise inquiries, contact developers@bkey.me.