bc_ui 0.4.2
bc_ui: ^0.4.2 copied to clipboard
A Flutter design system porting heroui-native 1:1 — 60+ token-driven components, light and dark, on a Material 3 base.

A Flutter design system that ports heroui-native 1:1
Same tokens, same variants, same motion — on a Material 3 base, so the rest of the Material ecosystem keeps working.
API reference · Components · Theming · Example app
Why #
- One token system, 64 semantic color slots. Every color is precomputed from
heroui-native's oklch sources — including each
color-mixderived hover/soft shade — into a light and a dark palette. No component hard-codes a color. - iOS-grade surfaces. Continuous ("squircle") corners via
RoundedSuperellipseBorder, layered surface/overlay shadows, and frosted headers built on realBackdropFilterblur. - The motion is ported, not approximated. Press scale 0.985 with width
compensation, switch thumb spring (mass 2 / stiffness 1600 / damping 120),
tab indicator that tracks your finger, 1500ms shimmer — see
BCMotion. - Material stays available.
BCTheme.light()returns aThemeData, soScaffold,Navigator,showDialogand every Material widget still work. - Inter is bundled. No font setup, no missing-glyph surprises.
- 60+ components, all light/dark aware, all documented in the API reference.
| Light | Dark |
|---|---|
![]() |
![]() |
The screen above is assembled entirely from bc_ui — header, card, buttons,
tabs, list group, chips, bottom nav. Its source is
example/lib/showcase/screens/demo_app_screen.dart.
Install #
flutter pub add bc_ui
or add it by hand:
dependencies:
bc_ui: ^0.4.0
Requires Dart SDK ^3.12.1. The only runtime dependency is
phone_numbers_parser, which
BCPhoneField uses for parsing and validation — pure Dart, no platform
channels.
Setup #
import 'package:bc_ui/bc_ui.dart';
MaterialApp(
theme: BCTheme.light(),
darkTheme: BCTheme.dark(),
themeMode: ThemeMode.system,
// Only needed if you use BCToast:
builder: (context, child) => BCToastProvider(child: child!),
home: const HomeScreen(),
);
That's the whole setup — every component reads its colors from the
BCThemeExtension those two factories install.
Quick start #
// Buttons: 7 variants x 3 sizes
BCButton(
variant: BCButtonVariant.secondary,
onPressed: () {},
startContent: const Icon(Icons.add, size: 18),
child: const Text('Add item'),
);
// A frosted app header — pair with extendBodyBehindAppBar so there is
// something to blur. The hairline appears only once content scrolls under.
Scaffold(
extendBodyBehindAppBar: true,
appBar: BCAppHeader(
title: const Text('Inbox'),
subtitle: const Text('12 unread'),
actions: [
BCHeaderIconButton(icon: const Icon(Icons.search), onPressed: () {}),
],
),
body: ListView(children: const []),
);
// Swipeable tabs: the bar and the panels share one controller, so a drag
// switches tabs and carries the indicator with it.
final tabs = BCTabsController<String>(values: const ['music', 'podcasts']);
Column(
children: [
BCTabs(items: items, controller: tabs, fullWidth: true),
Expanded(
child: BCTabView(
controller: tabs,
children: const [MusicPanel(), PodcastsPanel()],
),
),
],
);
// Compound form field with built-in validation states
BCTextField(
isRequired: true,
children: [
const BCTextFieldLabel('Email'),
const BCTextFieldInput(hintText: 'you@example.com'),
const BCTextFieldDescription("We'll never share your email."),
],
);
// Toast
BCToast.show(context, const BCToastData(
title: 'Changes saved',
variant: BCToastVariant.success,
));
Components #
Full props, defaults and enums for every entry: API reference.
| Category | Components |
|---|---|
| Navigation | BCAppHeader · BCSliverAppHeader · BCHeaderIconButton · BCBottomNav · BCNavRail · BCNavDrawer · BCToolbar · BCTabs · BCTabView |
| Actions | BCButton · BCSocialAuthButton · BCBrandLogo · BCLinkButton · BCCloseButton · BCFab · BCSpeedDial · BCToggleButton · BCToggleButtonGroup · BCPressable |
| Containers | BCSurface · BCCard · BCListGroup · BCAccordion · BCFlipCard · BCScrollShadow |
| Data display | BCText · BCAvatar · BCChip · BCRibbon · BCTagGroup · BCSeparator · BCSkeleton · BCSpinner · BCProgress · BCLoadingOverlay · BCRating · BCEmptyState |
| Forms | BCInput · BCTextField · BCTextArea · BCPasswordInput · BCSearchField · BCInputOTP · BCDateField · BCTimeField · BCDateTimePicker · BCPhoneField · BCSelect · BCControlField |
| Selection | BCCheckbox · BCRadioGroup · BCSwitch · BCSlider · BCRangeSlider |
| Overlays | BCDialog · BCPopover · BCMenu · BCToast |
The three pickers — BCDateField, BCTimeField, BCDateTimePicker — share a
presentation prop (dialog, popover, bottomSheet), so swapping one for
another never changes how it opens.
Naming is predictable across the library: variant picks the look, size
picks the metrics, state is controlled (value + onValueChange), and
disabled/invalid are always isDisabled / isInvalid.
Theming #
Custom accent #
BCTheme.light(
overrides: BCThemeOverrides(accent: const Color(0xFF0F766E)),
);
Accent-derived tokens (hover, soft, soft-foreground, focus) are recomputed for you, so a single color change stays consistent everywhere.
Reading tokens in your own widgets #
final bc = context.bcTheme;
DecoratedBox(
decoration: ShapeDecoration(
color: bc.accentSoft,
shape: BCShapes.continuous(BCRadius.xxl),
shadows: bc.surfaceShadow.shadows,
),
);
Design tokens #
BCColorsLight/BCColorsDark (raw palettes) · BCRadius (2→32, field 14) ·
BCSpacing (4px unit) · BCTypography (tailwind text scale) · BCShadows
(layered surface/overlay shadows) · BCMotion (springs and timings) ·
BCShapes (continuous corners) · BCSizes · BCDuration · BCBreakpoints.
See Theme and tokens for the full list.
Example app #
example/ mirrors heroui-native's demo: a full demo screen plus one page per
component, each with vertically paged usage variants and a pagination rail.
cd example && flutter run
Using bc_ui with an AI agent #
The repo ships an agent skill that teaches Claude Code, Cursor, Copilot and friends to reach for the right component, pass real props, and read colors from the theme instead of hard-coding them.
npx skills add binary-castle/bc-ui-flutter
Or copy skills/bc-ui/ into your project's .claude/skills/ by hand — the
skill ships inside the published package too, so it is already in your pub
cache.
Its per-component references are generated by the same script that writes
doc/api.md, so they cannot drift from the source.
Documentation #
- API reference — every component, prop, default and enum. The prop tables are generated from the source, so they track the code.
dart docgenerates the full dartdoc site from the inline documentation.- Regenerate both the reference and the agent skill with
python3 tool/gen_api_doc.py;--checkfails if either is stale, and--check-coveragelists public symbols nothing documents. Run both before publishing.
Tests #
flutter test
License #
Apache-2.0 — see LICENSE.
bc_ui is a port of heroui-native (Apache-2.0, © NextUI Inc.), reimplemented in Dart against Flutter's widget layer. NOTICE records the attribution, how the port differs, and the bundled Inter font (OFL) and CC0 brand marks.

