kh_screens¶
Composed, opinionated full-screen patterns (splash, onboarding, login)
for khflutterlib-based apps, built on kh_ui/kh_theme/
kh_core.
See PHASE_0_ARCHITECTURE.md §17 for the
customization principle every screen here follows, and the root
README.md for how this package fits into the workspace.
Status¶
Available. Version 0.1.1+8, shipped in release train khflutterlib-v0.4.3.
Exports:
KhSplashScreen— a themed cold-start screen: a centeredlogoslot, an optional asyncinitializecallback run while the screen is showing, aminimumDisplayDuration, and a requiredonInitializationCompletecallback the app uses to navigate onward — no router dependency assumed.KhOnboardingFlow/KhOnboardingPage— a swipeable, dot-indicated carousel of illustration + title + description slides, with a skip action and a "Get started" button on the last slide.KhLoginForm— the fields of a login screen (email, password with a visibility toggle, optional "remember me" and "forgot password"), with validation and a loading submit button. You supply the surrounding screen.
None of these depend on a router or state-management package: each one reports back through a callback and leaves navigation to you.
Example app¶
Demos for this package live in the workspace's shared gallery app at
packages/example, alongside kh_ui's own component gallery — not in a
separate kh_screens-only example:
Usage¶
dependencies:
kh_screens:
git:
url: https://github.com/msflib/flutter.git
path: packages/kh_screens
ref: khflutterlib-v0.4.3 # use the same release tag for every kh_* package
Splash screen¶
import 'package:kh_screens/kh_screens.dart';
KhSplashScreen(
logo: Image.asset('assets/logo.png', width: 140),
initialize: () => sessionRepository.restore(),
onInitializationComplete: () =>
Navigator.of(context).pushReplacementNamed('/home'),
);
initialize and the minimumDisplayDuration wait (default 1.5s) run
concurrently, not sequentially — the screen stays up for
max(minimumDisplayDuration, however long initialize takes), not the sum
of both. backgroundColor defaults to
Theme.of(context).scaffoldBackgroundColor, so it stays correct under a
consuming app's custom seedColor or KhTheme.dark().
Errors from initialize aren't caught by KhSplashScreen itself — wrap
your own initialize in a try/catch and decide the outcome before calling
back through onInitializationComplete.
Onboarding flow¶
KhOnboardingFlow(
pages: const [
KhOnboardingPage(
illustration: Icon(Icons.track_changes, size: 120),
title: 'Track everything in one place',
description: 'Never miss an update from order to delivery.',
),
KhOnboardingPage(
illustration: Icon(Icons.notifications_active, size: 120),
title: 'Stay in the loop',
description: 'Get notified the moment something changes.',
),
],
onComplete: () async {
await onboardingRepository.markComplete();
if (context.mounted) {
Navigator.of(context).pushReplacementNamed('/login');
}
},
);
illustration is any Widget (an Image.asset, an Icon, an SVG from
your own flutter_svg dependency). onComplete is a
Future<void> Function() and is the only way the flow finishes. It runs
from the "Get started" button on the last slide and from "Skip" on the
others. While it's running, both buttons show a loading state so it can't
be triggered twice. With nothing async to do, return
Future<void>.value().
showSkip (default true), skipLabel ('Skip'), getStartedLabel
('Get started') and backgroundColor customize the chrome.
Login form¶
KhLoginForm is just the form. Put it in your own Scaffold with
whatever header, links and error display your app needs:
Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: KhLoginForm(
onSubmit: (email, password, rememberMe) async {
await authRepository.login(email, password);
if (context.mounted) {
Navigator.of(context).pushReplacementNamed('/home');
}
},
onForgotPassword: () =>
Navigator.of(context).pushNamed('/reset-password'),
),
),
),
);
- Validation runs on submit. By default the email must be non-empty
and match
kh_core'sKhRegex.email, and the password must be non-empty. PassemailValidator/passwordValidator(for exampleKhValidators.minLength(8)fromkh_utils) for stricter rules. onSubmitisFuture<void> Function(String email, String password, bool rememberMe). While it's pending, the fields are disabled and the submit button shows a spinner.- Errors from
onSubmitaren't caught. Catch them inside your ownonSubmitand show them however you like (aKhSnackbar, an inline message). - The "Forgot password?" link only appears when
onForgotPasswordis set.showRememberMe(defaulttrue) andinitialRememberMecontrol the checkbox. Every label (emailLabel,passwordLabel,submitLabel, ...) and theemailHint/passwordHintcan be overridden.