Screens / auth
Sign in
Lets people sign in with email and password or an identity provider, with forgotten password, rejected credentials, offline and the wait after too many attempts.
Import
Sign in is part of Fliin Pro. With a license key, sign in once with fliin login, then add it in a Flutter app where fliin init has run:
fliin login
fliin add sign-inAlso installs: core, alert, auth-form, auth-header, button, link-button, page, social-sign-in, text-field, icons
Examples
Brand
Your brand on the screen: your logo above the title, and the providers first, their logos side by side, for an app whose users mostly sign in through one. title and subtitle replace the screen's texts when you pass them.
import 'package:your_app/ui/fliin/components/social_sign_in/fl_social_sign_in.dart';
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/icons/fl_icons.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInBrandExample extends StatelessWidget {
const SignInBrandExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: const SignInReady(),
mark: FlIcon(FlIcons.starFill),
providersLayout: FlSocialSignInLayout.row,
providersFirst: true,
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Ready
The sign-in form, with a button per provider above it. standalone holds its own controller over the service you pass; implement SignInService to reach your backend.
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInReadyExample extends StatelessWidget {
const SignInReadyExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: const SignInReady(),
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Sending
While the service checks the credentials, the button shows its spinner and the fields stay put.
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInSendingExample extends StatelessWidget {
const SignInSendingExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: const SignInSending(),
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Rejected
Wrong credentials: an alert above the form says so, without saying which of the two was wrong.
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInRejectedExample extends StatelessWidget {
const SignInRejectedExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: const SignInReady(problem: SignInProblem.rejected),
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Offline
Without a connection, the alert asks to reconnect and the form stays filled in.
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInOfflineExample extends StatelessWidget {
const SignInOfflineExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: const SignInReady(problem: SignInProblem.offline),
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Throttled
After too many attempts, the form waits: the alert counts down until the time the service gave.
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInThrottledExample extends StatelessWidget {
const SignInThrottledExample({super.key});
@override
Widget build(BuildContext context) {
return SignInScreen.standalone(
service: const SampleSignInService(latency: Duration(milliseconds: 600)),
initial: SignInThrottled(DateTime.now().add(const Duration(seconds: 45))),
providers: [
for (final provider in sampleSignInProviders) (provider: provider, icon: _Monogram(provider.name)),
],
onForgotPassword: () {},
onSignUp: () {},
);
}
}
/// Stands in for a provider's logo until the app puts in the official one:
/// its initial in a square, at the size and color of the icon.
class _Monogram extends StatelessWidget {
const _Monogram(this.name);
final String name;
@override
Widget build(BuildContext context) {
final icon = IconTheme.of(context);
final theme = FlScope.of(context);
final size = icon.size!;
return ExcludeSemantics(
child: SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: FlContinuousBorder(
radius: theme.shape.radiusXs,
side: BorderSide(color: icon.color!, width: theme.size.border),
),
),
child: Center(
child: Text(
name[0].toUpperCase(),
textScaler: TextScaler.noScaling,
style: TextStyle(
color: icon.color,
fontSize: size * 0.6,
height: 1,
fontWeight: theme.tokens.typography.weight.semibold,
),
),
),
),
),
);
}
}Routing
fliin add sign-in prints the route for the router it finds in your pubspec, a file next to the page that wires its navigation. Each of them:
go_router
// lib/sign_in_route.dart, next to sign_in_page.dart.
import 'package:go_router/go_router.dart';
import 'sign_in_page.dart';
/// Add signInRoute to the routes of your GoRouter.
final signInRoute = GoRoute(
path: '/sign-in',
builder: (context, state) => SignInPage(
// '/': your app's home.
onSignedIn: () => context.go('/'),
onForgotPassword: () => context.push('/forgot-password'),
onSignUp: () => context.push('/sign-up'),
),
);navigator
// lib/sign_in_route.dart, next to sign_in_page.dart.
import 'package:flutter/material.dart';
import 'forgot_password_route.dart';
import 'sign_in_page.dart';
import 'sign_up_route.dart';
/// Opens “Sign in”: `Navigator.of(context).push(signInRoute(homePage: …))`.
/// [homePage] builds your app's home.
Route<void> signInRoute({required WidgetBuilder homePage}) => MaterialPageRoute<void>(
builder: (context) => SignInPage(
onSignedIn: () => Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute<void>(builder: homePage), (_) => false),
onForgotPassword: () => Navigator.of(context).push(forgotPasswordRoute()),
onSignUp: () => Navigator.of(context).push(signUpRoute(homePage: homePage)),
),
);State
The controller is a ChangeNotifier from widgets.dart, with no package. fliin add sign-in prints the page that holds it with the state management it finds, its imports written for your package; below they read your_app. Your backend implements the Service interface of the screen's _data.dart file:
none
// lib/sign_in_page.dart
// Your backend: implement SignInService (sign_in_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
class SignInPage extends StatelessWidget {
const SignInPage({
super.key,
required this.onSignedIn,
required this.onForgotPassword,
required this.onSignUp,
});
final VoidCallback onSignedIn;
final VoidCallback onForgotPassword;
final VoidCallback onSignUp;
@override
Widget build(BuildContext context) => SignInScreen.standalone(
service: const SampleSignInService(),
onSignedIn: onSignedIn,
onForgotPassword: onForgotPassword,
onSignUp: onSignUp,
);
}provider
// lib/sign_in_page.dart
// Your backend: implement SignInService (sign_in_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
class SignInPage extends StatelessWidget {
const SignInPage({
super.key,
required this.onSignedIn,
required this.onForgotPassword,
required this.onSignUp,
});
final VoidCallback onSignedIn;
final VoidCallback onForgotPassword;
final VoidCallback onSignUp;
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (_) => SignInController(service: const SampleSignInService()),
child: Builder(
builder: (context) => SignInScreen(
controller: context.read<SignInController>(),
onSignedIn: onSignedIn,
onForgotPassword: onForgotPassword,
onSignUp: onSignUp,
),
),
);
}riverpod
// lib/sign_in_page.dart
// Your backend: implement SignInService (sign_in_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final signInControllerProvider = Provider.autoDispose<SignInController>((ref) {
final controller = SignInController(service: const SampleSignInService());
ref.onDispose(controller.dispose);
return controller;
});
class SignInPage extends ConsumerWidget {
const SignInPage({
super.key,
required this.onSignedIn,
required this.onForgotPassword,
required this.onSignUp,
});
final VoidCallback onSignedIn;
final VoidCallback onForgotPassword;
final VoidCallback onSignUp;
@override
Widget build(BuildContext context, WidgetRef ref) => SignInScreen(
controller: ref.watch(signInControllerProvider),
onSignedIn: onSignedIn,
onForgotPassword: onForgotPassword,
onSignUp: onSignUp,
);
}bloc
// lib/sign_in_page.dart
// Your backend: implement SignInService (sign_in_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_controller.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_data.dart';
import 'package:your_app/ui/fliin/screens/sign_in/sign_in_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
/// The screen's controller as a bloc, for your BlocListener and BlocBuilder:
/// one emission per controller notification. `version` tells them apart
/// when `state` does not change (mode, filters, text…, read them on
/// `controller`). The screen listens to the controller itself.
class SignInCubit extends Cubit<({SignInState state, int version})> {
SignInCubit(this.controller) : super((state: controller.state, version: 0)) {
controller.addListener(_changed);
}
final SignInController controller;
void _changed() => emit((state: controller.state, version: state.version + 1));
@override
Future<void> close() {
controller
..removeListener(_changed)
..dispose();
return super.close();
}
}
class SignInPage extends StatelessWidget {
const SignInPage({
super.key,
required this.onSignedIn,
required this.onForgotPassword,
required this.onSignUp,
});
final VoidCallback onSignedIn;
final VoidCallback onForgotPassword;
final VoidCallback onSignUp;
@override
Widget build(BuildContext context) => BlocProvider(
create: (_) => SignInCubit(SignInController(service: const SampleSignInService())),
child: Builder(
builder: (context) => SignInScreen(
controller: context.read<SignInCubit>().controller,
onSignedIn: onSignedIn,
onForgotPassword: onForgotPassword,
onSignUp: onSignUp,
),
),
);
}The snippets lead to forgot-password, sign-up: install these screens too and paste their snippets.
API
SignInScreen: class extends StatefulWidget
SignInScreen.new: const new({super.key, required SignInController controller, List<({SignInProvider provider, Widget icon})> providers, Widget? mark, String? title, String? subtitle, FlSocialSignInLayout providersLayout, bool providersFirst, VoidCallback? onSignedIn, VoidCallback? onForgotPassword, VoidCallback? onSignUp})
SignInScreen.standalone: const new({super.key, required SignInService service, SignInState? initial, DateTime Function()? now, List<({SignInProvider provider, Widget icon})> providers, Widget? mark, String? title, String? subtitle, FlSocialSignInLayout providersLayout, bool providersFirst, VoidCallback? onSignedIn, VoidCallback? onForgotPassword, VoidCallback? onSignUp})
SignInScreen.controller: get SignInController?
SignInScreen.service: get SignInService?
SignInScreen.initial: get SignInState?
SignInScreen.now: get DateTime Function()?
SignInScreen.providers: get List<({SignInProvider provider, Widget icon})>
SignInScreen.mark: get Widget?
SignInScreen.title: get String?
SignInScreen.subtitle: get String?
SignInScreen.providersLayout: get FlSocialSignInLayout
SignInScreen.providersFirst: get bool
SignInScreen.onSignedIn: get VoidCallback?
SignInScreen.onForgotPassword: get VoidCallback?
SignInScreen.onSignUp: get VoidCallback?
SignInScreen.createState: State<SignInScreen>()
SignInProblem: enum {rejected, offline, failed}
SignInProblem.rejected: static final SignInProblem
SignInProblem.offline: static final SignInProblem
SignInProblem.failed: static final SignInProblem
SignInState: sealed class permits {SignInDone, SignInReady, SignInSending, SignInThrottled}
SignInState.new: const new()
SignInReady: final class extends SignInState
SignInReady.new: const new({SignInProblem? problem})
SignInReady.problem: get SignInProblem?
SignInSending: final class extends SignInState
SignInSending.new: const new({SignInProvider? provider})
SignInSending.provider: get SignInProvider?
SignInThrottled: final class extends SignInState
SignInThrottled.new: const new(DateTime until)
SignInThrottled.until: get DateTime
SignInDone: final class extends SignInState
SignInDone.new: const new()
SignInController: class extends ChangeNotifier
SignInController.new: new({required SignInService service, SignInState initial, DateTime Function()? now})
SignInController.service: get SignInService
SignInController.state: get SignInState
SignInController.wait: get Duration?
SignInController.tick: void()
SignInController.signIn: Future<bool>(SignInCredentials credentials)
SignInController.signInWith: Future<bool>(SignInProvider provider)
SignInController.dispose: void()
SignInProvider: final class
SignInProvider.new: const new({required String id, required String name})
SignInProvider.id: get String
SignInProvider.name: get String
SignInProvider.toString: String()
SignInCredentials: final class
SignInCredentials.new: const new({required String email, required String password})
SignInCredentials.email: get String
SignInCredentials.password: get String
SignInCredentials.toString: String()
SignInEmailIssue: enum {missing, malformed}
SignInEmailIssue.missing: static final SignInEmailIssue
SignInEmailIssue.malformed: static final SignInEmailIssue
signInEmailIssue: SignInEmailIssue?(String email)
SignInRejected: final class implements Exception
SignInRejected.new: const new()
SignInNoNetwork: final class implements Exception
SignInNoNetwork.new: const new()
SignInTooManyAttempts: final class implements Exception
SignInTooManyAttempts.new: const new(Duration retryAfter)
SignInTooManyAttempts.retryAfter: get Duration
SignInService: abstract interface class
SignInService.new: new()
SignInService.signIn: abstract Future<void>(SignInCredentials credentials)
SignInService.signInWith: abstract Future<void>(SignInProvider provider)
sampleSignInProviders: const dynamic
SampleSignInService: final class implements SignInService
SampleSignInService.new: const new({Duration latency})
SampleSignInService.latency: get Duration
SampleSignInService.signIn: Future<void>(SignInCredentials credentials)
SampleSignInService.signInWith: Future<void>(SignInProvider provider)
signInL10n: const Map<String, Map<String, String>>
SignInStrings: final class
SignInStrings.new: const new(String language)
SignInStrings.of: factory new(BuildContext context)
SignInStrings.language: get String
SignInStrings.title: get String
SignInStrings.subtitle: get String
SignInStrings.email: get String
SignInStrings.emailPlaceholder: get String
SignInStrings.password: get String
SignInStrings.showPassword: get String
SignInStrings.hidePassword: get String
SignInStrings.showPasswordLabel: get String
SignInStrings.hidePasswordLabel: get String
SignInStrings.forgot: get String
SignInStrings.submit: get String
SignInStrings.retryIn: String(Duration wait)
SignInStrings.or: get String
SignInStrings.continueWith: String(String provider)
SignInStrings.noAccount: get String
SignInStrings.signUp: get String
SignInStrings.emailMissing: get String
SignInStrings.emailMalformed: get String
SignInStrings.passwordMissing: get String
SignInStrings.rejectedTitle: get String
SignInStrings.rejectedMessage: get String
SignInStrings.offlineTitle: get String
SignInStrings.offlineMessage: get String
SignInStrings.failedTitle: get String
SignInStrings.failedMessage: get String
SignInStrings.throttledTitle: get String
SignInStrings.throttledMessage: get StringStrings
Every label in English, French and Arabic. The screen follows the closest Localizations; the same table is in the manifest, ready for your ARB files.
| Key | en | fr | ar |
|---|---|---|---|
signInTitle | Sign in | Connexion | تسجيل الدخول |
signInSubtitle | Welcome back. Enter your details to continue. | Bon retour. Entrez vos identifiants pour continuer. | مرحبًا بعودتك. أدخل بياناتك للمتابعة. |
signInEmail | Adresse e-mail | البريد الإلكتروني | |
signInEmailPlaceholder | [email protected] | [email protected] | [email protected] |
signInPassword | Password | Mot de passe | كلمة المرور |
signInShowPassword | Show | Afficher | إظهار |
signInHidePassword | Hide | Masquer | إخفاء |
signInShowPasswordLabel | Show password | Afficher le mot de passe | إظهار كلمة المرور |
signInHidePasswordLabel | Hide password | Masquer le mot de passe | إخفاء كلمة المرور |
signInForgot | Forgot password? | Mot de passe oublié ? | هل نسيت كلمة المرور؟ |
signInSubmit | Sign in | Se connecter | تسجيل الدخول |
signInRetryIn | Try again in {time} | Réessayer dans {time} | أعد المحاولة بعد {time} |
signInOr | or | ou | أو |
signInContinueWith | Continue with {provider} | Continuer avec {provider} | المتابعة باستخدام {provider} |
signInNoAccount | No account yet? | Pas encore de compte ? | ليس لديك حساب؟ |
signInSignUp | Create one | Créer un compte | أنشئ حسابًا |
signInEmailMissing | Enter your email. | Saisissez votre adresse e-mail. | أدخل بريدك الإلكتروني. |
signInEmailMalformed | Enter an email such as [email protected]. | Saisissez une adresse comme [email protected]. | أدخل بريدًا مثل [email protected]. |
signInPasswordMissing | Enter your password. | Saisissez votre mot de passe. | أدخل كلمة المرور. |
signInRejectedTitle | Email or password is incorrect | Adresse ou mot de passe incorrect | البريد الإلكتروني أو كلمة المرور غير صحيحة |
signInRejectedMessage | Check them and try again, or reset your password. | Vérifiez-les et réessayez, ou réinitialisez votre mot de passe. | تحقق منهما وأعد المحاولة، أو أعد تعيين كلمة المرور. |
signInOfflineTitle | You are offline | Vous êtes hors ligne | أنت غير متصل |
signInOfflineMessage | Check your connection, then try again. | Vérifiez votre connexion, puis réessayez. | تحقق من اتصالك ثم أعد المحاولة. |
signInFailedTitle | Sign-in failed | La connexion a échoué | تعذّر تسجيل الدخول |
signInFailedMessage | Something went wrong on our side. Try again in a moment. | Un problème est survenu de notre côté. Réessayez dans un instant. | حدثت مشكلة من جهتنا. أعد المحاولة بعد قليل. |
signInThrottledTitle | Too many attempts | Trop d’essais | محاولات كثيرة جدًا |
signInThrottledMessage | For your security, sign-in is paused for a moment. | Par sécurité, la connexion est suspendue un instant. | حفاظًا على أمانك، أُوقف تسجيل الدخول مؤقتًا. |
Reference renders
The 16 images published with version 0.2.4, rendered by the shared harness on macOS with Flutter 3.47.7. Each shows every state side by side, at the size of an iPhone (390 × 844) or of an Android phone (412 × 915). fliin verify sign-in compares your copy to them.
















Use it to
- let users sign in with their email and password
- offer sign in with Apple or Google next to the form
- show that the email or password was rejected at sign in
- make users wait after too many sign in attempts, with a countdown
- let the password manager autofill the sign in form
- present a login page with email, password and a Google button
- Not for
- creating an account: use the sign-up screen (sign-up)
- resetting a forgotten password: use the forgot password screen (forgot-password)
- an access form in an existing screen: use the access form block (auth-form)
- States