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 _anim; @override void initState() { super.initState(); _ctrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 1200)) ..repeat(); _anim = Tween(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), ), ); }, ); } }