feat: Design System — colors, typography, theme
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user