showCustomModal<T> static method
Muestra un modal personalizado desde abajo (Bottom Sheet)
context es opcional: si no lo pasás, usa GpNavigator.navigatorKey
(requiere tenerlo conectado en tu MaterialApp/Router — ver
GpNavigator). Pasarlo explícito sigue siendo lo recomendado cuando
lo llamás desde dentro de un widget.
Implementation
static Future<T?> showCustomModal<T>({
BuildContext? context,
required Widget child,
double? borderRadius,
Color? backgroundColor,
Duration animationDuration = GpMotion.medium,
Curve animationCurve = GpMotion.emphasized,
bool isScrollControlled = true,
bool dismissible = true,
}) {
final resolvedContext = GpNavigator.resolve(context);
if (resolvedContext == null) return Future.value(null);
final theme = Theme.of(resolvedContext);
final surfaceTheme = theme.gpSurfaceTheme;
return showModalBottomSheet<T>(
context: resolvedContext,
isScrollControlled: isScrollControlled,
backgroundColor: Colors.transparent,
isDismissible: dismissible,
builder: (context) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: animationDuration,
curve: animationCurve,
builder: (context, value, child) {
return Transform.translate(
offset: Offset(0, 50 * (1 - value)),
child: Opacity(opacity: value, child: child),
);
},
child: Container(
decoration: BoxDecoration(
color: backgroundColor ?? theme.colorScheme.surface,
borderRadius: BorderRadius.vertical(
top: Radius.circular(
borderRadius ?? surfaceTheme.panelBorderRadius,
),
),
boxShadow: [
BoxShadow(
color: (surfaceTheme.shadowColor ?? theme.colorScheme.shadow)
.withValues(alpha: surfaceTheme.subtleBorderAlpha),
blurRadius: surfaceTheme.shadowBlurRadius + 12,
offset: const Offset(0, -5),
),
],
),
child: child,
),
);
},
);
}