Files
minstrel/flutter_client/lib/likes/like_button.dart
T
bvandeusen 84f16c25f6 feat(ui): Lucide migration unit 1 — dependency + heart (#60)
Design system mandates Lucide, not Material. Foundation before the
mechanical Icons.* sweep:

- pubspec: add flutter_lucide ^1.11.0
- shared/widgets/lucide_heart.dart: LucideHeart renders the verified
  lucide-icons/lucide heart path as outline (stroke) or filled, via
  flutter_svg, tinted by color — Lucide ships no filled heart, so the
  liked state fills the same Lucide silhouette (user-chosen approach)
- like_button: use LucideHeart instead of Icons.favorite/_border
- notification drawables re-derived from the verbatim Lucide heart
  path (border = stroke, filled = fill); separators spaced for
  Android pathData

Unit 2 (mechanical Icons.* -> LucideIcons.* sweep) follows once this
is CI-green. pubspec.lock regenerated by CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:18:22 -04:00

38 lines
981 B
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/endpoints/likes.dart';
import '../shared/widgets/lucide_heart.dart';
import '../theme/theme_extension.dart';
import 'likes_provider.dart';
class LikeButton extends ConsumerWidget {
const LikeButton({
required this.kind,
required this.id,
this.size = 22,
super.key,
});
final LikeKind kind;
final String id;
final double size;
@override
Widget build(BuildContext context, WidgetRef ref) {
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
final state = ref.watch(likedIdsProvider);
final liked = state.maybeWhen(
data: (s) => s.has(kind, id),
orElse: () => false,
);
return IconButton(
icon: LucideHeart(
filled: liked,
color: liked ? fs.accent : fs.ash,
size: size,
),
onPressed: () => ref.read(likesControllerProvider).toggle(kind, id),
);
}
}