import "package:shadcn_flutter/shadcn_flutter.dart"; import '../../utils/format_relative_time.dart'; class ProjectButton extends StatefulWidget { final String label; final VoidCallback? onPressed; final DateTime? lastMessage; final bool collapsed; ProjectButton({ required this.label, this.onPressed, this.lastMessage, this.collapsed = false, }); @override State createState() => ProjectButtonState(); } class ProjectButtonState extends State with TickerProviderStateMixin { bool _isHovering = false; late AnimationController _chevronController; @override void initState() { super.initState(); _chevronController = AnimationController( duration: Duration(milliseconds: 100), vsync: this, ); if (!widget.collapsed) { _chevronController.forward(); } } @override void didUpdateWidget(ProjectButton oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.collapsed != widget.collapsed) { if (widget.collapsed) { _chevronController.reverse(); } else { _chevronController.forward(); } } } @override void dispose() { _chevronController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { ColorScheme colorScheme = Theme.of(context).colorScheme; return SizedBox( width: double.infinity, child: Button( style: ButtonStyle.ghost().copyWith( padding: (context, state, edgeInsets) { return EdgeInsets.only( top: 8, left: 12, bottom: 8, right: 12 ); } ), disableFocusOutline: true, onPressed: () { if (widget.onPressed != null) { widget.onPressed!(); } }, onHover: (isHovering) { setState(() { _isHovering = isHovering; }); }, leading: !_isHovering ? Icon( !widget.collapsed ? LucideIcons.folderOpen : LucideIcons.folderClosed ).iconSmall : RotationTransition( turns: Tween(begin: 0.0, end: 0.25).animate(_chevronController), child: Icon( LucideIcons.chevronRight, color: colorScheme.mutedForeground, ).iconSmall, ), trailingGap: 32, trailing: widget.lastMessage != null ? Text( formatRelativeTime(widget.lastMessage!) ).muted : null, child: Text( widget.label, style: TextStyle( color: colorScheme.mutedForeground ), maxLines: 1, overflow: TextOverflow.ellipsis, ).small, ), ); } }