import 'package:flutter/material.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/widgets/app_icon.dart'; import '../../../core/widgets/pressable.dart'; /// One large, generic shortcut on the home screen. class ShortcutTile extends StatelessWidget { const ShortcutTile({ super.key, required this.title, required this.subtitle, required this.iconAsset, required this.size, required this.assigned, required this.onTap, this.onLongPress, }); final String title; final String? subtitle; final String iconAsset; final double size; final bool assigned; final VoidCallback onTap; final VoidCallback? onLongPress; @override Widget build(BuildContext context) { final colors = context.colors; final theme = Theme.of(context); final placeholder = !assigned; final iconSize = (size * 0.27).clamp(30.0, 46.0); final semantics = StringBuffer(title); if (subtitle != null && subtitle!.isNotEmpty) semantics.write(', $subtitle'); semantics.write('. Tap to open.'); if (onLongPress != null) semantics.write(' Long press to change.'); return Pressable( onTap: onTap, onLongPress: onLongPress, semanticLabel: semantics.toString(), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: size, height: size, decoration: BoxDecoration( color: colors.surface, borderRadius: BorderRadius.circular(size * 0.17), border: Border.all( color: placeholder ? colors.accent.withValues(alpha: 0.16) : colors.border, ), boxShadow: [ BoxShadow( color: colors.shadow.withValues( alpha: Theme.of(context).brightness == Brightness.dark ? 0.2 : 0.04, ), blurRadius: 26, offset: const Offset(0, 10), ), ], ), child: Stack( children: [ Center( child: AppIcon( iconAsset, size: iconSize, color: placeholder ? colors.inkMuted : colors.ink, ), ), if (placeholder) Positioned( top: size * 0.09, right: size * 0.09, child: Container( width: 26, height: 26, decoration: BoxDecoration( color: colors.accent, shape: BoxShape.circle, ), alignment: Alignment.center, child: AppIcon( 'assets/icons/plus.svg', size: 14, color: colors.accentInk, ), ), ), ], ), ), const SizedBox(height: 12), Text( title, maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: theme.textTheme.titleMedium?.copyWith( fontSize: size >= 160 ? 16 : 14, ), ), if (subtitle != null) ...[ const SizedBox(height: 2), SizedBox( height: 17, child: Text( subtitle!, maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: theme.textTheme.bodySmall?.copyWith( color: placeholder ? colors.accent : colors.inkMuted, fontWeight: placeholder ? FontWeight.w600 : FontWeight.w400, fontSize: size >= 160 ? 12 : 11, ), ), ), ], ], ), ); } }