bc_ui 0.4.0
bc_ui: ^0.4.0 copied to clipboard
A Flutter design system porting heroui-native 1:1 — 60+ token-driven components, light and dark, on a Material 3 base.
0.4.0 #
Phone field
BCPhoneField— an international phone input. The field's prefix is a tappable flag and dial code that opens the searchable country list, and the number groups itself as you type.- Leave
initialCountrynull and the field opens on the device's own region, the way a web form readsnavigator.language— a phone set to Bangladesh opens on Bangladesh.fallbackCountrycovers a device that reports no usable region (a bareenlocale, or a UN M.49 region likees_419), andBCPhoneField.deviceCountry()exposes the lookup for your own state. This is the phone's configured region, not where it physically is. - Validation is libPhoneNumber's metadata rather than a regex, so it knows
each country's real lengths and prefixes:
+1 555 000 0000is rejected where a digit count would pass it.onChangedhands back aBCPhoneNumberwithe164,national,international,isoCodeandisValidon every keystroke;onValidityChangedfires only when validity flips, so a submit button can be driven straight from it. - Nothing is blocked while you type — a half-typed number is not an error, so
the message waits for blur (or for a caller-supplied
errorText, which always wins).invalidNumberText: nullkeeps the field silent and reports through the callback only. - The country's trunk prefix is dropped as you type, because it is not part
of an international number: a UK number beside
+44is7400 123456, never07400 123456. - The picker is authoritative about the country.
+1covers 25 countries and no parser can tell a US number from a Canadian one, so whatever the user picks wins over what the metadata guesses. - This adds bc_ui's first runtime dependency,
phone_numbers_parser. It is pure Dart with no platform channels, and its own only dependency ismeta.
Select
triggerBuilderreplaces aBCSelect's trigger wholesale while keeping its press feedback, tap handling, disabled dimming and popover anchoring.matchTriggerWidth(defaulttrue, unchanged behaviour) stops a narrow custom trigger from squeezing the popover list to its own width.triggerFeedback(defaultBCPressFeedback.scale, unchanged behaviour) because the scale is width-compensated and pops harder on a small inline trigger than on the default one.
Input
autofillHintsonBCInput, forwarded to the underlying field. Without it the OS keychain and iOS's one-tap SMS code were unreachable.
0.3.0 #
Accordion
BCAccordionports heroui-native's Accordion: a column of collapsible sections, one open at a time or several withselectionMode: BCAccordionSelectionMode.multiple. Compose each section fromBCAccordionItem,BCAccordionTriggerandBCAccordionContent;variant: BCAccordionVariant.surfacewraps the stack in a rounded surface and insets the hairline separators, andhideSeparatordrops them.- State is yours: pass
value+onValueChange, or hand it aBCAccordionController— heroui's uncontrolleddefaultValueis that controller'sinitialValue.isCollapsible: falsekeeps whatever is open from closing. - Content springs open on heroui's layout-transition spring while it fades in over 200ms, and the chevron rotates counter-clockwise to match. The body is built on first expand and dropped once a collapse settles, so lift any state that lives inside it. Reduced-motion settings skip all three animations.
BCAccordionIndicatorrenders the chevron; give it achildto replace it, in which case it is not rotated for you — read the state withBCAccordionItem.isExpandedOf(context), the equivalent of heroui'suseAccordionItem()hook.
0.2.1 #
Speed dial
BCSpeedDialopens into the root overlay rather than the nearest one. Inside a nestedNavigator— a shell branch, a tab view — the nearest overlay covers only that screen's slot, so the backdrop stopped short of any surrounding chrome: a bottom navigation bar kept painting over the open dial, undimmed, and still took taps.
0.2.0 #
App header
filledIconButtonsonBCAppHeaderandBCSliverAppHeaderrenders everyBCHeaderIconButtonin the leading and actions slots filled, so a screen picks the style once instead of at each button. It reaches the back button the header implies, which no call site could style before.- Breaking:
BCHeaderIconButton.filledis nowbool?and defaults to null, which defers to the enclosing header (and to false where there is none). Passingfilled: trueorfilled: falseis unchanged and still wins over the header; only code that reads the field needs a null check. - The header's inherited style is now installed unconditionally. It used to
be skipped unless
foregroundColorwas set, so a header that only wanted the default colours had no channel to its buttons at all.
0.1.0 #
Select
- Three presentations: the anchored
popoverit always had, abottomSheetwith room for a long list, and awheelfor short ordered ones, committed with Done. Set withpresentation. - Search.
isSearchablefilters on label and description;onSearchreplaces that with your own lookup — debounced bysearchDebounce, awaited with a spinner, and rendered exactly as returned, so it can hit the network. - Pagination.
onLoadMorefires as the list nears its end, once per page;isLoadingMoreshows a spinner under the last row. - Rows take
leadingandtrailingwidgets, a per-itemonTapthat runs alongside the value change, andisDisabled.itemBuilderhands the whole row over, selection state included. emptyPlaceholderandmaxListHeightfor the rest.
The version jumps to 0.1.0 so ^0.1.0 resolves the way callers expect;
^0.0.x had pinned them to a single patch.
Agent skill
skills/bc-ui/teaches an AI agent to use the library — setup, the naming conventions, a routing table to per-category references, and the traps that fail silently. Install withnpx skills add binary-castle/bc-ui-flutter, or copy it into.claude/skills/; it ships in the package either way.- Its references come out of
tool/gen_api_doc.py, the same script that writesdoc/api.md, so they cannot drift.--checkfails when either is stale and--check-coveragelists public symbols nothing documents.
Fixes
- The generated prop tables dropped every named parameter of a constructor that
led with a positional one, so
BCTextwas documented as taking onlydata, andBCLabel,BCDescription,BCFieldErrorandBCTextFieldLabelwere each missing their flags.BCTextFieldError's argument was listed astextwhen it ismessage. All now generated correctly, along with the previously undocumentedBCTextWeight,BCInputOTPSlot*,BCSkeleton*Animation,BCNavDrawerItemandBCAnchoredOverlayController. - The README's License section still said the license was a placeholder, left over from before the package was licensed. It now states Apache-2.0 and credits heroui-native. pub.dev's own metadata was already correct.
0.0.2 #
- Fixed the README on pub.dev: images and repository links are absolute now.
pub.dev strips raw
<img>tags and drops repo-relative links, so the banner, the light/dark screenshots and every entry in the component table rendered without them. - Install instructions now point at the published package rather than a local path dependency.
0.0.1 #
First release — a Flutter port of heroui-native, covering 50+ components on a Material 3 base.
Foundation
BCTheme.light()/BCTheme.dark()return aThemeData, so Material widgets keep working alongside bc_ui.- 64 semantic colour tokens in
BCThemeExtension, precomputed from heroui-native's oklch sources including everycolor-mixderived hover and soft shade.BCThemeOverridesrecomputes the accent-derived tokens from a single colour. - Continuous (squircle) corners via
RoundedSuperellipseBorder, layered surface and overlay shadows, and the ported motion constants inBCMotion. - Inter is bundled; no font setup.
Components
- Navigation —
BCAppHeader,BCSliverAppHeader,BCBottomNav,BCNavRail,BCNavDrawer,BCToolbar,BCTabswith a swipeableBCTabView. - Actions —
BCButton,BCSocialAuthButton(10 providers, vector brand marks, no assets),BCLinkButton,BCCloseButton,BCFab,BCSpeedDial,BCToggleButton, and theBCPressablefeedback engine. - Containers and data display —
BCSurface,BCCard,BCListGroup,BCFlipCard,BCScrollShadow,BCAvatar,BCChip,BCRibbon,BCTagGroup,BCSkeleton,BCSpinner,BCProgress,BCLoadingOverlay,BCRating,BCEmptyState. - Forms and selection —
BCInput,BCTextField,BCTextArea,BCPasswordInput,BCSearchField,BCInputOTP,BCDateField,BCTimeField,BCDateTimePicker,BCSelect,BCControlField,BCCheckbox,BCRadioGroup,BCSwitch,BCSlider,BCRangeSlider. - Overlays —
BCDialog,BCPopover,BCMenu, andBCToastwith top/bottom placement and an interactive swipe-to-dismiss.
Full prop tables in doc/api.md; the example app has one screen per component.