Flutter · colveor_ui

Widgets

Every widget is styled by your theme. Import each group from package:colveor_ui/widgets/<group>.dart.

Buttons

widgets/buttons.dart

Dart
VoButton(label: 'Continue', onPressed: submit);
VoButton(label: 'Delete', variant: VoButtonVariant.danger, onPressed: delete);
VoButton(label: 'Saving', isLoading: true, onPressed: null);

VoIconButton(icon: const Icon(Icons.share), label: 'Share', onPressed: share);
NameDescription
VoButtonlabel, onPressed, variant (primary, secondary, outline, text, danger), isLoading, isFullWidth (default true), prefixIcon, suffixIcon, height, colors, margin.
VoIconButtonicon, onPressed, optional label underneath, tooltip, color, size.

Inputs

widgets/inputs.dart

Text inputs share a VoFieldOptions object (label, hint, helper and error text, icons, keyboard type, input action, max lines/length, enabled, read-only, and labelBehavior: auto, floating, external or none).

Dart
VoInputField(
  options: const VoFieldOptions(label: 'Email', keyboardType: TextInputType.emailAddress),
  validator: VoValidators.email,
  controller: emailController,
);

VoPasswordField(
  options: const VoFieldOptions(label: 'Password'),
  validator: VoValidators.password,
);

VoSearchField(onChanged: (query) => search(query)); // debounced, 400ms

VoPhoneInput

Dart
VoPhoneInput(
  layout: VoPhoneInputLayout.integrated, // or split, stacked
  initialCountryCode: 'NG',
  onChanged: (country, phone, parsed) {
    final e164 = parsed?.fullNumber;
  },
)

A country picker plus digit-only number field. It parses the number as you type (passing a PhoneParseResult), accepts a full number as initialValue, and writes the composed number into controller. The country list comes from VoConfig.initialCountryCode and favoriteCountries.

VoPinInput & VoKeyboard

Dart
VoPinInput(
  length: 6,
  errorText: error,
  isLoading: verifying,
  onCompleted: (code) => verify(code),
);

VoKeyboard(maxLength: 4, controller: pinController, onSubmit: confirmPin);

VoKeyboard is an on-screen number pad (1–9, an optional action key, 0 and backspace).

VoSelectField

Dart
VoSelectField<String, String>(
  options: const VoFieldOptions(label: 'Fruit'),
  overlayOptions: VoOverlayOptions.singleSelect(
    title: 'Pick a fruit',
    items: ['Apple', 'Banana', 'Cherry'],
  ),
  onChanged: (fruit) => setState(() => selected = fruit),
)

Opens an overlay on tap. Use VoOverlayOptions.multiSelect for List<T> results.

Form helpers

VoFormGroup and VoFormControl keep a map of controls (label, hint, validator, keyboard type, password flag, initial value) with their own controllers: initState(), getControl(key), setValue, updateControl and dispose().

Display

widgets/display.dart

Dart
VoText(
  'By continuing you agree to our [Terms] and [Privacy Policy].',
  onTap: (index, text) => index == 0 ? openTerms() : openPrivacy(),
);
NameDescription
VoTextRich text where each [bracketed] span is a tappable link. Styled with VoTextStyle.
VoAvatarNetwork image or initials, with an optional online dot.
VoCounterBadgeA count badge over any icon (maxCount 99, showZero).
VoCounterTextA number that animates when it changes.
VoCountryFlagA flag by country code: circle, roundedRect or rect.
VoDividerDashed or solid divider, optionally with a text label.

Feedback

widgets/feedback.dart

Toasts

Dart
VoToast.error(context: context, message: 'Something went wrong');
VoToast.banner(message: 'You are offline', type: VoToastType.warning);

final id = VoToast.show(
  message: 'Uploading…',
  title: 'Please wait',
  style: VoToastStyle.snackBar,
  position: VoToastPosition.top,
);
VoToast.dismissById(id);

Toasts stack (up to three) and work without a context by falling back to the root navigator. Helpers: success, error, warning, info, banner, show, and dismissById / dismissFirst / dismissLast / dismissAll. Reusing a toastId replaces that toast. Inside screens, prefer the showSuccessToast-style helpers from base screens.

VoFeedbackView

Dart
VoFeedbackView.empty('No orders yet', 'Orders you place will show up here.');
VoFeedbackView.offline('You are offline', 'Check your connection and try again.');

VoFeedbackView.custom(
  title: 'Almost there',
  description: 'Verify your email to continue.',
  icon: const Icon(Icons.mail_outline),
  actionBuilder: VoButton(label: 'Resend email', onPressed: resend),
);

Full-area states: error, offline, noResults, empty, unauthorized, forbidden, maintenance, notFound and custom.

VoCountdownAction

Dart
VoCountdownAction(
  prefixText: "Didn't receive a code?",
  actionText: 'Resend',
  countdownPrefixText: 'Resend in',
  duration: const Duration(seconds: 30),
  onPressed: () async => resendOtp(),
)

Restart it through a GlobalKey<VoCountdownActionState> and restart().

Layout

widgets/layout.dart

NameDescription
VoScaffoldScaffold with themed body padding (sizes.md by default) and a VoScaffoldStyle for colors, drawers and system UI overlay style.
VoAppBar.fromStyleBuilds an AppBar from a VoAppBarStyle, with title, leading and actions.
VoScrollableFormA scrollable column that fills the viewport, with header, footer, spacing and keyboard dismissal on drag.
VoTileView / VoTileLists or rows of selectable tiles with active-state styling (VoTileStyle, VoRowTileStyle).
Dart
VoScaffold(
  appBar: VoAppBar.fromStyle(const VoAppBarStyle(), title: 'Sign in'),
  body: VoScrollableForm(
    footer: VoButton(label: 'Continue', onPressed: submit),
    children: [emailField, passwordField],
  ),
)

Overlays

widgets/overlay.dart

Dart
final fruit = await showVoOverlay<String, String>(
  context,
  type: VoOverlayType.dialog, // bottomSheet (default), dialog or modal
  options: VoOverlayOptions.singleSelect(
    title: 'Pick one',
    items: ['Apple', 'Banana'],
    itemTile: VoOverlayTile(title: (s) => s),
    onSearch: (query, items) => items
        .where((i) => i.toLowerCase().contains(query.toLowerCase()))
        .toList(),
  ),
);
NameDescription
VoOverlayOptions.builderAny custom content, with optional title, heading and footer.
VoOverlayOptions.singleSelectA searchable list that returns the tapped item. Supports favoriteItems, itemsAsStream and selectedItem.
VoOverlayOptions.multiSelectReturns List<T> on confirm. Options: selectedItems, minSelection, maxSelection, confirmLabel, clearLabel.
VoOverlayTileHow each item renders: title, subtitle, or leading / title / trailing builders.
VoBottomSheetOptionsinitialChildSize 0.5, minChildSize 0.25, maxChildSize 0.9, canFullHeight.

Search appears only when onSearch is set; favorites are listed first.

Page flow

widgets/page_flow.dart

A multi-step flow inside one screen, with its own history and animated transitions.

Dart
final flow = VoPageFlowController(initialPageKey: 'phone');

VoPageFlowView(
  controller: flow,
  theme: const VoPageFlowTheme(transition: VoPageFlowTransition.slideFade),
  pages: [
    VoPage(key: 'phone', builder: (_) => PhoneStep(onNext: () => flow.goToPage('otp'))),
    VoPage(key: 'otp', builder: (_) => const OtpStep(), canLeave: () => !verifying),
  ],
);
NameDescription
ControllergoToPage, replace, back, reset; currentKey, history, canGoBack. Each call returns success, alreadyCurrent, blocked or pageNotFound.
VoPagekey, builder, canLeave (return false to block), onEnter, onExit.
Transitionsnone, fade, scale, slide, slideFade — or a custom transitionBuilder.
VoPageFlowScope.of(context)The controller, from inside a page.

Dashboard

widgets/dashboard.dart

The signed-in shell: app bar, bottom dock, drawer and end drawer, with its own pane history and back handling.

Dart
VoDashboard(
  initialPaneKey: 'home',
  dockPanes: [
    VoDashboardPane.dock(
      key: 'home',
      title: 'Home',
      iconData: Icons.home_outlined,
      builder: (context, pane) => const HomePane(),
    ),
    VoDashboardPane.spacer(),
    VoDashboardPane.dock(
      key: 'explore',
      title: 'Explore',
      iconData: Icons.explore_outlined,
      builder: (context, pane) => const ExplorePane(),
    ),
  ],
  drawerPanes: [
    VoDashboardPane.divider(title: 'Account'),
    VoDashboardPane.drawer(
      key: 'profile',
      title: 'Profile',
      iconData: Icons.person_outline,
      builder: (context, pane) => const ProfilePane(),
    ),
    VoDashboardPane.stickyBottom(
      key: 'sign-out',
      title: 'Sign out',
      iconData: Icons.logout,
      onPressed: (context, pane) => signOut(),
    ),
  ],
  onPaneChanged: (key) => analytics.screen(key),
)
NameDescription
Pane typesdock, drawer, endDrawer, stickyBottom (pinned at the drawer bottom), divider and spacer.
Per-pane optionsshowAppBar, showDock, showDrawer, showEndDrawer, showFloatingActionButton, floatingActionButtonBuilder, appBarActionsBuilder, appBarLeadingBuilder, onPressed (replaces navigation).
context.dashboardScopegoTo(key), openDrawer / closeDrawer, openEndDrawer / closeEndDrawer, handleBack.
Back buttonCloses an open drawer, then goes back through pane history, then pops the route.
StylingVoDashboardTheme via componentTheme.dashboard or the style parameter.