import 'package:flutter/material.dart'; import 'package:patbond_flutter/core/theme/app_theme.dart'; /// 点赞 / 收藏按钮语义变体(05 号规范 §3.5:同一组件,图标与语义色 /// 参数化)。点赞激活 = `error` 图标 + `errorDark` 计数(demo 的 /// `Colors.red` 3.13:1 修订弃用,D6);收藏激活 = `accentDark` 同色。 enum LikeButtonVariant { like( inactiveIcon: Icons.favorite_border, activeIcon: Icons.favorite, activeIconColor: AppColors.error, activeCountColor: AppColors.errorDark, ), bookmark( inactiveIcon: Icons.bookmark_border, activeIcon: Icons.bookmark, activeIconColor: AppColors.accentDark, activeCountColor: AppColors.accentDark, ); const LikeButtonVariant({ required this.inactiveIcon, required this.activeIcon, required this.activeIconColor, required this.activeCountColor, }); final IconData inactiveIcon; final IconData activeIcon; final Color activeIconColor; final Color activeCountColor; } /// 点赞/收藏交互钮(05 号规范 §3.5 静态规格):图标 20 + 计数 13/w600, /// 未激活一律 `inkSoft`(6.59:1)。触控 44×44 由 padding 撑足。 /// /// T3-14 只做展示([onPressed] 传 null 即禁用态,仍按正常色渲染计数与 /// 状态);乐观更新动画与 ToggleSync 接线属 T3-15/16。 class LikeButton extends StatelessWidget { const LikeButton({ required this.variant, required this.active, required this.count, super.key, this.onPressed, this.semanticLabel, }); final LikeButtonVariant variant; final bool active; final int count; final VoidCallback? onPressed; final String? semanticLabel; @override Widget build(BuildContext context) { final iconColor = active ? variant.activeIconColor : AppColors.inkSoft; final countColor = active ? variant.activeCountColor : AppColors.inkSoft; return Semantics( label: semanticLabel, button: onPressed != null, child: InkWell( onTap: onPressed, borderRadius: BorderRadius.circular(AppRadius.pill), child: ConstrainedBox( constraints: const BoxConstraints(minWidth: 44, minHeight: 44), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( active ? variant.activeIcon : variant.inactiveIcon, size: 20, color: iconColor, ), const SizedBox(width: 4), Text( '$count', style: TextStyle( color: countColor, fontSize: 13, fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ); } }