mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-11 17:30:00 +02:00
feat: implement login and dashboard screens, introducing GlassContainer and TvFocusableCard widgets.
This commit is contained in:
1 parent
c668eed52a
commit
ae404622ad
4 files changed
+577
-359
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import '../theme/app_theme.dart';
|
||||
|
||||
class GlassContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final EdgeInsetsGeometry padding;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
final double borderRadius;
|
||||
final double opacity;
|
||||
final Color? borderColor;
|
||||
final bool border;
|
||||
|
||||
const GlassContainer({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.width,
|
||||
this.height,
|
||||
this.padding = const EdgeInsets.all(16),
|
||||
this.margin,
|
||||
this.borderRadius = 16.0,
|
||||
this.opacity = 0.6,
|
||||
this.borderColor,
|
||||
this.border = true,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: width,
|
||||
height: height,
|
||||
margin: margin,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
||||
child: Container(
|
||||
padding: padding,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.surface.withOpacity(opacity),
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: border
|
||||
? Border.all(
|
||||
color: borderColor ?? Colors.white.withOpacity(0.1),
|
||||
width: 1,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
class TvFocusableCard extends StatefulWidget {
|
||||
final Widget child;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback? onFocus;
|
||||
final double scaleFactor;
|
||||
final Duration animationDuration;
|
||||
final Color? focusColor;
|
||||
final bool autofocus;
|
||||
final double borderRadius;
|
||||
|
||||
const TvFocusableCard({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.onTap,
|
||||
this.onFocus,
|
||||
this.scaleFactor = 1.05,
|
||||
this.animationDuration = const Duration(milliseconds: 200),
|
||||
this.focusColor,
|
||||
this.autofocus = false,
|
||||
this.borderRadius = 12.0,
|
||||
});
|
||||
|
||||
@override
|
||||
State<TvFocusableCard> createState() => _TvFocusableCardState();
|
||||
}
|
||||
|
||||
class _TvFocusableCardState extends State<TvFocusableCard>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _scaleAnimation;
|
||||
bool _isFocused = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: widget.animationDuration,
|
||||
);
|
||||
_scaleAnimation = Tween<double>(begin: 1.0, end: widget.scaleFactor)
|
||||
.animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _handleFocusChange(bool hasFocus) {
|
||||
if (widget.onFocus != null && hasFocus) {
|
||||
widget.onFocus!();
|
||||
}
|
||||
setState(() {
|
||||
_isFocused = hasFocus;
|
||||
});
|
||||
if (hasFocus) {
|
||||
_controller.forward();
|
||||
} else {
|
||||
_controller.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _scaleAnimation,
|
||||
builder: (context, child) {
|
||||
return Transform.scale(
|
||||
scale: _scaleAnimation.value,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: widget.onTap,
|
||||
onFocusChange: _handleFocusChange,
|
||||
autofocus: widget.autofocus,
|
||||
borderRadius: BorderRadius.circular(widget.borderRadius),
|
||||
focusColor: Colors.transparent, // We handle visual focus manually
|
||||
hoverColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(widget.borderRadius),
|
||||
border: _isFocused
|
||||
? Border.all(
|
||||
color: widget.focusColor ?? AppColors.focusBorder,
|
||||
width: 3,
|
||||
)
|
||||
: Border.all(color: Colors.transparent, width: 3),
|
||||
boxShadow: _isFocused
|
||||
? [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.3),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
BoxShadow(
|
||||
color: (widget.focusColor ?? AppColors.focusBorder).withOpacity(0.2),
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
]
|
||||
: [],
|
||||
),
|
||||
child: widget.child,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user