highcharts / highcharts/highcharts_flutter

HighchartsTreemapSeriesStatesOptions : inactive behavior not working as expected

Open
#72 1 comment 0 reactions 0 assignees View on GitHub
bug investigation planned
Dominant language
Dart
Stars
12
Forks
3
PR merge metrics
No merged PRs in 30d

Description

### Expected behaviour

`HighchartsTreemapSeriesStatesOptions(
inactive: HighchartsSeriesStatesInactiveOptions(enabled: false
),)`

Expecting the inactive behavior to get disabled.

### Actual behaviour

Even after updating the enabled parameter to false, the inactive overlay is still not getting disabled.

### Version

1.1.2

### Affected devices/platforms

Web with Chrome

### Relevant log output

```shell

```

### Relevant code snippet

```dart
class TreemapNode {
final String id;
final String name;
final double? value;
final double? colorValue;
final List? children;

TreemapNode({
required this.id,
required this.name,
this.value,
this.colorValue,
this.children,
});

/// Flatten hierarchical data into Highcharts-compatible flat list
List> toFlatList({String? parentId}) {
final List> list = [];

list.add({
'id': id,
'name': name,
if (parentId != null) 'parent': parentId,
if (value != null) 'value': value,
if (colorValue != null) 'colorValue': colorValue,
});

if (children != null && children!.isNotEmpty) {
for (final child in children!) {
list.addAll(child.toFlatList(parentId: id));
}
}
return list;
}
}

final List treemapData = [
TreemapNode(
id: 'Technology',
name: 'Technology',
value: 305000000,
colorValue: 9.5,
children: [
TreemapNode(
id: 'MSFT', name: 'Microsoft Corp.', value: 2400000, colorValue: 3.8),
TreemapNode(
id: 'GOOGL', name: 'Alphabet Inc.', value: 1600000, colorValue: -1.5),
TreemapNode(
id: 'ADBE', name: 'Adobe Inc.', value: 220000, colorValue: 7.8),
TreemapNode(
id: 'NFLX', name: 'Netflix Inc.', value: 190000, colorValue: -1.8),
TreemapNode(
id: 'CRM', name: 'Salesforce Inc.', value: 200000, colorValue: 4.2),
TreemapNode(
id: 'AAPL', name: 'Apple Inc.', value: 2800000, colorValue: 5.2),
TreemapNode(
id: 'TSLA', name: 'Tesla Inc.', value: 800000, colorValue: 8.7),
TreemapNode(
id: 'NVDA', name: 'NVIDIA Corp.', value: 1200000, colorValue: 12.5),
TreemapNode(
id: 'WIN1', name: 'Big Winner Inc', value: 75000, colorValue: 14.2),
],
),
TreemapNode(
id: 'Financial',
name: 'Financial',
value: 205000000,
colorValue: 4.5,
children: [
TreemapNode(
id: 'JPM', name: 'JPMorgan Chase', value: 450000, colorValue: 1.2),
TreemapNode(
id: 'BAC', name: 'Bank of America', value: 280000, colorValue: -2.1),
TreemapNode(id: 'V', name: 'Visa Inc.', value: 480000, colorValue: 4.5),
TreemapNode(
id: 'MA', name: 'Mastercard Inc.', value: 340000, colorValue: 3.2),
],
),
TreemapNode(
id: 'Healthcare',
name: 'Healthcare',
value: 140500000,
colorValue: -1.3,
children: [
TreemapNode(
id: 'JNJ',
name: 'Johnson and Johnson',
value: 420000,
colorValue: -0.8),
TreemapNode(
id: 'UNH',
name: 'UnitedHealth Group',
value: 520000,
colorValue: 6.1),
],
),
TreemapNode(
id: 'Consumer',
name: 'Consumer',
value: 245000000,
colorValue: 24.5,
children: [
TreemapNode(
id: 'AMZN', name: 'Amazon.com Inc.', value: 1500000, colorValue: 2.1),
TreemapNode(id: 'HD', name: 'Home Depot', value: 350000, colorValue: 1.8),
TreemapNode(
id: 'WMT', name: 'Walmart Inc.', value: 420000, colorValue: 0.9),
TreemapNode(
id: 'PG', name: 'Procter and Gamble', value: 380000, colorValue: 2.3),
TreemapNode(
id: 'DIS', name: 'Walt Disney Co.', value: 180000, colorValue: -3.2),
],
),
TreemapNode(
id: 'Energy',
name: 'Energy',
value: -6.7,
colorValue: 12.5,
children: [
TreemapNode(
id: 'XOM', name: 'Exxon Mobil', value: 450000, colorValue: -4.3),
TreemapNode(
id: 'LOSS1', name: 'Big Loser Corp', value: 50000, colorValue: -8.5),
],
),
];

class SectorHeatmapChart extends StatelessWidget {
const SectorHeatmapChart({super.key});

@override
Widget build(BuildContext context) {
/// ✅ FIX 1 — Only add sectors at root and their children with parent set.
final List> flatData = [];

// Flatten data

for (var sector in treemapData) {
// Add sector itself (Level 1)
flatData.add({
'id': sector.id,
'name': sector.name,
'value': sector.value,
'colorValue': sector.colorValue,
});

// Add children (Level 2)
if (sector.children != null && sector.children!.isNotEmpty) {
for (final company in sector.children!) {
flatData.add({
'id': company.id,
'name': company.name,
'parent': sector.id,
'value': company.value,
// ✅ Don't add colorValue here — prevents sector-level blend
});
}
}
}

/// ✅ FIX 2 — Map the data to Highcharts options
final List dataPoints =
flatData.map((item) {
final double colorValue =
(item['colorValue']?.toDouble() ?? 0.0).clamp(-10.0, 10.0);

// Auto color based on colorValue
String color;
if (colorValue < 0) {
final intensity = (colorValue / -10.0).clamp(0.0, 1.0);
color =
'#${(255).toRadixString(16)}${(80 + (100 * (1 - intensity))).round().toRadixString(16)}${(80 + (100 * (1 - intensity))).round().toRadixString(16)}';
} else if (colorValue > 0) {
final intensity = (colorValue / 10.0).clamp(0.0, 1.0);
color =
'#${(50 + (100 * (1 - intensity))).round().toRadixString(16)}${(200).toRadixString(16)}${(50 + (100 * (1 - intensity))).round().toRadixString(16)}';
} else {
color = '#cccccc';
}

return HighchartsTreemapSeriesDataOptions(
id: item['id'],
name: item['name'],
parent: item['parent'],
value: item['value']?.toDouble(),
colorValue: colorValue,
color: color,
accessibility: HighchartsTreemapSeriesDataAccessibilityOptions(
enabled: true,
description:
'${item['name']}: Market Cap \$${item['value']?.toStringAsFixed(0)}M, Change ${colorValue.toStringAsFixed(1)}%',
),
);
}).toList();

final HighchartsTreemapSeriesOptions treemapOptions =
HighchartsTreemapSeriesOptions(
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
allowTraversingTree: true,
interactByLeaf: false,
borderWidth: 0,
colorByPoint: true,
states: HighchartsTreemapSeriesStatesOptions(
inactive: HighchartsSeriesStatesInactiveOptions(enabled: false
// 👈 disables the grey overlay
),
normal: HighchartsSeriesStatesNormalOptions(),
hover: HighchartsTreemapSeriesStatesHoverOptions(enabled: true)),
levels: [
HighchartsTreemapSeriesLevelsOptions(
level: 1,
layoutAlgorithm: 'squarified',
borderWidth: 2,
borderColor: '#101010',
dataLabels: HighchartsTreemapSeriesLevelsDataLabelsOptions(
enabled: true,
allowOverlap: true,
color: '#FFFFFF',
),
),
HighchartsTreemapSeriesLevelsOptions(
level: 2,
layoutAlgorithm: 'squarified',
borderWidth: 0,
borderColor: '',
dataLabels: HighchartsTreemapSeriesLevelsDataLabelsOptions(
enabled: false,
allowOverlap: true,
color: '#FFFFFF',
),
),
],
);

return HighchartsChart(
HighchartsOptions(
chart: HighchartsChartOptions(type: 'treemap'),
colorAxis: [
HighchartsColorAxisOptions(
min: -10, max: 10, maxColor: "green", minColor: "red")
],
plotOptions: HighchartsPlotOptions(
treemap: HighchartsTreemapSeriesOptions(
states: HighchartsTreemapSeriesStatesOptions(
inactive: HighchartsSeriesStatesInactiveOptions(enabled: false
// 👈 disables the grey overlay
),
normal: HighchartsSeriesStatesNormalOptions(),
hover:
HighchartsTreemapSeriesStatesHoverOptions(enabled: true)),
),
),
tooltip: HighchartsTooltipOptions(
pointFormat: '{point.name}
'
'Market Cap: \${point.value:,.0f}M
'
'Performance: {point.colorValue:.1f}%',
backgroundColor: 'black',
borderColor: 'gray',
borderRadius: 5,
),
series: [
HighchartsTreemapSeries(
name: 'Market Data',
dataPoints: dataPoints,
options: treemapOptions,
),
],
),
javaScriptModules: const [
'https://code.highcharts.com/highcharts.js',
'https://code.highcharts.com/modules/treemap.js',
],
);
}
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the provided SectorHeatmapChart snippet and reproduce the inactive-state behavior in Chrome using version 1.1.2. Inspect how the treemap states are passed through HighchartsTreemapSeriesOptions and plotOptions; done means setting inactive.enabled to false removes the inactive overlay.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
data-visualization, frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.