feat: Design System — colors, typography, theme

This commit is contained in:
TrochtaOndrej
2026-03-17 23:39:48 +01:00
parent ae28e7ffd8
commit 03e1ab1d24
6 changed files with 269 additions and 0 deletions
View File
+24
View File
@@ -0,0 +1,24 @@
/// App-wide constants for KittieMobile.
abstract final class AppConstants {
// Touch targets (Apple HIG)
static const double minTouchTarget = 44.0;
// Animation durations
static const Duration animationFast = Duration(milliseconds: 200);
static const Duration animationNormal = Duration(milliseconds: 300);
static const Duration animationSlow = Duration(milliseconds: 500);
// Energy levels
static const int energyLow = 1;
static const int energyMedium = 2;
static const int energyHigh = 3;
// Streaks
static const int maxStreakDisplay = 7;
// Layout
static const double bottomNavHeight = 64.0;
static const double fabSize = 56.0;
static const double cardBorderRadius = 16.0;
static const double bottomSheetBorderRadius = 24.0;
}
View File
+40
View File
@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
/// Warm Parchment color palette for KittieMobile.
abstract final class KittieColors {
// Cream / surface
static const Color cream = Color(0xFFF5F2EC);
static const Color creamDark = Color(0xFFEDE8DF);
static const Color creamBorder = Color(0xFFE0DBD0);
// Brown / primary
static const Color brown = Color(0xFF6B5A48);
static const Color brownLight = Color(0xFF8C8070);
static const Color brownDark = Color(0xFF2C2820);
static const Color brownMid = Color(0xFF3D3830);
// Sage green / tertiary
static const Color sageGreen = Color(0xFF7BAE82);
static const Color greenLight = Color(0xFFEEF4EF);
static const Color greenDark = Color(0xFF3A6040);
// Amber / secondary
static const Color amber = Color(0xFFC4A882);
// Purple / accent
static const Color purple = Color(0xFF9070A0);
static const Color purpleLight = Color(0xFFF0E8F8);
// Red / error
static const Color red = Color(0xFFC45858);
static const Color redLight = Color(0xFFFAF0F0);
// Orange / warning
static const Color orange = Color(0xFFC4943A);
static const Color orangeLight = Color(0xFFFBF3E8);
// Energy level colors
static const Color energyLow = sageGreen;
static const Color energyMedium = orange;
static const Color energyHigh = red;
}
+121
View File
@@ -0,0 +1,121 @@
import 'package:flutter/material.dart';
import 'kittie_colors.dart';
import 'kittie_typography.dart';
import '../constants/app_constants.dart';
/// Material 3 theme for KittieMobile.
abstract final class KittieTheme {
static ThemeData get light {
final colorScheme = ColorScheme.light(
surface: KittieColors.cream,
onSurface: KittieColors.brownDark,
primary: KittieColors.brown,
onPrimary: KittieColors.cream,
secondary: KittieColors.amber,
onSecondary: KittieColors.brownDark,
tertiary: KittieColors.sageGreen,
onTertiary: KittieColors.cream,
error: KittieColors.red,
onError: KittieColors.cream,
);
return ThemeData(
useMaterial3: true,
colorScheme: colorScheme,
textTheme: KittieTypography.textTheme,
scaffoldBackgroundColor: KittieColors.cream,
// AppBar
appBarTheme: AppBarTheme(
backgroundColor: Colors.transparent,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: false,
titleTextStyle: KittieTypography.h2.copyWith(
color: KittieColors.brownDark,
),
iconTheme: const IconThemeData(color: KittieColors.brownDark),
),
// Card
cardTheme: CardThemeData(
color: KittieColors.cream,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConstants.cardBorderRadius),
side: const BorderSide(color: KittieColors.creamBorder),
),
),
// Bottom Navigation Bar
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
backgroundColor: KittieColors.cream,
selectedItemColor: KittieColors.brown,
unselectedItemColor: KittieColors.brownLight,
elevation: 0,
type: BottomNavigationBarType.fixed,
),
// FAB
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: KittieColors.brown,
foregroundColor: KittieColors.cream,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConstants.cardBorderRadius),
),
),
// Bottom Sheet
bottomSheetTheme: const BottomSheetThemeData(
backgroundColor: KittieColors.cream,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(AppConstants.bottomSheetBorderRadius),
),
),
),
// Input Decoration
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: KittieColors.creamDark,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: KittieColors.brown, width: 1.5),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
// Elevated Button
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: KittieColors.brown,
foregroundColor: KittieColors.cream,
minimumSize: const Size(0, 48),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
textStyle: KittieTypography.labelLarge,
elevation: 0,
),
),
// Text Button
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: KittieColors.brown,
textStyle: KittieTypography.labelLarge,
),
),
);
}
}
+84
View File
@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'kittie_colors.dart';
/// Typography system for KittieMobile.
///
/// Primary font: Lexend (optimized for readability).
/// Alt font: Atkinson Hyperlegible (high legibility).
/// Minimum text size: 13sp.
abstract final class KittieTypography {
// Headings
static TextStyle get h1 => GoogleFonts.lexend(
fontSize: 28,
fontWeight: FontWeight.w700,
color: KittieColors.brown,
);
static TextStyle get h2 => GoogleFonts.lexend(
fontSize: 22,
fontWeight: FontWeight.w600,
color: KittieColors.brown,
);
static TextStyle get h3 => GoogleFonts.lexend(
fontSize: 18,
fontWeight: FontWeight.w600,
color: KittieColors.brown,
);
// Body
static TextStyle get bodyLarge => GoogleFonts.lexend(
fontSize: 16,
fontWeight: FontWeight.w400,
color: KittieColors.brown,
);
static TextStyle get bodyMedium => GoogleFonts.lexend(
fontSize: 14,
fontWeight: FontWeight.w400,
color: KittieColors.brown,
);
static TextStyle get bodySmall => GoogleFonts.lexend(
fontSize: 13,
fontWeight: FontWeight.w400,
color: KittieColors.brown,
);
// Labels
static TextStyle get labelLarge => GoogleFonts.lexend(
fontSize: 14,
fontWeight: FontWeight.w500,
color: KittieColors.brown,
);
static TextStyle get labelMedium => GoogleFonts.lexend(
fontSize: 12,
fontWeight: FontWeight.w500,
color: KittieColors.brown,
);
static TextStyle get labelSmall => GoogleFonts.lexend(
fontSize: 11,
fontWeight: FontWeight.w500,
color: KittieColors.brown,
);
/// Builds the full [TextTheme] for Material 3.
static TextTheme get textTheme => TextTheme(
headlineLarge: h1,
headlineMedium: h2,
headlineSmall: h3,
bodyLarge: bodyLarge,
bodyMedium: bodyMedium,
bodySmall: bodySmall,
labelLarge: labelLarge,
labelMedium: labelMedium,
labelSmall: labelSmall,
titleLarge: h2,
titleMedium: h3,
titleSmall: labelLarge,
);
}