Files
lab-app/lib/features/auth/auth_widgets.dart
T
2026-06-10 23:22:15 +03:00

105 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/theme/app_theme.dart';
/// Animated floating blob background used on auth screens.
/// [bright] = true → white blobs (for dark/gradient backgrounds).
/// [bright] = false → primary/accent blobs (for light backgrounds).
class AnimatedAuthBg extends StatefulWidget {
const AnimatedAuthBg({super.key, this.bright = false});
final bool bright;
@override
State<AnimatedAuthBg> createState() => _AnimatedAuthBgState();
}
class _AnimatedAuthBgState extends State<AnimatedAuthBg>
with SingleTickerProviderStateMixin {
late AnimationController _ctrl;
late Animation<double> _anim;
@override
void initState() {
super.initState();
_ctrl = AnimationController(
vsync: this,
duration: const Duration(seconds: 8),
)..repeat(reverse: true);
_anim = CurvedAnimation(parent: _ctrl, curve: Curves.easeInOut);
}
@override
void dispose() {
_ctrl.dispose();
super.dispose();
}
Color _blob(double alpha) => widget.bright
? Colors.white.withValues(alpha: alpha * 1.5)
: AppColors.primary.withValues(alpha: alpha);
Color _blobAccent(double alpha) => widget.bright
? Colors.white.withValues(alpha: alpha * 1.2)
: AppColors.accent.withValues(alpha: alpha);
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _anim,
builder: (_, __) {
final t = _anim.value;
return Stack(
children: [
Positioned(
top: -80 + t * 30,
left: -60 + t * 20,
child: AuthBlob(size: 300, color: _blob(0.08)),
),
Positioned(
top: 200 - t * 40,
right: -100 + t * 25,
child: AuthBlob(size: 250, color: _blobAccent(0.06)),
),
Positioned(
bottom: 100 + t * 30,
left: 50 - t * 15,
child: AuthBlob(size: 200, color: _blob(0.05)),
),
Positioned(
bottom: -50 + t * 20,
right: -50 + t * 10,
child: AuthBlob(size: 280, color: _blobAccent(0.07)),
),
Positioned(
top: 350 + t * 25,
left: 80 + t * 20,
child: AuthBlob(size: 160, color: _blob(0.04)),
),
Positioned(
top: -40 - t * 10,
left: 120 + t * 30,
child: AuthBlob(size: 180, color: _blobAccent(0.05)),
),
],
);
},
);
}
}
/// A simple solid circle used as a background blob.
class AuthBlob extends StatelessWidget {
const AuthBlob({super.key, required this.size, required this.color});
final double size;
final Color color;
@override
Widget build(BuildContext context) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
);
}
}