Skip to content

Commit cf9d4bf

Browse files
committed
feat: Make legend interactive by allowing drill-down on tap
1 parent 00aa424 commit cf9d4bf

3 files changed

Lines changed: 41 additions & 27 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ A powerful, interactive, and highly customizable Circle Pack Chart (Circular Tre
2222
- **Anti-Scaled Consistency:** Labels maintain a constant visual size on screen regardless of the zoom level.
2323
- **Visibility Toggle:** Control whether values are shown inside circles using the `showValue` flag.
2424
- **✨ Dynamic Opacity:** Automatically scales child circle opacity based on their relative values, visually highlighting more important data points.
25-
- **📋 Dynamic Legend:** Includes a built-in vertical legend component that automatically updates to reflect labels and display values of the currently focused level.
25+
- **📋 Interactive Legend:** Includes a built-in vertical legend component that automatically updates to reflect labels and display values. Tapping a legend item triggers a drill-down into that category.
2626

2727
## 📦 Installation
2828

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ packages:
108108
path: ".."
109109
relative: true
110110
source: path
111-
version: "2.0.0"
111+
version: "2.0.1"
112112
flutter_lints:
113113
dependency: "direct dev"
114114
description:

lib/flutter_circle_pack_chart_legend.dart

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,48 @@ class FlutterCirclePackChartLegend extends StatelessWidget {
3434
),
3535
...children.map((node) {
3636
final Color color = node.color ?? parentColor;
37-
return Padding(
38-
padding: const EdgeInsets.symmetric(vertical: 4.0),
39-
child: Row(
40-
mainAxisSize: MainAxisSize.min,
41-
children: [
42-
Container(
43-
width: 14,
44-
height: 12, // Slightly wider for a "pill" or just 12x12
45-
decoration: BoxDecoration(
46-
color: color.withValues(alpha: 0.8),
47-
borderRadius: BorderRadius.circular(4),
37+
final bool canDrill = node.children.isNotEmpty;
38+
39+
return InkWell(
40+
onTap: canDrill ? () => controller.drillDown(node) : null,
41+
borderRadius: BorderRadius.circular(8),
42+
child: Padding(
43+
padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 8.0),
44+
child: Row(
45+
children: [
46+
Container(
47+
width: 14,
48+
height: 12,
49+
decoration: BoxDecoration(
50+
color: color.withValues(alpha: 0.8),
51+
borderRadius: BorderRadius.circular(4),
52+
),
4853
),
49-
),
50-
const SizedBox(width: 12),
51-
Text(
52-
node.label,
53-
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
54-
fontWeight: FontWeight.w500,
54+
const SizedBox(width: 12),
55+
Expanded(
56+
child: Text(
57+
node.label,
58+
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
59+
fontWeight: FontWeight.w500,
60+
),
61+
),
5562
),
56-
),
57-
const Spacer(),
58-
Text(
59-
node.displayValue ?? node.value.toStringAsFixed(0),
60-
style: Theme.of(context).textTheme.bodySmall?.copyWith(
61-
color: Colors.grey,
63+
Text(
64+
node.displayValue ?? node.value.toStringAsFixed(0),
65+
style: Theme.of(context).textTheme.bodySmall?.copyWith(
66+
color: Colors.grey,
67+
),
6268
),
63-
),
64-
],
69+
if (canDrill) ...[
70+
const SizedBox(width: 8),
71+
Icon(
72+
Icons.chevron_right,
73+
size: 14,
74+
color: Colors.grey.withValues(alpha: 0.5),
75+
),
76+
],
77+
],
78+
),
6579
),
6680
);
6781
}),

0 commit comments

Comments
 (0)