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>
297 lines
8.9 KiB
Dart
297 lines
8.9 KiB
Dart
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);
|
||
}
|
||
}
|