Implement premium UI/UX refinements for Apple-like polish

Add three major UI components with animations and dark mode support:

- PremiumRouteCard: Enhanced route cards with left accent bar, delivery count badge, animated hover effects (1.02x scale), and dynamic shadow elevation
- DarkModeMapComponent: Google Maps integration with dark theme styling, custom info panels, navigation buttons, and delivery status indicators
- DeliveryListItem: Animated list items with staggered entrance animations, status badges with icons, contact indicators, and hover states

Updates:
- RoutesPage: Now uses PremiumRouteCard with improved visual hierarchy
- DeliveriesPage: Integrated DarkModeMapComponent and DeliveryListItem with proper theme awareness
- Animation system: Leverages existing AppAnimations constants for 200ms fast interactions and easeOut curves

Design philosophy:
- Element separation through left accent bars (status-coded)
- Elevation and shadow for depth (0.1-0.3 opacity)
- Staggered animations for list items (50ms delays)
- Dark mode optimized for evening use (reduced brightness)
- Responsive hover states with tactile feedback

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jean-Philippe Brule
2025-11-15 14:41:32 -05:00
parent ccb817e3c6
commit 3f31a509e0
23 changed files with 3519 additions and 791 deletions
+272
View File
@@ -0,0 +1,272 @@
import 'package:flutter/material.dart';
/// Svrnty Animation System
/// Complete animation configuration with durations, curves, and stagger delays
class AppAnimations {
// Prevent instantiation
AppAnimations._();
// ============================================
// ANIMATION DURATION CONSTANTS
// ============================================
/// Fast animation duration (200ms) - Button press, hover, quick interactions
static const Duration durationFast = Duration(milliseconds: 200);
/// Normal animation duration (300ms) - Default animations, fade, slide
static const Duration durationNormal = Duration(milliseconds: 300);
/// Slow animation duration (500ms) - Prominent animations, entrance, transitions
static const Duration durationSlow = Duration(milliseconds: 500);
/// Extra slow animation duration (800ms) - Slow, attention-grabbing animations
static const Duration durationXSlow = Duration(milliseconds: 800);
// ============================================
// ANIMATION DURATION IN MILLISECONDS
// ============================================
/// Fast animation milliseconds (200ms)
static const int durationFastMs = 200;
/// Normal animation milliseconds (300ms)
static const int durationNormalMs = 300;
/// Slow animation milliseconds (500ms)
static const int durationSlowMs = 500;
/// Extra slow animation milliseconds (800ms)
static const int durationXSlowMs = 800;
// ============================================
// ANIMATION CURVES
// ============================================
/// Ease In - Slow start, fast end (decelerate)
static const Curve curveEaseIn = Curves.easeIn;
/// Ease Out - Fast start, slow end (decelerate)
static const Curve curveEaseOut = Curves.easeOut;
/// Ease In Out - Smooth both ends (decelerate at start and end)
static const Curve curveEaseInOut = Curves.easeInOut;
/// Ease In Back - Back in, bounce effect
static const Curve curveEaseInBack = Curves.easeInBack;
/// Ease Out Back - Back out, bounce effect
static const Curve curveEaseOutBack = Curves.easeOutBack;
/// Elastic/Bouncy effect
static const Curve curveElastic = Curves.elasticOut;
/// Bouncing motion
static const Curve curveBounce = Curves.bounceOut;
/// Fast Out Slow In - Material standard curve
static const Curve curveFastOutSlowIn = Curves.fastOutSlowIn;
/// Deceleration curve (accelerate)
static const Curve curveAccelerate = Curves.decelerate;
/// Linear curve (no acceleration/deceleration)
static const Curve curveLinear = Curves.linear;
// ============================================
// STAGGER DELAYS (FOR LIST ANIMATIONS)
// ============================================
/// Default stagger delay for list items (50ms)
static const Duration staggerDelay = Duration(milliseconds: 50);
/// Quick stagger delay (30ms)
static const Duration staggerDelayFast = Duration(milliseconds: 30);
/// Slow stagger delay (100ms)
static const Duration staggerDelaySlow = Duration(milliseconds: 100);
/// Stagger delay in milliseconds
static const int staggerDelayMs = 50;
// ============================================
// SCALE ANIMATION CONSTANTS
// ============================================
/// Normal scale (1.0)
static const double scaleNormal = 1.0;
/// Hover/Light scale (1.02)
static const double scaleHover = 1.02;
/// Pressed/Active scale (0.98)
static const double scalePressed = 0.98;
/// Animation scale (0.9)
static const double scaleAnimation = 0.9;
// ============================================
// OFFSET ANIMATION CONSTANTS
// ============================================
/// Slide offset - Small (8px)
static const Offset offsetSm = Offset(0, 8);
/// Slide offset - Medium (16px)
static const Offset offsetMd = Offset(0, 16);
/// Slide offset - Large (20px)
static const Offset offsetLg = Offset(0, 20);
/// Slide offset - Extra large (32px)
static const Offset offsetXl = Offset(0, 32);
/// Floating offset - Up (10px)
static const Offset offsetFloating = Offset(0, -10);
// ============================================
// OPACITY ANIMATION CONSTANTS
// ============================================
/// Full opacity
static const double opacityFull = 1.0;
/// Half opacity
static const double opacityHalf = 0.5;
/// Subtle opacity (70%)
static const double opacitySubtle = 0.7;
/// Dim opacity (50%)
static const double opacityDim = 0.5;
/// Fade out opacity (30%)
static const double opacityFadeOut = 0.3;
/// Invisible opacity (0%)
static const double opacityInvisible = 0.0;
// ============================================
// ANIMATION PRESETS
// ============================================
/// Scale animation preset (button press) - note: CurvedAnimation cannot be const
// Use this pattern in your widgets instead:
// CurvedAnimation(parent: controller, curve: Curves.easeInOut)
// ============================================
// ROTATION ANIMATION CONSTANTS
// ============================================
/// Full rotation (360 degrees)
static const double rotationFull = 1.0;
/// Half rotation (180 degrees)
static const double rotationHalf = 0.5;
/// Quarter rotation (90 degrees)
static const double rotationQuarter = 0.25;
// ============================================
// UTILITY METHODS
// ============================================
/// Get duration based on animation intensity
static Duration getDuration(AnimationIntensity intensity) {
switch (intensity) {
case AnimationIntensity.fast:
return durationFast;
case AnimationIntensity.normal:
return durationNormal;
case AnimationIntensity.slow:
return durationSlow;
case AnimationIntensity.xSlow:
return durationXSlow;
}
}
/// Get curve based on animation type
static Curve getCurve(AnimationType type) {
switch (type) {
case AnimationType.easeIn:
return curveEaseIn;
case AnimationType.easeOut:
return curveEaseOut;
case AnimationType.easeInOut:
return curveEaseInOut;
case AnimationType.elastic:
return curveElastic;
case AnimationType.bounce:
return curveBounce;
case AnimationType.linear:
return curveLinear;
}
}
/// Get stagger delay for list index
static Duration getStaggerDelay(int index, {bool fast = false}) {
final baseDelay = fast ? staggerDelayFast : staggerDelay;
return Duration(
milliseconds: baseDelay.inMilliseconds * index,
);
}
/// Get scale value based on interaction state
static double getScale(InteractionState state) {
switch (state) {
case InteractionState.normal:
return scaleNormal;
case InteractionState.hover:
return scaleHover;
case InteractionState.pressed:
return scalePressed;
}
}
}
/// Animation intensity levels
enum AnimationIntensity {
/// 200ms - Quick interactions
fast,
/// 300ms - Standard animations
normal,
/// 500ms - Prominent animations
slow,
/// 800ms - Slow, attention-grabbing animations
xSlow,
}
/// Animation types/curves
enum AnimationType {
/// Ease In curve
easeIn,
/// Ease Out curve
easeOut,
/// Ease In Out curve
easeInOut,
/// Elastic/bouncy curve
elastic,
/// Bounce curve
bounce,
/// Linear curve
linear,
}
/// Interaction states for animation
enum InteractionState {
/// Normal/default state
normal,
/// Hover state
hover,
/// Pressed/active state
pressed,
}
+146
View File
@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
/// Svrnty Border System - Border Radius Constants
/// All border radius values follow a strict 4px grid
class AppBorders {
// Prevent instantiation
AppBorders._();
// ============================================
// BORDER RADIUS VALUES (4px Grid)
// ============================================
/// Extra small border radius (4px) - unit × 1
/// Used for: Subtle rounding on chips, tags, small elements
static const double radiusXs = 4.0;
/// Small border radius (8px) - unit × 2
/// Used for: Buttons, inputs, small cards
static const double radiusSm = 8.0;
/// Medium border radius (12px) - unit × 3
/// Used for: Cards, dropdowns, standard components
static const double radiusMd = 12.0;
/// Large border radius (16px) - unit × 4
/// Used for: Dialogs, large cards, prominent containers
static const double radiusLg = 16.0;
/// Extra large border radius (24px) - unit × 6
/// Used for: Containers, large surfaces
static const double radiusXl = 24.0;
/// Fully rounded border radius (999px)
/// Used for: Pills, badges, fully circular elements
static const double radiusRound = 999.0;
// ============================================
// BORDER RADIUS - BORDERRADIUS OBJECTS
// ============================================
/// BorderRadius.circular(4px)
static const BorderRadius circularXs = BorderRadius.all(Radius.circular(radiusXs));
/// BorderRadius.circular(8px)
static const BorderRadius circularSm = BorderRadius.all(Radius.circular(radiusSm));
/// BorderRadius.circular(12px)
static const BorderRadius circularMd = BorderRadius.all(Radius.circular(radiusMd));
/// BorderRadius.circular(16px)
static const BorderRadius circularLg = BorderRadius.all(Radius.circular(radiusLg));
/// BorderRadius.circular(24px)
static const BorderRadius circularXl = BorderRadius.all(Radius.circular(radiusXl));
/// BorderRadius.circular(999px) - Fully rounded
static const BorderRadius circularRound = BorderRadius.all(Radius.circular(radiusRound));
// ============================================
// BORDER RADIUS - TOP ONLY (for bottom sheets)
// ============================================
/// BorderRadius with top corners rounded (8px)
static const BorderRadius topSmallRadius = BorderRadius.only(
topLeft: Radius.circular(radiusSm),
topRight: Radius.circular(radiusSm),
);
/// BorderRadius with top corners rounded (12px)
static const BorderRadius topMediumRadius = BorderRadius.only(
topLeft: Radius.circular(radiusMd),
topRight: Radius.circular(radiusMd),
);
/// BorderRadius with top corners rounded (16px)
static const BorderRadius topLargeRadius = BorderRadius.only(
topLeft: Radius.circular(radiusLg),
topRight: Radius.circular(radiusLg),
);
// ============================================
// COMPONENT BORDER RADIUS MAPPING
// ============================================
/// Button border radius (8px - radiusSm)
static const double buttonRadius = radiusSm;
/// Input field border radius (8px - radiusSm)
static const double inputRadius = radiusSm;
/// Card border radius (12px - radiusMd)
static const double cardRadius = radiusMd;
/// Dialog border radius (16px - radiusLg)
static const double dialogRadius = radiusLg;
/// Chip border radius (999px - radiusRound, fully rounded)
static const double chipRadius = radiusRound;
/// Bottom sheet border radius (16px - radiusLg)
static const double bottomSheetRadius = radiusLg;
/// Dropdown border radius (8px - radiusSm)
static const double dropdownRadius = radiusSm;
/// Small component border radius (4px - radiusXs)
static const double smallComponentRadius = radiusXs;
// ============================================
// BORDER RADIUS SHAPE OBJECTS
// ============================================
/// RoundedRectangleBorder for buttons (8px radius)
static const ShapeBorder buttonShape = RoundedRectangleBorder(
borderRadius: circularSm,
);
/// RoundedRectangleBorder for cards (12px radius)
static const ShapeBorder cardShape = RoundedRectangleBorder(
borderRadius: circularMd,
);
/// RoundedRectangleBorder for dialogs (16px radius)
static const ShapeBorder dialogShape = RoundedRectangleBorder(
borderRadius: circularLg,
);
// ============================================
// COMPONENT BORDER RADIUS OBJECTS
// ============================================
/// Small component border radius (4px - Radius object)
static const Radius smallRadius = Radius.circular(radiusXs);
/// Button border radius (8px - Radius object)
static const Radius buttonBorderRadius = Radius.circular(radiusSm);
/// Card border radius (12px - Radius object)
static const Radius cardBorderRadius = Radius.circular(radiusMd);
/// Dialog border radius (16px - Radius object)
static const Radius dialogBorderRadius = Radius.circular(radiusLg);
/// Fully rounded (999px - Radius object)
static const Radius fullRoundRadius = Radius.circular(radiusRound);
}
+159
View File
@@ -0,0 +1,159 @@
import 'package:flutter/material.dart';
/// Svrnty Brand Color System
/// Complete color palette following Material Design 3 specifications
class SvrntyColors {
// Prevent instantiation
SvrntyColors._();
// ============================================
// CORE BRAND COLORS
// ============================================
/// Crimson Red - Primary accent and brand signature
static const Color crimsonRed = Color(0xDF2D45);
/// Almost Black - Primary dark background
static const Color almostBlack = Color(0x06080C);
/// Dark Slate - Secondary dark tone
static const Color darkSlate = Color(0x3A4958);
/// Slate Gray - Mid-tone gray
static const Color slateGray = Color(0x506576);
/// Teal - Tertiary accent
static const Color teal = Color(0x1D2C39);
/// Light Gray - Neutral light
static const Color lightGray = Color(0xAEB8BE);
// ============================================
// SEMANTIC COLORS
// ============================================
/// Success - Green for positive actions and completed states
static const Color success = Color(0x22C55E);
/// Warning - Amber for warnings and attention-needed states
static const Color warning = Color(0xF59E0B);
/// Info - Blue for informational and in-progress states
static const Color info = Color(0x3B82F6);
/// Error - Red for errors, failures, and destructive actions
static const Color error = Color(0xEF4444);
// ============================================
// DELIVERY STATUS COLORS
// ============================================
/// Status Pending - Awaiting action (Slate Gray)
static const Color statusPending = slateGray;
/// Status In Progress - Currently being delivered (Blue)
static const Color statusInProgress = info;
/// Status Completed - Successfully delivered (Green)
static const Color statusCompleted = success;
/// Status Skipped - Skipped/passed delivery (Amber)
static const Color statusSkipped = warning;
/// Status Failed - Failed delivery (Red)
static const Color statusFailed = error;
// ============================================
// SURFACE VARIANTS
// ============================================
/// Surface Elevated - Light elevated surface
static const Color surfaceElevated = Color(0xF5F7FA);
/// Surface Subdued - Subdued light surface
static const Color surfaceSubdued = Color(0xE8EAEE);
// ============================================
// EXTENDED COLOR FAMILIES - SUCCESS (GREEN)
// ============================================
/// Success color light theme
static const Color successLight = Color(0x22C55E);
/// Success on color light theme
static const Color onSuccessLight = Color(0xFFFFFF);
/// Success container light theme
static const Color successContainerLight = Color(0xDCFCE7);
/// Success on container light theme
static const Color onSuccessContainerLight = Color(0x14532D);
/// Success color dark theme
static const Color successDark = Color(0x4ADE80);
/// Success on color dark theme
static const Color onSuccessDark = Color(0x14532D);
/// Success container dark theme
static const Color successContainerDark = Color(0x15803D);
/// Success on container dark theme
static const Color onSuccessContainerDark = Color(0xDCFCE7);
// ============================================
// EXTENDED COLOR FAMILIES - WARNING (AMBER)
// ============================================
/// Warning color light theme
static const Color warningLight = Color(0xF59E0B);
/// Warning on color light theme
static const Color onWarningLight = Color(0xFFFFFF);
/// Warning container light theme
static const Color warningContainerLight = Color(0xFEF3C7);
/// Warning on container light theme
static const Color onWarningContainerLight = Color(0x78350F);
/// Warning color dark theme
static const Color warningDark = Color(0xFBBF24);
/// Warning on color dark theme
static const Color onWarningDark = Color(0x78350F);
/// Warning container dark theme
static const Color warningContainerDark = Color(0xD97706);
/// Warning on container dark theme
static const Color onWarningContainerDark = Color(0xFEF3C7);
// ============================================
// EXTENDED COLOR FAMILIES - INFO (BLUE)
// ============================================
/// Info color light theme
static const Color infoLight = Color(0x3B82F6);
/// Info on color light theme
static const Color onInfoLight = Color(0xFFFFFF);
/// Info container light theme
static const Color infoContainerLight = Color(0xDEEEFF);
/// Info on container light theme
static const Color onInfoContainerLight = Color(0x003DA1);
/// Info color dark theme
static const Color infoDark = Color(0x90CAF9);
/// Info on color dark theme
static const Color onInfoDark = Color(0x003DA1);
/// Info container dark theme
static const Color infoContainerDark = Color(0x0D47A1);
/// Info on container dark theme
static const Color onInfoContainerDark = Color(0xDEEEFF);
}
+262
View File
@@ -0,0 +1,262 @@
import 'package:flutter/material.dart';
import 'spacing_system.dart';
import 'border_system.dart';
import 'shadow_system.dart';
import 'size_system.dart';
/// Component Theme Data Builders
/// Centralized component theme definitions for consistent styling
class ComponentThemes {
static CardThemeData cardTheme(ColorScheme colorScheme) {
return CardThemeData(
elevation: AppShadow.cardElevation,
shadowColor: AppShadow.getShadowColor(colorScheme.brightness),
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularMd,
),
clipBehavior: Clip.antiAlias,
color: colorScheme.surface,
);
}
static AppBarTheme appBarTheme(ColorScheme colorScheme) {
return AppBarTheme(
backgroundColor: colorScheme.surface,
foregroundColor: colorScheme.onSurface,
elevation: AppShadow.appBarElevation,
centerTitle: false,
iconTheme: IconThemeData(
color: colorScheme.onSurface,
size: AppSizes.iconMd,
),
titleTextStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 20,
color: colorScheme.onSurface,
),
);
}
static FilledButtonThemeData filledButtonTheme(ColorScheme colorScheme) {
return FilledButtonThemeData(
style: FilledButton.styleFrom(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
elevation: AppShadow.elevationSm,
padding: AppSpacing.paddingButton,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularSm,
),
textStyle: const TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
);
}
static ElevatedButtonThemeData elevatedButtonTheme(ColorScheme colorScheme) {
return ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
elevation: AppShadow.elevationSm,
padding: AppSpacing.paddingButton,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularSm,
),
textStyle: const TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
);
}
static OutlinedButtonThemeData outlinedButtonTheme(ColorScheme colorScheme) {
return OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: colorScheme.primary,
side: BorderSide(color: colorScheme.outline),
padding: AppSpacing.paddingButton,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularSm,
),
textStyle: const TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
);
}
static InputDecorationTheme inputDecorationTheme(ColorScheme colorScheme) {
return InputDecorationTheme(
filled: true,
fillColor: colorScheme.surfaceContainerHighest.withOpacity(0.5),
contentPadding: EdgeInsets.symmetric(
horizontal: AppSpacing.inputPadding,
vertical: AppSpacing.md,
),
border: OutlineInputBorder(
borderRadius: AppBorders.circularSm,
borderSide: BorderSide(
color: colorScheme.outline.withOpacity(0.3),
),
),
enabledBorder: OutlineInputBorder(
borderRadius: AppBorders.circularSm,
borderSide: BorderSide(
color: colorScheme.outline.withOpacity(0.3),
width: 1,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: AppBorders.circularSm,
borderSide: BorderSide(
color: colorScheme.primary,
width: 2,
),
),
errorBorder: OutlineInputBorder(
borderRadius: AppBorders.circularSm,
borderSide: BorderSide(
color: colorScheme.error,
width: 1,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: AppBorders.circularSm,
borderSide: BorderSide(
color: colorScheme.error,
width: 2,
),
),
labelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant,
),
hintStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w400,
color: colorScheme.onSurfaceVariant.withOpacity(0.6),
),
);
}
static SnackBarThemeData snackBarTheme(ColorScheme colorScheme) {
return SnackBarThemeData(
backgroundColor: colorScheme.inverseSurface,
contentTextStyle: TextStyle(
fontFamily: 'Montserrat',
color: colorScheme.onInverseSurface,
),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularSm,
),
);
}
static DialogThemeData dialogTheme(ColorScheme colorScheme) {
return DialogThemeData(
backgroundColor: colorScheme.surface,
elevation: AppShadow.dialogElevation,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularLg,
),
contentTextStyle: TextStyle(
fontFamily: 'Montserrat',
color: colorScheme.onSurface,
),
);
}
static BottomNavigationBarThemeData bottomNavigationBarTheme(
ColorScheme colorScheme,
) {
return BottomNavigationBarThemeData(
backgroundColor: colorScheme.surface,
selectedItemColor: colorScheme.primary,
unselectedItemColor: colorScheme.onSurfaceVariant,
showSelectedLabels: true,
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
selectedLabelStyle: const TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
fontSize: 12,
),
unselectedLabelStyle: const TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w400,
fontSize: 12,
),
);
}
static ChipThemeData chipTheme(ColorScheme colorScheme) {
return ChipThemeData(
backgroundColor: colorScheme.surfaceContainerHighest,
deleteIconColor: colorScheme.onSurfaceVariant,
disabledColor: colorScheme.surfaceContainerHighest.withOpacity(0.38),
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.sm,
vertical: AppSpacing.xs,
),
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularSm,
),
labelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant,
),
secondaryLabelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant,
),
brightness: colorScheme.brightness,
);
}
static ProgressIndicatorThemeData progressIndicatorTheme(
ColorScheme colorScheme,
) {
return ProgressIndicatorThemeData(
color: colorScheme.primary,
linearTrackColor: colorScheme.surfaceContainerHighest,
circularTrackColor: colorScheme.surfaceContainerHighest,
);
}
static FloatingActionButtonThemeData floatingActionButtonTheme(
ColorScheme colorScheme,
) {
return FloatingActionButtonThemeData(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
elevation: AppShadow.fabElevation,
shape: RoundedRectangleBorder(
borderRadius: AppBorders.circularMd,
),
);
}
static SliderThemeData sliderTheme(ColorScheme colorScheme) {
return SliderThemeData(
trackHeight: 4.0,
activeTrackColor: colorScheme.primary,
inactiveTrackColor: colorScheme.surfaceContainerHighest,
thumbColor: colorScheme.primary,
overlayColor: colorScheme.primary.withOpacity(0.12),
valueIndicatorColor: colorScheme.primary,
);
}
}
+332
View File
@@ -0,0 +1,332 @@
import 'package:flutter/material.dart';
import 'color_system.dart';
/// Svrnty Gradient System
/// Predefined gradients for status bars, progress indicators, and backgrounds
class AppGradients {
// Prevent instantiation
AppGradients._();
// ============================================
// DELIVERY STATUS GRADIENTS
// ============================================
/// Pending status gradient (Slate Gray)
static const LinearGradient gradientStatusPending = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.statusPending,
Color(0x506576), // Slightly different shade for gradient effect
],
);
/// In Progress status gradient (Blue/Info)
static const LinearGradient gradientStatusInProgress = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.statusInProgress,
Color(0x5B9BFF), // Lighter blue for gradient
],
);
/// Completed status gradient (Green/Success)
static const LinearGradient gradientStatusCompleted = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.statusCompleted,
Color(0x4ADE80), // Lighter green for gradient
],
);
/// Skipped status gradient (Amber/Warning)
static const LinearGradient gradientStatusSkipped = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.statusSkipped,
Color(0xFBBF24), // Lighter amber for gradient
],
);
/// Failed status gradient (Red/Error)
static const LinearGradient gradientStatusFailed = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.statusFailed,
Color(0xFF7D7D), // Lighter red for gradient
],
);
// ============================================
// PROGRESS INDICATOR GRADIENTS
// ============================================
/// Progress bar gradient (Blue to transparent)
static LinearGradient gradientProgress({
required Color color,
bool horizontal = true,
}) {
return LinearGradient(
begin: horizontal ? Alignment.centerLeft : Alignment.topCenter,
end: horizontal ? Alignment.centerRight : Alignment.bottomCenter,
colors: [
color,
color.withOpacity(0.8),
],
);
}
/// Success progress gradient
static const LinearGradient gradientProgressSuccess = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.success,
Color(0x4ADE80), // Lighter green
],
);
/// Warning progress gradient
static const LinearGradient gradientProgressWarning = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.warning,
Color(0xFBBF24), // Lighter amber
],
);
/// Error progress gradient
static const LinearGradient gradientProgressError = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.error,
Color(0xFF7D7D), // Lighter red
],
);
/// Info progress gradient
static const LinearGradient gradientProgressInfo = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
SvrntyColors.info,
Color(0x5B9BFF), // Lighter blue
],
);
// ============================================
// BRAND GRADIENTS
// ============================================
/// Primary brand gradient (Crimson Red)
static const LinearGradient gradientPrimary = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
SvrntyColors.crimsonRed,
Color(0xC44D58), // Slightly darker shade
],
);
/// Secondary brand gradient (Slate Blue)
static const LinearGradient gradientSecondary = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
SvrntyColors.darkSlate,
SvrntyColors.slateGray,
],
);
/// Accent gradient (Crimson to Slate)
static const LinearGradient gradientAccent = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
SvrntyColors.crimsonRed,
SvrntyColors.darkSlate,
],
);
// ============================================
// BACKGROUND GRADIENTS
// ============================================
/// Light background gradient
static const LinearGradient gradientBackgroundLight = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFAFAFC),
Color(0xF5F7FA),
],
);
/// Dark background gradient
static const LinearGradient gradientBackgroundDark = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0x1A1C1E),
Color(0x2A2D34),
],
);
/// Elevated surface gradient (light)
static const LinearGradient gradientElevatedLight = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFFF),
Color(0xF5F7FA),
],
);
/// Elevated surface gradient (dark)
static const LinearGradient gradientElevatedDark = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0x2A2D34),
Color(0x1F2123),
],
);
// ============================================
// OVERLAY GRADIENTS
// ============================================
/// Dark overlay gradient (for images)
static const LinearGradient gradientOverlayDark = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0x00000000), // Transparent at top
Color(0x4D000000), // Dark at bottom
],
);
/// Light overlay gradient
static const LinearGradient gradientOverlayLight = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0x00FFFFFF), // Transparent at top
Color(0x4DFFFFFF), // Light at bottom
],
);
/// Vignette gradient (darkened edges)
static const RadialGradient gradientVignette = RadialGradient(
center: Alignment.center,
radius: 1.2,
colors: [
Color(0x00000000),
Color(0x80000000),
],
);
// ============================================
// SHIMMER GRADIENTS (for loading states)
// ============================================
/// Shimmer gradient light theme
static const LinearGradient gradientShimmerLight = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFFFFF),
Color(0x80F0F0F0),
Color(0xFFFFFFFF),
],
stops: [0.1, 0.5, 0.9],
);
/// Shimmer gradient dark theme
static const LinearGradient gradientShimmerDark = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFF2A2D34),
Color(0x80383940),
Color(0xFF2A2D34),
],
stops: [0.1, 0.5, 0.9],
);
// ============================================
// UTILITY METHODS
// ============================================
/// Get status gradient based on delivery status
static LinearGradient getStatusGradient(String status) {
switch (status.toLowerCase()) {
case 'pending':
return gradientStatusPending;
case 'in_progress':
case 'inprogress':
return gradientStatusInProgress;
case 'completed':
case 'done':
return gradientStatusCompleted;
case 'skipped':
return gradientStatusSkipped;
case 'failed':
return gradientStatusFailed;
default:
return gradientStatusPending;
}
}
/// Get progress gradient based on status
static LinearGradient getProgressGradient(String status) {
switch (status.toLowerCase()) {
case 'success':
return gradientProgressSuccess;
case 'warning':
return gradientProgressWarning;
case 'error':
return gradientProgressError;
case 'info':
return gradientProgressInfo;
default:
return gradientProgressSuccess;
}
}
/// Create a custom gradient with opacity
static LinearGradient withOpacity(
LinearGradient gradient,
double opacity,
) {
return LinearGradient(
begin: gradient.begin,
end: gradient.end,
colors: gradient.colors
.map((color) => color.withOpacity(opacity))
.toList(),
stops: gradient.stops,
);
}
/// Create a directional gradient
static LinearGradient directional({
required List<Color> colors,
required Alignment begin,
required Alignment end,
List<double>? stops,
}) {
return LinearGradient(
begin: begin,
end: end,
colors: colors,
stops: stops,
);
}
}
+208
View File
@@ -0,0 +1,208 @@
import 'package:flutter/material.dart';
/// Svrnty Shadow & Elevation System
/// Comprehensive shadow and elevation definitions for light and dark themes
class AppShadow {
// Prevent instantiation
AppShadow._();
// ============================================
// ELEVATION CONSTANTS
// ============================================
/// No elevation/shadow
static const double elevationNone = 0.0;
/// Minimal depth elevation
static const double elevationXs = 1.0;
/// Small shadow elevation (default for cards)
static const double elevationSm = 2.0;
/// Medium shadow elevation (hover states)
static const double elevationMd = 4.0;
/// Large shadow elevation
static const double elevationLg = 8.0;
/// Extra large shadow elevation (dialogs, prominent surfaces)
static const double elevationXl = 16.0;
// ============================================
// SHADOW DEFINITIONS - LIGHT THEME
// ============================================
/// Light theme shadow color (10% opacity black)
static const Color _shadowColorLight = Color(0x1A000000);
/// No shadow for light theme
static const List<BoxShadow> shadowNoneLight = [];
/// Minimal shadow for light theme
static const List<BoxShadow> shadowXsLight = [
BoxShadow(
color: _shadowColorLight,
blurRadius: 1,
offset: Offset(0, 1),
),
];
/// Small shadow for light theme (default for cards)
static const List<BoxShadow> shadowSmLight = [
BoxShadow(
color: _shadowColorLight,
blurRadius: 2,
offset: Offset(0, 1),
),
];
/// Medium shadow for light theme (hover states)
static const List<BoxShadow> shadowMdLight = [
BoxShadow(
color: _shadowColorLight,
blurRadius: 4,
offset: Offset(0, 2),
),
];
/// Large shadow for light theme
static const List<BoxShadow> shadowLgLight = [
BoxShadow(
color: _shadowColorLight,
blurRadius: 8,
offset: Offset(0, 4),
),
];
/// Extra large shadow for light theme (dialogs)
static const List<BoxShadow> shadowXlLight = [
BoxShadow(
color: _shadowColorLight,
blurRadius: 16,
offset: Offset(0, 8),
),
];
// ============================================
// SHADOW DEFINITIONS - DARK THEME
// ============================================
/// Dark theme shadow color (pure black)
static const Color _shadowColorDark = Color(0x4D000000);
/// No shadow for dark theme
static const List<BoxShadow> shadowNoneDark = [];
/// Minimal shadow for dark theme
static const List<BoxShadow> shadowXsDark = [
BoxShadow(
color: _shadowColorDark,
blurRadius: 1,
offset: Offset(0, 1),
),
];
/// Small shadow for dark theme (default for cards)
static const List<BoxShadow> shadowSmDark = [
BoxShadow(
color: _shadowColorDark,
blurRadius: 2,
offset: Offset(0, 1),
),
];
/// Medium shadow for dark theme (hover states)
static const List<BoxShadow> shadowMdDark = [
BoxShadow(
color: _shadowColorDark,
blurRadius: 4,
offset: Offset(0, 2),
),
];
/// Large shadow for dark theme
static const List<BoxShadow> shadowLgDark = [
BoxShadow(
color: _shadowColorDark,
blurRadius: 8,
offset: Offset(0, 4),
),
];
/// Extra large shadow for dark theme (dialogs)
static const List<BoxShadow> shadowXlDark = [
BoxShadow(
color: _shadowColorDark,
blurRadius: 16,
offset: Offset(0, 8),
),
];
// ============================================
// SHADOW UTILITY METHODS
// ============================================
/// Get shadow list based on brightness and elevation level
static List<BoxShadow> getShadow(
Brightness brightness,
double elevation,
) {
final isDark = brightness == Brightness.dark;
switch (elevation) {
case elevationNone:
return isDark ? shadowNoneDark : shadowNoneLight;
case elevationXs:
return isDark ? shadowXsDark : shadowXsLight;
case elevationSm:
return isDark ? shadowSmDark : shadowSmLight;
case elevationMd:
return isDark ? shadowMdDark : shadowMdLight;
case elevationLg:
return isDark ? shadowLgDark : shadowLgLight;
case elevationXl:
return isDark ? shadowXlDark : shadowXlLight;
default:
return isDark ? shadowSmDark : shadowSmLight;
}
}
/// Get shadow color based on brightness
static Color getShadowColor(Brightness brightness) {
return brightness == Brightness.dark ? _shadowColorDark : _shadowColorLight;
}
// ============================================
// COMPONENT ELEVATION MAPPING
// ============================================
/// Card elevation (2)
static const double cardElevation = elevationSm;
/// Card hover elevation (4)
static const double cardHoverElevation = elevationMd;
/// AppBar elevation (0 - flat design)
static const double appBarElevation = elevationNone;
/// Dialog elevation (8)
static const double dialogElevation = elevationLg;
/// FAB elevation (8)
static const double fabElevation = elevationLg;
/// FAB hover elevation (16)
static const double fabHoverElevation = elevationXl;
/// Bottom sheet elevation (8)
static const double bottomSheetElevation = elevationLg;
/// Floating action button pressed elevation (12)
static const double fabPressedElevation = elevationXl;
/// Menu/Dropdown elevation (8)
static const double menuElevation = elevationLg;
/// Tooltip elevation (16)
static const double tooltipElevation = elevationXl;
}
+236
View File
@@ -0,0 +1,236 @@
import 'package:flutter/material.dart';
/// Svrnty Size System
/// Standard sizing constants for icons, buttons, containers, and other components
class AppSizes {
// Prevent instantiation
AppSizes._();
// ============================================
// ICON SIZES
// ============================================
/// Extra small icon (16px)
static const double iconXs = 16.0;
/// Small icon (20px)
static const double iconSm = 20.0;
/// Standard icon size (24px)
static const double iconMd = 24.0;
/// Large icon size (32px)
static const double iconLg = 32.0;
/// Extra large icon (40px)
static const double iconXl = 40.0;
/// Huge icon (48px)
static const double iconXxl = 48.0;
/// Extra huge icon (56px)
static const double iconXxxl = 56.0;
// ============================================
// BUTTON SIZES
// ============================================
/// Small button height (32px)
static const double buttonHeightSm = 32.0;
/// Medium button height (40px) - Default
static const double buttonHeightMd = 40.0;
/// Large button height (48px)
static const double buttonHeightLg = 48.0;
/// Extra large button height (56px)
static const double buttonHeightXl = 56.0;
// ============================================
// INPUT FIELD SIZES
// ============================================
/// Input field height
static const double inputHeight = 56.0;
/// Compact input field height (no vertical padding)
static const double inputHeightCompact = 40.0;
/// Input field min width
static const double inputMinWidth = 48.0;
// ============================================
// CONTAINER & LAYOUT SIZES
// ============================================
/// Standard card minimum height
static const double cardMinHeight = 80.0;
/// Standard dialog max width (mobile)
static const double dialogMaxWidthMobile = 280.0;
/// Standard dialog max width (tablet/desktop)
static const double dialogMaxWidthDesktop = 560.0;
/// Maximum content width for centered layouts
static const double maxContentWidth = 1200.0;
/// Compact content width (forms, focused layouts)
static const double compactContentWidth = 600.0;
/// Standard container max width
static const double containerMaxWidth = 900.0;
// ============================================
// APPBAR & HEADER SIZES
// ============================================
/// Standard app bar height
static const double appBarHeight = 56.0;
/// Large app bar height
static const double appBarHeightLarge = 72.0;
/// Compact app bar height
static const double appBarHeightCompact = 48.0;
// ============================================
// BOTTOM SHEET SIZES
// ============================================
/// Bottom sheet max width
static const double bottomSheetMaxWidth = 540.0;
/// Bottom sheet default height (auto)
static const double bottomSheetHeightAuto = 0.0;
/// Bottom sheet half screen height
static const double bottomSheetHeightHalf = 0.5;
/// Bottom sheet 3/4 screen height
static const double bottomSheetHeight3Quarter = 0.75;
// ============================================
// ELEVATION & Z-INDEX
// ============================================
/// Standard z-index for floating elements
static const int zIndexFloating = 100;
/// Z-index for modals/dialogs
static const int zIndexModal = 50;
/// Z-index for tooltips
static const int zIndexTooltip = 150;
// ============================================
// DIVIDER & LINE SIZES
// ============================================
/// Divider thickness
static const double dividerThickness = 1.0;
/// Thin divider thickness (0.5px)
static const double dividerThicknessThin = 0.5;
/// Thick divider thickness (2px)
static const double dividerThicknessThick = 2.0;
/// Horizontal divider height
static const double dividerHeightHorizontal = 1.0;
/// Vertical divider width
static const double dividerWidthVertical = 1.0;
// ============================================
// PROGRESS INDICATOR SIZES
// ============================================
/// Progress indicator thickness
static const double progressIndicatorThickness = 4.0;
/// Circular progress indicator size
static const double circularProgressSize = 48.0;
/// Linear progress indicator height (thin)
static const double linearProgressHeightThin = 2.0;
/// Linear progress indicator height (standard)
static const double linearProgressHeightStandard = 4.0;
/// Linear progress indicator height (thick)
static const double linearProgressHeightThick = 8.0;
// ============================================
// CHIP & BADGE SIZES
// ============================================
/// Chip height
static const double chipHeight = 32.0;
/// Small chip height
static const double chipHeightSm = 24.0;
/// Badge size (for counter badges)
static const double badgeSize = 24.0;
/// Badge size (small)
static const double badgeSizeSm = 16.0;
// ============================================
// AVATAR SIZES
// ============================================
/// Small avatar size
static const double avatarSizeSm = 32.0;
/// Medium avatar size
static const double avatarSizeMd = 48.0;
/// Large avatar size
static const double avatarSizeLg = 64.0;
/// Extra large avatar size
static const double avatarSizeXl = 80.0;
// ============================================
// RESPONSIVE SIZING
// ============================================
/// Minimum tap target size (Material guidelines - 48px)
static const double minTapTarget = 48.0;
/// Minimum tap target size for desktop (36px)
static const double minTapTargetDesktop = 36.0;
/// Standard element spacing
static const double elementSpacing = 8.0;
/// Large element spacing
static const double elementSpacingLarge = 16.0;
// ============================================
// UTILITY METHODS
// ============================================
/// Get responsive button height based on device type
static double getButtonHeight(bool isCompact) {
return isCompact ? buttonHeightMd : buttonHeightLg;
}
/// Get responsive dialog max width based on screen width
static double getDialogMaxWidth(double screenWidth) {
return screenWidth < 600 ? dialogMaxWidthMobile : dialogMaxWidthDesktop;
}
/// Get responsive icon size
static double getIconSize({
required bool isCompact,
required bool isLarge,
}) {
if (isLarge) return iconLg;
if (isCompact) return iconSm;
return iconMd;
}
}
+296
View File
@@ -0,0 +1,296 @@
import 'package:flutter/material.dart';
/// Svrnty Spacing System - 4px Grid
/// All spacing, sizing, and border radius values follow a strict 4px grid
class AppSpacing {
// Prevent instantiation
AppSpacing._();
// ============================================
// BASE SPACING SCALE (4px grid)
// ============================================
/// Extra small spacing (4px) - unit × 1
static const double xs = 4.0;
/// Small spacing (8px) - unit × 2
static const double sm = 8.0;
/// Medium spacing (16px) - unit × 4 - DEFAULT
static const double md = 16.0;
/// Large spacing (24px) - unit × 6
static const double lg = 24.0;
/// Extra large spacing (32px) - unit × 8
static const double xl = 32.0;
/// Double extra large (48px) - unit × 12
static const double xxl = 48.0;
/// Triple extra large (64px) - unit × 16
static const double xxxl = 64.0;
// ============================================
// COMPONENT-SPECIFIC SPACING
// ============================================
/// Padding inside cards
static const double cardPadding = md; // 16px
/// Horizontal button padding
static const double buttonPaddingX = lg; // 24px
/// Vertical button padding
static const double buttonPaddingY = 12.0; // sm × 1.5
/// Padding in input fields
static const double inputPadding = md; // 16px
/// Standard icon size
static const double iconSize = lg; // 24px
/// Large icon size
static const double iconSizeLarge = xl; // 32px
/// Dialog content padding
static const double dialogPadding = lg; // 24px
/// Standard app bar height
static const double appBarHeight = 56.0;
/// List item padding
static const double listItemPadding = md; // 16px
// ============================================
// PRE-BUILT EDGEINSETS - ALL SIDES
// ============================================
/// EdgeInsets.all(4px)
static const EdgeInsets paddingAllXs = EdgeInsets.all(xs);
/// EdgeInsets.all(8px)
static const EdgeInsets paddingAllSm = EdgeInsets.all(sm);
/// EdgeInsets.all(16px)
static const EdgeInsets paddingAllMd = EdgeInsets.all(md);
/// EdgeInsets.all(24px)
static const EdgeInsets paddingAllLg = EdgeInsets.all(lg);
/// EdgeInsets.all(32px)
static const EdgeInsets paddingAllXl = EdgeInsets.all(xl);
/// EdgeInsets.all(48px)
static const EdgeInsets paddingAllXxl = EdgeInsets.all(xxl);
// ============================================
// PRE-BUILT EDGEINSETS - HORIZONTAL
// ============================================
/// EdgeInsets.symmetric(horizontal: 4px)
static const EdgeInsets paddingHorizontalXs =
EdgeInsets.symmetric(horizontal: xs);
/// EdgeInsets.symmetric(horizontal: 8px)
static const EdgeInsets paddingHorizontalSm =
EdgeInsets.symmetric(horizontal: sm);
/// EdgeInsets.symmetric(horizontal: 16px)
static const EdgeInsets paddingHorizontalMd =
EdgeInsets.symmetric(horizontal: md);
/// EdgeInsets.symmetric(horizontal: 24px)
static const EdgeInsets paddingHorizontalLg =
EdgeInsets.symmetric(horizontal: lg);
/// EdgeInsets.symmetric(horizontal: 32px)
static const EdgeInsets paddingHorizontalXl =
EdgeInsets.symmetric(horizontal: xl);
// ============================================
// PRE-BUILT EDGEINSETS - VERTICAL
// ============================================
/// EdgeInsets.symmetric(vertical: 4px)
static const EdgeInsets paddingVerticalXs =
EdgeInsets.symmetric(vertical: xs);
/// EdgeInsets.symmetric(vertical: 8px)
static const EdgeInsets paddingVerticalSm =
EdgeInsets.symmetric(vertical: sm);
/// EdgeInsets.symmetric(vertical: 16px)
static const EdgeInsets paddingVerticalMd =
EdgeInsets.symmetric(vertical: md);
/// EdgeInsets.symmetric(vertical: 24px)
static const EdgeInsets paddingVerticalLg =
EdgeInsets.symmetric(vertical: lg);
/// EdgeInsets.symmetric(vertical: 32px)
static const EdgeInsets paddingVerticalXl =
EdgeInsets.symmetric(vertical: xl);
// ============================================
// PRE-BUILT EDGEINSETS - COMPONENT SPECIFIC
// ============================================
/// Card padding (16px all sides)
static const EdgeInsets paddingCard = paddingAllMd;
/// Button padding (horizontal: 24px, vertical: 12px)
static const EdgeInsets paddingButton =
EdgeInsets.symmetric(horizontal: lg, vertical: buttonPaddingY);
/// List item padding (horizontal: 16px, vertical: 8px)
static const EdgeInsets paddingListItem =
EdgeInsets.symmetric(horizontal: md, vertical: sm);
/// Dialog padding (24px all sides)
static const EdgeInsets paddingDialog = paddingAllLg;
// ============================================
// SPACER WIDGETS - UNIVERSAL (SQUARE)
// ============================================
/// SizedBox(width: 4, height: 4)
static const Widget spacerXs = SizedBox(width: xs, height: xs);
/// SizedBox(width: 8, height: 8)
static const Widget spacerSm = SizedBox(width: sm, height: sm);
/// SizedBox(width: 16, height: 16)
static const Widget spacerMd = SizedBox(width: md, height: md);
/// SizedBox(width: 24, height: 24)
static const Widget spacerLg = SizedBox(width: lg, height: lg);
/// SizedBox(width: 32, height: 32)
static const Widget spacerXl = SizedBox(width: xl, height: xl);
// ============================================
// SPACER WIDGETS - VERTICAL
// ============================================
/// SizedBox(height: 4)
static const Widget vSpacerXs = SizedBox(height: xs);
/// SizedBox(height: 8)
static const Widget vSpacerSm = SizedBox(height: sm);
/// SizedBox(height: 16)
static const Widget vSpacerMd = SizedBox(height: md);
/// SizedBox(height: 24)
static const Widget vSpacerLg = SizedBox(height: lg);
/// SizedBox(height: 32)
static const Widget vSpacerXl = SizedBox(height: xl);
/// SizedBox(height: 48)
static const Widget vSpacerXxl = SizedBox(height: xxl);
/// SizedBox(height: 64)
static const Widget vSpacerXxxl = SizedBox(height: xxxl);
// ============================================
// SPACER WIDGETS - HORIZONTAL
// ============================================
/// SizedBox(width: 4)
static const Widget hSpacerXs = SizedBox(width: xs);
/// SizedBox(width: 8)
static const Widget hSpacerSm = SizedBox(width: sm);
/// SizedBox(width: 16)
static const Widget hSpacerMd = SizedBox(width: md);
/// SizedBox(width: 24)
static const Widget hSpacerLg = SizedBox(width: lg);
/// SizedBox(width: 32)
static const Widget hSpacerXl = SizedBox(width: xl);
/// SizedBox(width: 48)
static const Widget hSpacerXxl = SizedBox(width: xxl);
/// SizedBox(width: 64)
static const Widget hSpacerXxxl = SizedBox(width: xxxl);
// ============================================
// GAPS FOR ROW/COLUMN SPACING
// ============================================
/// Gap for Row/Column (4px)
static const double gapXs = xs;
/// Gap for Row/Column (8px)
static const double gapSm = sm;
/// Gap for Row/Column (16px)
static const double gapMd = md;
/// Gap for Row/Column (24px)
static const double gapLg = lg;
/// Gap for Row/Column (32px)
static const double gapXl = xl;
// ============================================
// RESPONSIVE SCREEN MARGINS
// ============================================
/// Screen margin for mobile devices (< 600px)
static const double screenMarginMobile = md; // 16px
/// Screen margin for tablets (600-1024px)
static const double screenMarginTablet = lg; // 24px
/// Screen margin for desktop (> 1024px)
static const double screenMarginDesktop = xl; // 32px
/// Max content width constraint
static const double maxContentWidth = 1200.0;
/// Compact content width for forms/compact layouts
static const double compactContentWidth = 600.0;
// ============================================
// RESPONSIVE PADDING FOR SCREENS
// ============================================
/// Screen padding for mobile
static const EdgeInsets screenPaddingMobile =
EdgeInsets.symmetric(horizontal: screenMarginMobile);
/// Screen padding for tablet
static const EdgeInsets screenPaddingTablet =
EdgeInsets.symmetric(horizontal: screenMarginTablet);
/// Screen padding for desktop
static const EdgeInsets screenPaddingDesktop =
EdgeInsets.symmetric(horizontal: screenMarginDesktop);
// ============================================
// UTILITY METHODS
// ============================================
/// Get responsive screen margin based on screen width
static double getScreenMargin(double screenWidth) {
if (screenWidth < 600) {
return screenMarginMobile;
} else if (screenWidth < 1024) {
return screenMarginTablet;
} else {
return screenMarginDesktop;
}
}
/// Get responsive screen padding based on screen width
static EdgeInsets getScreenPadding(double screenWidth) {
final margin = getScreenMargin(screenWidth);
return EdgeInsets.symmetric(horizontal: margin);
}
}
+331
View File
@@ -0,0 +1,331 @@
import 'package:flutter/material.dart';
/// Svrnty Typography System
/// Extended text styles and typography utilities beyond Material Design 3
class AppTypography {
// Prevent instantiation
AppTypography._();
// ============================================
// FONT FAMILIES
// ============================================
/// Primary font family (Montserrat)
static const String fontFamilyPrimary = 'Montserrat';
/// Monospace font family (IBM Plex Mono)
static const String fontFamilyMono = 'IBMPlexMono';
// ============================================
// FONT WEIGHTS
// ============================================
/// Light font weight (300)
static const FontWeight weightLight = FontWeight.w300;
/// Regular font weight (400)
static const FontWeight weightRegular = FontWeight.w400;
/// Medium font weight (500)
static const FontWeight weightMedium = FontWeight.w500;
/// Semi-bold font weight (600)
static const FontWeight weightSemiBold = FontWeight.w600;
/// Bold font weight (700)
static const FontWeight weightBold = FontWeight.w700;
// ============================================
// FONT SIZES
// ============================================
/// Display Large font size (57px)
static const double sizeDisplayLarge = 57.0;
/// Display Medium font size (45px)
static const double sizeDisplayMedium = 45.0;
/// Display Small font size (36px)
static const double sizeDisplaySmall = 36.0;
/// Headline Large font size (32px)
static const double sizeHeadlineLarge = 32.0;
/// Headline Medium font size (28px)
static const double sizeHeadlineMedium = 28.0;
/// Headline Small font size (24px)
static const double sizeHeadlineSmall = 24.0;
/// Title Large font size (22px)
static const double sizeTitleLarge = 22.0;
/// Title Medium font size (16px)
static const double sizeTitleMedium = 16.0;
/// Title Small font size (14px)
static const double sizeTitleSmall = 14.0;
/// Body Large font size (16px)
static const double sizeBodyLarge = 16.0;
/// Body Medium font size (14px)
static const double sizeBodyMedium = 14.0;
/// Body Small font size (12px)
static const double sizeBodySmall = 12.0;
/// Label Large font size (14px)
static const double sizeLabelLarge = 14.0;
/// Label Medium font size (12px)
static const double sizeLabelMedium = 12.0;
/// Label Small font size (11px)
static const double sizeLabelSmall = 11.0;
// ============================================
// LINE HEIGHTS
// ============================================
/// Display Large line height (1.12 = 64px)
static const double lineHeightDisplayLarge = 1.12;
/// Display Medium line height (1.16 = 52px)
static const double lineHeightDisplayMedium = 1.16;
/// Display Small line height (1.22 = 44px)
static const double lineHeightDisplaySmall = 1.22;
/// Headline Large line height (1.25 = 40px)
static const double lineHeightHeadlineLarge = 1.25;
/// Headline Medium line height (1.29 = 36px)
static const double lineHeightHeadlineMedium = 1.29;
/// Headline Small line height (1.33 = 32px)
static const double lineHeightHeadlineSmall = 1.33;
/// Title Large line height (1.27 = 28px)
static const double lineHeightTitleLarge = 1.27;
/// Title Medium line height (1.5 = 24px)
static const double lineHeightTitleMedium = 1.5;
/// Title Small line height (1.43 = 20px)
static const double lineHeightTitleSmall = 1.43;
/// Body Large line height (1.5 = 24px)
static const double lineHeightBodyLarge = 1.5;
/// Body Medium line height (1.43 = 20px)
static const double lineHeightBodyMedium = 1.43;
/// Body Small line height (1.33 = 16px)
static const double lineHeightBodySmall = 1.33;
/// Label Large line height (1.43 = 20px)
static const double lineHeightLabelLarge = 1.43;
/// Label Medium line height (1.33 = 16px)
static const double lineHeightLabelMedium = 1.33;
/// Label Small line height (1.45 = 16px)
static const double lineHeightLabelSmall = 1.45;
// ============================================
// LETTER SPACING
// ============================================
/// Display Large letter spacing (-0.5px)
static const double letterSpacingDisplayLarge = -0.5;
/// Display Medium letter spacing (-0.5px)
static const double letterSpacingDisplayMedium = -0.5;
/// Display Small letter spacing (-0.25px)
static const double letterSpacingDisplaySmall = -0.25;
/// Headline Large letter spacing (-0.25px)
static const double letterSpacingHeadlineLarge = -0.25;
/// Headline Medium letter spacing (0px)
static const double letterSpacingHeadlineMedium = 0.0;
/// Headline Small letter spacing (0px)
static const double letterSpacingHeadlineSmall = 0.0;
/// Title Large letter spacing (0px)
static const double letterSpacingTitleLarge = 0.0;
/// Title Medium letter spacing (0.15px)
static const double letterSpacingTitleMedium = 0.15;
/// Title Small letter spacing (0.1px)
static const double letterSpacingTitleSmall = 0.1;
/// Body Large letter spacing (0.5px)
static const double letterSpacingBodyLarge = 0.5;
/// Body Medium letter spacing (0.25px)
static const double letterSpacingBodyMedium = 0.25;
/// Body Small letter spacing (0.4px)
static const double letterSpacingBodySmall = 0.4;
/// Label Large letter spacing (0.1px)
static const double letterSpacingLabelLarge = 0.1;
/// Label Medium letter spacing (0.5px)
static const double letterSpacingLabelMedium = 0.5;
/// Label Small letter spacing (0.5px)
static const double letterSpacingLabelSmall = 0.5;
// ============================================
// CUSTOM TEXT STYLES
// ============================================
/// Monospace small text style
static const TextStyle monoSmall = TextStyle(
fontFamily: fontFamilyMono,
fontSize: sizeBodySmall,
fontWeight: weightRegular,
);
/// Monospace medium text style
static const TextStyle monoMedium = TextStyle(
fontFamily: fontFamilyMono,
fontSize: sizeBodyMedium,
fontWeight: weightRegular,
);
/// Monospace large text style
static const TextStyle monoLarge = TextStyle(
fontFamily: fontFamilyMono,
fontSize: sizeBodyLarge,
fontWeight: weightRegular,
);
/// Monospace bold text style
static const TextStyle monoBold = TextStyle(
fontFamily: fontFamilyMono,
fontSize: sizeBodyMedium,
fontWeight: weightBold,
);
/// Code snippet text style
static const TextStyle codeStyle = TextStyle(
fontFamily: fontFamilyMono,
fontSize: sizeBodySmall,
fontWeight: weightRegular,
backgroundColor: Color(0xFFF5F5F5),
);
// ============================================
// TEXT STYLE EXTENSIONS
// ============================================
/// Create a text style with color override
static TextStyle withColor(
TextStyle baseStyle,
Color color,
) {
return baseStyle.copyWith(color: color);
}
/// Create a text style with size override
static TextStyle withSize(
TextStyle baseStyle,
double fontSize,
) {
return baseStyle.copyWith(fontSize: fontSize);
}
/// Create a text style with weight override
static TextStyle withWeight(
TextStyle baseStyle,
FontWeight fontWeight,
) {
return baseStyle.copyWith(fontWeight: fontWeight);
}
/// Create a text style with opacity
static TextStyle withOpacity(
TextStyle baseStyle,
double opacity,
) {
final color = baseStyle.color ?? Colors.black;
return baseStyle.copyWith(
color: color.withOpacity(opacity),
);
}
/// Create a text style with letter spacing override
static TextStyle withLetterSpacing(
TextStyle baseStyle,
double letterSpacing,
) {
return baseStyle.copyWith(letterSpacing: letterSpacing);
}
/// Create a text style with line height override
static TextStyle withLineHeight(
TextStyle baseStyle,
double height,
) {
return baseStyle.copyWith(height: height);
}
/// Create a monospace version of a text style
static TextStyle toMonospace(TextStyle baseStyle) {
return baseStyle.copyWith(
fontFamily: fontFamilyMono,
);
}
/// Create an italic version of a text style
static TextStyle toItalic(TextStyle baseStyle) {
return baseStyle.copyWith(
fontStyle: FontStyle.italic,
);
}
/// Create a strikethrough version of a text style
static TextStyle withStrikethrough(TextStyle baseStyle) {
return baseStyle.copyWith(
decoration: TextDecoration.lineThrough,
);
}
/// Create an underlined version of a text style
static TextStyle withUnderline(TextStyle baseStyle) {
return baseStyle.copyWith(
decoration: TextDecoration.underline,
);
}
/// Create a text style with multiple modifications
static TextStyle merge(
TextStyle baseStyle, {
Color? color,
double? fontSize,
FontWeight? fontWeight,
double? letterSpacing,
double? height,
String? fontFamily,
FontStyle? fontStyle,
TextDecoration? decoration,
}) {
return baseStyle.copyWith(
color: color,
fontSize: fontSize,
fontWeight: fontWeight,
letterSpacing: letterSpacing,
height: height,
fontFamily: fontFamily,
fontStyle: fontStyle,
decoration: decoration,
);
}
}