buildFluentChartPopoverMultiValue function

Widget buildFluentChartPopoverMultiValue(
  1. FluentChartPopoverData data,
  2. FluentChartPopoverStyle style,
  3. Color fallbackForeground
)

Builds the stacked popover body. ChartPopover.tsx:116-165.

fallbackForeground is colorNeutralForeground1, the false arm of ChartPopover.tsx:257.

Implementation

Widget buildFluentChartPopoverMultiValue(
  FluentChartPopoverData data,
  FluentChartPopoverStyle style,
  Color fallbackForeground,
) {
  const states = <WidgetState>{};
  final values = data.yValues ?? const <FluentYValueHover>[];
  final hasSubCounts = fluentChartPopoverHasSubCounts(values);

  final rows = <Widget>[
    for (var index = 0; index < values.length; index++)
      _popoverRow(
        values[index],
        style,
        fallbackForeground,
        popoverColour: data.color,
        culture: data.culture,
        hasSubCounts: hasSubCounts,
        // ChartPopover.tsx:187 — every column but the last carries a 16px
        // trailing margin.
        isLast: index == values.length - 1,
      ),
  ];

  // ChartPopover.tsx:128 formats `hoverXValue`, which upstream's charts hand
  // over raw. Here the chart has already formatted it, as it has every text
  // field, and formatting it again would read a de-DE `15.000` back as 15.
  final xValue = data.xValue ?? '';

  // `calloutContentRoot` is a grid (useChartPopoverStyles.styles.ts:34), so
  // every block in it — each row wrapper included — is as wide as the widest,
  // and a row's bottom rule runs the full width of the body.
  return IntrinsicWidth(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Padding(
          // ChartPopover.tsx:122 — 11px below the date container, but only
          // when subcounts exist. The same 11 as the single-value accent bar
          // margin. An empty reading lays out no line box, as at :63.
          padding: EdgeInsets.only(
            bottom: hasSubCounts ? kChartPopoverAccentBarMarginTop : 0,
          ),
          child: xValue.isEmpty
              ? null
              : Text(xValue, style: style.xTextStyle!.resolve(states)),
        ),
        // ChartPopover.tsx:131 — subcounts lay the rows out as a flex row;
        // otherwise they stack.
        if (hasSubCounts)
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: rows,
          )
        else
          Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.min,
            children: rows,
          ),
        // ChartPopover.tsx:161 renders the description INSIDE the row wrapper
        // here, unlike the single-value path where it is a sibling at :106.
        if (data.descriptionMessage != null)
          Text(
            data.descriptionMessage!,
            style: style.descriptionTextStyle!.resolve(states),
          ),
      ],
    ),
  );
}