ntb_vistech_widgets 1.0.0
ntb_vistech_widgets: ^1.0.0 copied to clipboard
NTB reusable Flutter widgets library
NTB Vistech Widgets #
A Flutter widget library with customizable buttons, inputs, and UI components for NTB applications.
๐ฏ Features #
- โ NTBOutlinedButton - Customizable outlined buttons with multiple variants
- โ Button - Elevated buttons with theme support
- โ Multiple Variants - Primary, Secondary, Disabled, Transparent
- โ Icon Support - Leading and trailing icons
- โ Dark Mode - Automatic theme adaptation
๐ฆ Installation #
Option 1: Install from pub.dev (Recommended for Production) #
Add this to your app's pubspec.yaml:
dependencies:
ntb_vistech_widgets: ^0.1.0
Then run:
flutter pub get
Option 2: Install Locally (Recommended for Development) #
For local development or testing unreleased features, use a path dependency.
Step 1: Clone the Repository
Clone at the same level as your consumer app:
your-projects/
โโโ your-app/ # Your Flutter app
โโโ ntb-smartphone-widgetbook/ # This widget library
cd your-projects/
git clone https://bitbucket.org/NTB-NO/ntb-smartphone-widgetbook.git
Step 2: Update Your App's Dependencies
In your app's pubspec.yaml, add the path dependency:
dependencies:
flutter:
sdk: flutter
# Use path dependency for local development
ntb_vistech_widgets:
path: ../ntb-smartphone-widgetbook
Step 3: Install Dependencies
cd your-app/
flutter pub get
Step 4: Import and Use
import 'package:ntb_vistech_widgets/ntb_vistech_widgets.dart';
// Use the widgets
NTBOutlinedButton(
label: 'Click Me',
variant: NTBButtonVariant.primary,
onPressed: () => print('Clicked!'),
)
๐ฅ Hot Reload with Local Changes
When using path dependency, changes are picked up automatically:
- Make changes in
ntb-smartphone-widgetbook/lib/ - Save the file
- Hot reload (
r) in your app - See changes instantly! โก
๐ Switching Between Versions
Use local version (development):
ntb_vistech_widgets:
path: ../ntb-smartphone-widgetbook
Use published version (production):
ntb_vistech_widgets: ^0.1.0
Just comment/uncomment and run flutter pub get.
๐ Quick Start #
Basic Outlined Button #
import 'package:ntb_vistech_widgets/ntb_vistech_widgets.dart';
NTBOutlinedButton(
label: 'Click Me',
variant: NTBButtonVariant.primary,
onPressed: () => print('Clicked!'),
)
Button with Icons #
NTBOutlinedButton(
label: 'Download',
variant: NTBButtonVariant.primary,
leadingIcon: Icons.download,
trailingIcon: Icons.arrow_forward,
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
onPressed: () => print('Download started'),
)
Transparent Button #
NTBOutlinedButton(
label: 'Cancel',
variant: NTBButtonVariant.transparent,
noBorder: true,
contentPadding: EdgeInsets.symmetric(horizontal: 0, vertical: 12),
onPressed: () => print('Cancelled'),
)
Elevated Button #
Button(
label: 'Submit',
variant: NTBButtonVariant.primary,
onPressed: () => print('Submitted'),
)
๐จ Button Variants #
| Variant | Description | Use Case |
|---|---|---|
primary |
Green background, white text | Main call-to-action buttons |
secondary |
Grey background, white text | Secondary actions |
disabled |
Grey tones, no interaction | Disabled state |
transparent |
Transparent background | Subtle actions, links |
Understanding Variants #
Variants provide pre-configured button styles that adapt to your app's theme (light/dark mode). Instead of manually setting colors for each button, use variants for consistency.
๐ ๏ธ Customization #
NTBOutlinedButton(
label: 'Custom Button',
variant: NTBButtonVariant.primary,
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
borderColor: Colors.deepPurple,
contentPadding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
maxLines: 2,
onPressed: () {},
)
Available Properties #
| Property | Type | Default | Description |
|---|---|---|---|
label |
String |
required | Button text |
variant |
NTBButtonVariant |
primary |
Button style variant |
onPressed |
VoidCallback? |
null |
Tap callback |
leadingIcon |
IconData? |
null |
Icon before text |
trailingIcon |
IconData? |
null |
Icon after text |
backgroundColor |
Color? |
variant color | Custom background |
foregroundColor |
Color? |
variant color | Custom text/icon color |
borderColor |
Color? |
theme outline | Custom border |
contentPadding |
EdgeInsetsGeometry? |
(16, 8) |
Internal padding |
noBorder |
bool |
false |
Remove border |
maxLines |
int |
3 |
Max text lines |
style |
TextStyle? |
null |
Custom text style |
๐ Widgetbook - Live Documentation #
This library includes Widgetbook - an interactive showcase where you can explore all widgets, variants, and configurations in real-time.
What is Widgetbook? #
Widgetbook is like Storybook for Flutter. It provides:
- ๐จ Live preview of all widgets
- ๐๏ธ Interactive controls (knobs) to modify properties in real-time
- ๐ Dark/Light mode toggle
- ๐ฑ Responsive preview
- ๐ Search and filter widgets
- ๐ Living documentation that stays in sync with code
Running Widgetbook Locally #
Understanding the Project Structure
This repository contains two separate Flutter projects:
ntb-smartphone-widgetbook/
โโโ lib/ # ๐ฆ Main widget library (published to pub.dev)
โ โโโ src/
โ โ โโโ inputs/
โ โ โโโ button.dart
โ โ โโโ outlined_button.dart
โ โโโ ntb_vistech_widgets.dart
โโโ pubspec.yaml # Library dependencies
โ
โโโ widgetbook/ # ๐ฑ Separate Flutter app (not published)
โโโ lib/
โ โโโ main.dart
โ โโโ widgetbook.dart
โ โโโ use_cases/
โโโ pubspec.yaml # Widgetbook dependencies
โโโ web/
Two projects explained:
-
Main Library (
/root)- The reusable widget library you install in your apps
- Gets published to pub.dev
- Contains the actual widget implementations
-
Widgetbook App (
/widgetbook/folder)- A standalone Flutter application
- Showcases and documents the widgets
- Used for development and testing only
- Not published to pub.dev
Why this structure?
- Widgetbook requires a separate Flutter app to run
- The main library stays clean and lightweight for pub.dev
- The widgetbook app can have its own dependencies without affecting the library
- This is the standard pattern for Flutter widget libraries with Widgetbook
- The widgetbook app can be built as a web version - (To be discussed?) this would allow us to deploy this library as a live documentation website where other team members can view and test all widget variants interactively in their browser before consuming the widgets.
Setup and Run
Step 1: Clone the Repository
# Clone the entire repository
git clone https://bitbucket.org/NTB-NO/ntb-smartphone-widgetbook.git
cd ntb-smartphone-widgetbook
Step 2: Install Main Library Dependencies
# From the root directory
flutter pub get
Step 3: Navigate to Widgetbook App
# Navigate into the widgetbook folder
cd widgetbook
Important: All remaining commands run from inside the widgetbook/ directory!
Step 4: Install Widgetbook Dependencies
# Inside widgetbook/ directory
flutter pub get
Step 5: Generate Widget Catalog
# Inside widgetbook/ directory
dart run build_runner build --delete-conflicting-outputs
This generates widgetbook.directories.g.dart which catalogs all widgets with @UseCase annotations.
Step 6: Run Widgetbook
# To run on Web (Recommended for Widgetbook)
flutter run -d chrome
# To run on a connected Simulator/Emulator
flutter run
The Widgetbook will open in your browser at http://localhost:XXXX
Quick Start Commands (TL;DR)
# One-liner to get started
git clone https://bitbucket.org/NTB-NO/ntb-smartphone-widgetbook.git && \
cd ntb-smartphone-widgetbook/widgetbook && \
flutter pub get && \
dart run build_runner build --delete-conflicting-outputs && \
flutter run -d chrome
Development Mode with Auto-Rebuild
For active development, use watch mode to automatically rebuild when you change use cases:
Terminal 1: Start watch mode
cd widgetbook
dart run build_runner watch --delete-conflicting-outputs
Terminal 2: Run the app
cd widgetbook
flutter run -d chrome
Now when you:
- Create new use cases
- Modify existing use cases
- Add
@UseCaseannotations
The catalog automatically rebuilds! Just hot reload (r) to see changes.
Typical Development Workflow
# 1. Edit widget in main library (from project root)
vim lib/src/inputs/my_widget.dart
# 2. Update use cases (from widgetbook/ directory)
cd widgetbook
vim lib/use_cases/inputs/my_widget_use_cases.dart
# 3. If watch mode is running, catalog rebuilds automatically
# 4. Press 'r' in the Flutter terminal to hot reload
# 5. See your changes in the browser instantly! โก
Troubleshooting
"Port already in use" error?
flutter run -d chrome --web-port=8080
Build errors after adding new use cases?
# Clean and rebuild
cd widgetbook
dart run build_runner clean
dart run build_runner build --delete-conflicting-outputs
Can't find your widgets in Widgetbook?
- Ensure you've added
@UseCaseannotations to your use case functions - Check that
build_runnercompleted successfully - Verify use case files are in
widgetbook/lib/use_cases/ - Make sure you're importing from
package:ntb_vistech_widgets/ntb_vistech_widgets.dart
Hot reload not working?
# Try hot restart instead
# Press 'R' (capital R) in the Flutter terminal
๐ฏ How to Create New Widgets for Widgetbook #
Widget Naming Convention & Organization #
All widgets in this library follow the NTB prefix pattern:
โ
NTBOutlinedButton // Good
โ
NTBTextField // Good
โ
NTBCheckbox // Good
โ OutlinedButton // Bad - missing NTB prefix
โ CustomButton // Bad - not following convention
Why NTB prefix?
- Clear identification - Easy to distinguish library widgets from Flutter's built-in widgets
- No naming conflicts - Avoids collisions with Material/Cupertino widgets
- Consistent imports - All widgets clearly come from
ntb_vistech_widgets - Better IDE autocomplete - Type "NTB" to see all available widgets
- Professional branding - Shows these are official NTB components
Widget Organization by Category #
Organize widgets in folders based on their purpose:
lib/src/
โโโ actions/ # User action widgets
โ โโโ button.dart # NTBButton
โ โโโ outlined_button.dart # NTBOutlinedButton
โ
โโโ inputs/ # Form input widgets
โ โโโ text_field.dart # NTBTextField
โ โโโ text_area.dart # NTBTextArea
โ โโโ checkbox.dart # NTBCheckbox
โ โโโ radio.dart # NTBRadio
โ โโโ switch.dart # NTBSwitch
โ โโโ multiselect.dart # NTBMultiselect
โ
โโโ feedback/ # User feedback widgets
โ โโโ snackbar.dart # NTBSnackbar
โ โโโ alert.dart # NTBAlert
โ โโโ badge.dart # NTBBadge
โ โโโ progress_indicator.dart # NTBProgressIndicator
โ
โโโ overlays/ # Modal/overlay widgets
โ โโโ modal.dart # NTBModal
โ โโโ dialog.dart # NTBDialog
โ โโโ bottom_sheet.dart # NTBBottomSheet
โ
โโโ display/ # Display/presentation widgets
โโโ card.dart # NTBCard
โโโ chip.dart # NTBChip
โโโ avatar.dart # NTBAvatar
Category Guidelines #
| Category | Purpose | Examples |
|---|---|---|
| actions/ | Trigger actions or navigation | Buttons, FABs, Icon buttons |
| inputs/ | Collect user input | Text fields, checkboxes, dropdowns, switches |
| feedback/ | Show status or notifications | Alerts, snackbars, badges, loading indicators |
| overlays/ | Temporary layered UI | Modals, dialogs, bottom sheets, tooltips |
| display/ | Present information | Cards, chips, avatars, list tiles |
Step 1: Create Your Widget #
Create your widget in the appropriate category folder with the NTB prefix:
// lib/src/inputs/text_field.dart
import 'package:flutter/material.dart';
import '../../global/button_variant.dart';
/// A customizable text input field following NTB design standards.
class NTBTextField extends StatelessWidget {
final String label;
final String? hintText;
final TextEditingController? controller;
final NTBButtonVariant variant;
const NTBTextField({
super.key,
required this.label,
this.hintText,
this.controller,
this.variant = NTBButtonVariant.primary,
});
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
decoration: InputDecoration(
labelText: label,
hintText: hintText,
border: OutlineInputBorder(),
),
);
}
}
### Step 2: Export from Main Library
Add to `lib/ntb_vistech_widgets.dart`:
```dart
library ntb_vistech_widgets;
export 'src/inputs/ntb_button.dart';
export 'src/inputs/ntb_outlined_button.dart';
export 'src/inputs/ntb_my_custom_widget.dart'; // โฌ
๏ธ Add this
export 'global/ntb_button_variant.dart';
Step 3: Create Use Cases for Widgetbook #
Create a use case file in the widgetbook directory:
// widgetbook/lib/use_cases/inputs/my_custom_widget_use_cases.dart
import 'package:flutter/material.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:ntb_vistech_widgets/ntb_vistech_widgets.dart';
// Basic use case
@UseCase(name: 'Default', type: MyCustomWidget)
Widget defaultCustomWidget(BuildContext context) {
final label = context.knobs.string(
label: 'Label',
initialValue: 'My Custom Widget',
);
return Center(
child: MyCustomWidget(
label: label,
variant: NTBButtonVariant.primary,
onPressed: () => print('Clicked!'),
),
);
}
// Use case with variants
@UseCase(name: 'Interactive', type: MyCustomWidget)
Widget interactiveCustomWidget(BuildContext context) {
final label = context.knobs.string(
label: 'Label',
initialValue: 'Interactive Widget',
);
final variant = context.knobs.list(
label: 'Variant',
options: NTBButtonVariant.values,
labelBuilder: (v) => v.name,
);
return Center(
child: MyCustomWidget(
label: label,
variant: variant,
onPressed: () => print('Variant: ${variant.name}'),
),
);
}
Step 4: Available Knobs (Interactive Controls) #
Widgetbook provides knobs to make properties interactive:
// Text input
final text = context.knobs.string(
label: 'Label',
initialValue: 'Default text',
);
// Number slider
final size = context.knobs.double.slider(
label: 'Size',
initialValue: 16,
min: 10,
max: 30,
);
// Integer slider
final count = context.knobs.int.slider(
label: 'Count',
initialValue: 3,
min: 1,
max: 10,
);
// Boolean toggle
final isEnabled = context.knobs.boolean(
label: 'Enabled',
initialValue: true,
);
// Dropdown list
final variant = context.knobs.list(
label: 'Variant',
options: NTBButtonVariant.values,
labelBuilder: (v) => v.name,
);
// Color picker
final color = context.knobs.color(
label: 'Color',
initialValue: Colors.blue,
);
Step 5: Generate Widgetbook Catalog #
After creating use cases, regenerate the catalog:
cd widgetbook
dart run build_runner build --delete-conflicting-outputs
What this does:
Generates widgetbook/lib/widgetbook.directories.g.dart - the widget catalog Automatically discovers all @UseCase annotations in your use case files Creates the navigation structure you'll see in Widgetbook's sidebar โ ๏ธ Important: This step is mandatory for your widgets to appear in Widgetbook!
This auto-generates:
widgetbook/lib/widgetbook.directories.g.dart- Widget catalog- Automatically discovers all
@UseCaseannotations
Step 6: View in Widgetbook #
flutter run -d chrome
Your widget will appear in the sidebar under the appropriate category!
๐ Widgetbook Project Structure #
widgetbook/
โโโ lib/
โ โโโ main.dart # Widgetbook app entry point
โ โโโ widgetbook.dart # Widgetbook configuration
โ โโโ widgetbook.directories.g.dart # Auto-generated catalog
โ โโโ use_cases/
โ โโโ inputs/
โ โ โโโ ntb_button_use_cases.dart # Button examples
โ โ โโโ ntb_outlined_button_use_cases.dart
โ โ โโโ ntb_my_custom_widget_use_cases.dart
โ โโโ other_category/
โ โโโ ...
โโโ pubspec.yaml # Widgetbook dependencies
โโโ README.md
๐จ Use Case Best Practices #
1. Create Multiple Use Cases #
Show different states and configurations:
@UseCase(name: 'Default', type: MyWidget)
Widget defaultWidget(BuildContext context) { ... }
@UseCase(name: 'With Icon', type: MyWidget)
Widget withIconWidget(BuildContext context) { ... }
@UseCase(name: 'Disabled', type: MyWidget)
Widget disabledWidget(BuildContext context) { ... }
@UseCase(name: 'Custom Colors', type: MyWidget)
Widget customColorsWidget(BuildContext context) { ... }
2. Use Descriptive Names #
Help users find what they need:
@UseCase(name: 'Primary Button with Leading Icon', type: NTBOutlinedButton)
@UseCase(name: 'Transparent Button - No Border', type: NTBOutlinedButton)
3. Add Interactive Controls #
Let users experiment with properties:
final hasIcon = context.knobs.boolean(
label: 'Show Icon',
initialValue: false,
);
final iconSize = context.knobs.double.slider(
label: 'Icon Size',
initialValue: 24,
min: 16,
max: 48,
);
4. Wrap in Padding #
Give widgets breathing room:
return Center(
child: Padding(
padding: const EdgeInsets.all(20),
child: MyWidget(...),
),
);
5. Group Related Use Cases #
Keep files organized by widget type:
button_use_cases.dart- All Button variantsoutlined_button_use_cases.dart- All NTBOutlinedButton variantsinput_field_use_cases.dart- All input variants
๐ Development Workflow #
# 1. Make changes to your widget in lib/
vim lib/src/inputs/ntb_my_widget.dart
# 2. Update or create use cases in widgetbook/
vim widgetbook/lib/use_cases/inputs/ntb_my_widget_use_cases.dart
# 3. Rebuild Widgetbook catalog
cd widgetbook
dart run build_runner build --delete-conflicting-outputs
# 4. Hot reload in browser to see changes
# Press 'r' in terminal or refresh browser
Watch Mode for Continuous Development #
cd widgetbook
# Start watch mode (auto-rebuilds on file changes)
dart run build_runner watch --delete-conflicting-outputs
# In another terminal, run the app
flutter run -d chrome
Now any changes to use cases will automatically rebuild the catalog!
๐ฆ Publishing to pub.dev #
Step-by-Step Publishing Guide #
1.Update Version Number
Follow Semantic Versioning:
# pubspec.yaml
name: ntb_vistech_widgets
version: 0.1.1 # โฌ
๏ธ Increment this
# version: 0.1.1-dev.2 # โฌ
๏ธ Or use dev suffix for prereleases
# Version format: MAJOR.MINOR.PATCH
# - MAJOR: Breaking changes
# - MINOR: New features (backwards compatible)
# - PATCH: Bug fixes
2.Update git tag and commit message to match your new version number before pushing to Bitbucket.
This keeps the repository in sync with the published version on pub.dev. #
1. Stage your pubspec, changelog, and other files related to the version bump #
git add pubspec.yaml CHANGELOG.md
2. Commit the version bump #
git commit -m "chore: bump version to 0.1.1"
3. Create a version tag (matching your pubspec version) #
git tag v0.1.1
4. Push both your code changes and the new tag to Bitbucket #
(Change 'master' to 'main' if your default branch name differs) #
git push origin master --tags
3.Run a Dry Run
Before publishing, ensure you have:
- โ A pub.dev account (sign in with Google)
- โ Verified email address on pub.dev
- โ
Updated version number in
pubspec.yaml - โ
Updated
CHANGELOG.mdwith version changes - โ
All tests passing (
flutter test) - โ
No analysis issues (
flutter analyze) - โ Proper package documentation
dart pub publish --dry-run
4.Publish to pub.dev
If the dry run succeeds, run the live publishing command.
โ ๏ธ Warning: Publishing is permanent. You cannot delete or overwrite a version once it is live on pub.dev.
dart pub publish
๐ Deploy Widgetbook (Optional) #
Deploy Widgetbook as a static website for team access (to be discussed):
cd widgetbook
flutter build web --release
# Upload build/web/ to hosting:
# - TeamCity CI/CD?
๐งช Testing #
# Run tests
flutter test
# Run tests with coverage
flutter test --coverage
# View coverage report
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html
๐ค Contributing #
Adding New Widgets #
- Create widget in
lib/src/[category]/ - Export from
lib/ntb_vistech_widgets.dart - Create use cases in
widgetbook/lib/use_cases/[category]/ - Rebuild Widgetbook:
dart run build_runner build - Update
CHANGELOG.md - Test thoroughly
- Submit PR with description
### Code Style
- Follow [Effective Dart](https://dart.dev/guides/language/effective-dart) guidelines
- Run `flutter analyze` before committing
- Use meaningful variable and function names
- Add documentation comments for public APIs
- Keep widgets composable and reusable
---
## ๐ Changelog
See [CHANGELOG.md](CHANGELOG.md) for version history and migration guides.
---
## ๐ License
MIT License - see [LICENSE](LICENSE) file for details.
---
## ๐ Links
- ๐ฆ [Pub.dev Package](https://pub.dev/packages/ntb_vistech_widgets)
- ๐ [Repository](https://bitbucket.org/NTB-NO/ntb-smartphone-widgetbook)
- ๐ [Issue Tracker](https://bitbucket.org/NTB-NO/ntb-smartphone-widgetbook/issues)
- ๐ [Widgetbook Documentation](https://docs.widgetbook.io/)
---
## ๐ Acknowledgments
Built with:
- [Flutter](https://flutter.dev/) - UI framework
- [Widgetbook](https://www.widgetbook.io/) - Component library tool
- [Material Design](https://material.io/) - Design system
---
Made with โค๏ธ by NTB