import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'colors.dart'; /// ----------------------------------------------------------------------------- /// Intaleq Design Tokens /// ----------------------------------------------------------------------------- /// A single source of truth for spacing, radii, shadows, durations and the /// shared bottom-sheet surface used across the passenger map overlays. /// /// Goal: kill the "magic numbers" scattered across every map widget /// (radii of 15/24/25, ad-hoc shadows, handles that appear only sometimes) /// so all sheets read as ONE consistent product — the way Uber / Careem / Bolt /// feel like a single system rather than a pile of separate screens. /// /// Everything here is additive. Existing widgets keep working untouched; new /// and refactored widgets opt in. /// 4pt spacing scale. Use these instead of raw `SizedBox(height: 10)`. class AppSpacing { AppSpacing._(); static const double xs = 4; static const double sm = 8; static const double md = 12; static const double lg = 16; static const double xl = 20; static const double xxl = 24; // Convenience gaps (const so they can live in const child lists). static const Widget gapXs = SizedBox(height: xs, width: xs); static const Widget gapSm = SizedBox(height: sm, width: sm); static const Widget gapMd = SizedBox(height: md, width: md); static const Widget gapLg = SizedBox(height: lg, width: lg); static const Widget gapXl = SizedBox(height: xl, width: xl); static const Widget vGapXs = SizedBox(height: xs); static const Widget vGapSm = SizedBox(height: sm); static const Widget vGapMd = SizedBox(height: md); static const Widget vGapLg = SizedBox(height: lg); static const Widget vGapXl = SizedBox(height: xl); } /// Corner radii. `sheet` is THE radius for every bottom sheet so they all match. class AppRadii { AppRadii._(); static const double sm = 8; static const double md = 12; static const double lg = 16; static const double sheet = 24; static const double pill = 999; static const BorderRadius sheetTop = BorderRadius.only( topLeft: Radius.circular(sheet), topRight: Radius.circular(sheet), ); static BorderRadius all(double r) => BorderRadius.circular(r); } /// Shared elevation. One shadow for sheets, one for cards — no more per-widget /// hand-tuned `BoxShadow`s (and no neumorphic accent-color shadows). class AppShadows { AppShadows._(); static List get sheet => [ BoxShadow( color: Colors.black.withValues( alpha: Get.isDarkMode ? 0.45 : 0.12, ), blurRadius: 24, spreadRadius: 1, offset: const Offset(0, -4), ), ]; static List get card => [ BoxShadow( color: Colors.black.withValues( alpha: Get.isDarkMode ? 0.30 : 0.06, ), blurRadius: 12, offset: const Offset(0, 4), ), ]; } /// Motion durations. Keep sheet slide-in/out consistent everywhere. class AppDurations { AppDurations._(); static const Duration fast = Duration(milliseconds: 200); static const Duration base = Duration(milliseconds: 300); static const Duration slow = Duration(milliseconds: 450); } /// Minimum touch target (Material / iOS HIG guidance is 44–48px). class AppSizes { AppSizes._(); static const double minTouch = 48; } /// ----------------------------------------------------------------------------- /// Shared bottom-sheet surface /// ----------------------------------------------------------------------------- /// The rounded-top card + shadow + optional drag handle that every map sheet /// draws by hand today. Wrap your content in this and all sheets instantly /// share the same radius, shadow, handle and horizontal rhythm. /// /// It does NOT own show/hide animation — each caller keeps its own /// AnimatedPositioned / transform logic so behaviour is unchanged. class IntaleqSheetSurface extends StatelessWidget { const IntaleqSheetSurface({ super.key, required this.child, this.padding = const EdgeInsets.fromLTRB(AppSpacing.xl, AppSpacing.md, AppSpacing.xl, AppSpacing.lg), this.showHandle = true, this.color, }); final Widget child; final EdgeInsets padding; final bool showHandle; final Color? color; @override Widget build(BuildContext context) { return Container( width: double.infinity, decoration: BoxDecoration( color: color ?? AppColor.cardColor, borderRadius: AppRadii.sheetTop, boxShadow: AppShadows.sheet, ), padding: padding, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (showHandle) ...[ const IntaleqSheetHandle(), AppSpacing.vGapMd, ], child, ], ), ); } } /// The little grab handle at the top of a sheet. Consistent size everywhere. class IntaleqSheetHandle extends StatelessWidget { const IntaleqSheetHandle({super.key}); @override Widget build(BuildContext context) { return Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: AppColor.grayColor.withValues(alpha: 0.35), borderRadius: BorderRadius.circular(AppRadii.pill), ), ), ); } }