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
This commit is contained in:
mav
2026-05-28 16:34:04 +02:00
parent 30cee5a486
commit 6311088256
9 changed files with 1168 additions and 638 deletions

View File

@@ -2,42 +2,65 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class SColors {
// Backgrounds
static const bgPage = Color(0xFFFAFAFE);
static const bgSurface = Color(0xFFFFFFFF);
// Primary (Indigo)
static const primary = Color(0xFF5B4FCF);
static const primaryLight = Color(0xFF7B70E0);
static const primaryDeep = Color(0xFF3D32A8);
static const primaryDark = Color(0xFF3D32A8); // button bottom border
static const primaryLight = Color(0xFFEAE7FB); // selected card tint
static const primaryBorder = Color(0xFF5B4FCF); // selected card border
// Text
static const textHead = Color(0xFF1C1A2E);
static const textBody = Color(0xFF4B4B6B);
static const textSub = Color(0xFF9898AA);
static const textDisabled = Color(0xFFC4C4D4);
// Borders
static const borderLight = Color(0xFFE8E6F0);
static const borderMedium = Color(0xFFD0CDEA);
// Accent
static const accent = Color(0xFFFF7EB3);
static const accentSoft = Color(0xFFFFF0F6);
static const bgPage = Color(0xFFFAF9FF);
static const surface = Color(0xFFFFFFFF);
static const textPrimary = Color(0xFF1C1A2E);
static const textSecondary = Color(0xFF7B7A8E);
static const border = Color(0xFFE8E6F0);
static const skyTint = Color(0xFFEEECFA);
static const gradientTop = Color(0xFF5B4FCF);
static const gradientBot = Color(0xFF8B5CF6);
static const accentLight = Color(0xFFFFF0F6);
// States
static const success = Color(0xFF4CAF50);
static const error = Color(0xFFFF4B4B);
}
TextStyle _nunito(double size, FontWeight weight, Color color, {double? height, double? letterSpacing}) {
return GoogleFonts.nunito(
fontSize: size,
fontWeight: weight,
color: color,
height: height,
letterSpacing: letterSpacing,
);
}
class SText {
static TextStyle headline1(Color c) => _nunito(36, FontWeight.w900, c, height: 1.15);
static TextStyle headline2(Color c) => _nunito(26, FontWeight.w800, c, height: 1.2);
static TextStyle title(Color c) => _nunito(22, FontWeight.w800, c, height: 1.25);
static TextStyle subtitle(Color c) => _nunito(15, FontWeight.w600, c, height: 1.5);
static TextStyle body(Color c) => _nunito(15, FontWeight.w600, c, height: 1.5);
static TextStyle caption(Color c) => _nunito(12, FontWeight.w500, c, height: 1.4);
static TextStyle button(Color c) => _nunito(15, FontWeight.w800, c, letterSpacing: 0.3);
static TextStyle cardLabel(Color c) => _nunito(16, FontWeight.w700, c);
static TextStyle cardSub(Color c) => _nunito(13, FontWeight.w500, c);
}
ThemeData buildTheme() {
return ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: SColors.primary,
brightness: Brightness.light,
colorScheme: const ColorScheme.light(
primary: SColors.primary,
surface: SColors.bgSurface,
),
scaffoldBackgroundColor: SColors.bgPage,
textTheme: GoogleFonts.plusJakartaSansTextTheme().copyWith(
displayLarge: GoogleFonts.plusJakartaSans(
fontSize: 32, fontWeight: FontWeight.w800, color: SColors.textPrimary,
),
headlineMedium: GoogleFonts.plusJakartaSans(
fontSize: 24, fontWeight: FontWeight.w700, color: SColors.textPrimary,
),
bodyLarge: GoogleFonts.plusJakartaSans(
fontSize: 16, fontWeight: FontWeight.w400, color: SColors.textPrimary,
),
bodyMedium: GoogleFonts.plusJakartaSans(
fontSize: 14, fontWeight: FontWeight.w400, color: SColors.textSecondary,
),
),
textTheme: GoogleFonts.nunitoTextTheme(),
useMaterial3: true,
);
}