Files
shaynee-flutter/lib/screens/intro_screen.dart
mav 6311088256 redesign: duolingo-pattern onboarding, no gradient, pressable button
- Nunito font replacing Plus Jakarta Sans
- SButton: Stack-based 3D pressable (dark shadow layer + top layer translates on press)
- SCard: flat border-based selection, no shadows
- SProgressBar: 4px thin bar, animated fill
- All screens: white bg, no gradients
- Duolingo layout: illustration top zone, content below, sticky button
2026-05-28 16:34:04 +02:00

216 lines
6.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import '../theme.dart';
import '../widgets/s_button.dart';
import 'quiz/quiz_flow.dart';
class IntroScreen extends StatelessWidget {
const IntroScreen({super.key});
void _start(BuildContext context) {
Navigator.of(context).push(PageRouteBuilder(
pageBuilder: (_, a, __) => const QuizFlow(),
transitionsBuilder: (_, a, __, child) => SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(CurvedAnimation(parent: a, curve: Curves.easeOut)),
child: child,
),
transitionDuration: const Duration(milliseconds: 300),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: SColors.bgSurface,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Illustration zone (top 42%)
Expanded(
flex: 42,
child: _illustrationZone()
.animate()
.fadeIn(duration: 500.ms),
),
// Content zone (bottom 58%)
Expanded(
flex: 58,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
// Trust badge
_badge()
.animate()
.fadeIn(duration: 400.ms, delay: 150.ms),
const SizedBox(height: 16),
// Headline
Text(
'Skin that glows,\nroutine that works.',
style: SText.headline2(SColors.textHead),
)
.animate()
.fadeIn(duration: 400.ms, delay: 200.ms)
.slideY(begin: 0.06, end: 0, duration: 400.ms),
const SizedBox(height: 10),
// Sub
Text(
'Answer 5 quick questions and get your\npersonalised skincare plan in 60 seconds.',
style: SText.subtitle(SColors.textSub),
)
.animate()
.fadeIn(duration: 400.ms, delay: 280.ms),
const Spacer(),
// Stats row
_statsRow()
.animate()
.fadeIn(duration: 400.ms, delay: 360.ms),
const SizedBox(height: 24),
// CTA button
SButton(
label: 'GET STARTED',
onTap: () => _start(context),
)
.animate()
.fadeIn(duration: 400.ms, delay: 440.ms)
.slideY(begin: 0.1, end: 0, duration: 400.ms),
const SizedBox(height: 16),
// Sign in link (plain text, no button)
Center(
child: GestureDetector(
onTap: () {},
child: Text(
'Already have an account? Sign in',
style: SText.caption(SColors.textSub),
),
),
)
.animate()
.fadeIn(duration: 400.ms, delay: 500.ms),
const SizedBox(height: 20),
],
),
),
),
],
),
),
);
}
Widget _illustrationZone() {
return Stack(
children: [
// Light tinted background for art area
Container(color: const Color(0xFFF7F5FF)),
// Stats visual — abstract feature cards
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_featureChip(Icons.auto_awesome_rounded, 'AI skin analysis'),
const SizedBox(height: 10),
_featureChip(Icons.science_rounded, 'Ingredient science'),
const SizedBox(height: 10),
_featureChip(Icons.lock_outline_rounded, 'Private & secure'),
],
),
),
],
);
}
Widget _featureChip(IconData icon, String label) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: SColors.bgSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: SColors.borderLight, width: 1.5),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, color: SColors.primary, size: 20),
const SizedBox(width: 10),
Text(label, style: SText.cardLabel(SColors.textHead)),
],
),
);
}
Widget _badge() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: SColors.primaryLight,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 7,
height: 7,
decoration: const BoxDecoration(
color: SColors.accent,
shape: BoxShape.circle,
),
),
const SizedBox(width: 6),
Text(
'Trusted by 50,000+ women',
style: SText.caption(SColors.primary).copyWith(fontWeight: FontWeight.w700),
),
],
),
);
}
Widget _statsRow() {
return Row(
children: [
_statBox('50K+', 'Users'),
const SizedBox(width: 10),
_statBox('4.9★', 'Rating'),
const SizedBox(width: 10),
_statBox('94%', 'Results'),
],
);
}
Widget _statBox(String value, String label) {
return Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 14),
decoration: BoxDecoration(
color: SColors.bgSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: SColors.borderLight, width: 1.5),
),
child: Column(
children: [
Text(value, style: SText.title(SColors.primary)),
const SizedBox(height: 2),
Text(label, style: SText.caption(SColors.textSub)),
],
),
),
);
}
}