112 lines
2.7 KiB
Dart
112 lines
2.7 KiB
Dart
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<ProjectButton> createState() => ProjectButtonState();
|
|
}
|
|
|
|
class ProjectButtonState extends State<ProjectButton> 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,
|
|
),
|
|
);
|
|
|
|
}
|
|
}
|