Files
tripz-llc/apps/driver/lib/core/ui/skeleton.dart
T

105 lines
3.1 KiB
Dart

import 'package:flutter/material.dart';
import '../design/tokens.dart';
/// هيكل التحميل — تأثير نبض على عناصر مستوحاة من الشاشة الفعلية.
/// docs/26 §7
class Skeleton extends StatelessWidget {
const Skeleton({super.key});
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
final baseColor = cs.surfaceContainerHighest;
final highlightColor = cs.surfaceContainerHigh;
return Padding(
padding: const EdgeInsets.all(T.pagePadding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_PulseBox(width: double.infinity, height: 200, base: baseColor, highlight: highlightColor),
const SizedBox(height: T.s16),
_PulseBox(width: 200, height: 20, base: baseColor, highlight: highlightColor),
const SizedBox(height: T.s12),
_PulseBox(width: 140, height: 16, base: baseColor, highlight: highlightColor),
const SizedBox(height: T.s24),
Row(
children: [
_PulseBox(width: 48, height: 48, base: baseColor, highlight: highlightColor, radius: T.rCircle),
const SizedBox(width: T.s12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_PulseBox(width: double.infinity, height: 16, base: baseColor, highlight: highlightColor),
const SizedBox(height: T.s8),
_PulseBox(width: 120, height: 14, base: baseColor, highlight: highlightColor),
],
),
),
],
),
],
),
);
}
}
class _PulseBox extends StatefulWidget {
const _PulseBox({
required this.width,
required this.height,
required this.base,
required this.highlight,
this.radius = 8,
});
final double width;
final double height;
final Color base;
final Color highlight;
final double radius;
@override
State<_PulseBox> createState() => _PulseBoxState();
}
class _PulseBoxState extends State<_PulseBox>
with SingleTickerProviderStateMixin {
late final AnimationController _ctrl;
late final Animation<double> _anim;
@override
void initState() {
super.initState();
_ctrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))
..repeat();
_anim = Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(parent: _ctrl, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_ctrl.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _anim,
builder: (_, __) {
return Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
color: Color.lerp(widget.base, widget.highlight, _anim.value),
borderRadius: BorderRadius.circular(widget.radius),
),
);
},
);
}
}