Skip to content

Legend pointStyle: 'line' does not apply dataset borderDash pattern #12291

Description

@jklaus-work

Expected behavior

When using usePointStyle: true with pointStyle: 'line' in legend labels, the legend line segment should render with the same borderDash pattern as the dataset it represents (e.g., dashed lines should appear dashed in the legend).

Current behavior

The legend renders a solid line segment regardless of the dataset's borderDash setting. Only the color and width are inherited — the dash pattern is ignored.

Reproducible sample

Inline code sample provided below (no external link needed).

Optional extra steps/info to reproduce

Steps to Reproduce

  const options = {
    plugins: {
      legend: {
        labels: {
          usePointStyle: true,
          pointStyle: 'line',
          pointStyleWidth: 40,
        },
      },
    },
  };

  const data = {
    datasets: [
      {
        label: 'Solid Line',
        borderColor: '#1a5276',
        borderWidth: 2,
        // no borderDash — should render solid in legend ✓
      },
      {
        label: 'Dashed Line',
        borderColor: '#e74c3c',
        borderWidth: 2,
        borderDash: [6, 3],
        // should render dashed in legend ✗ (renders solid)
      },
    ],
  };

Possible solution

The fix would be to pass lineDash into drawPointLegend (via the options parameter) and apply it before stroking:

  // In drawPointLegend, before the switch statement:
  if (options.lineDash) {
    ctx.setLineDash(options.lineDash);
  } else {
    ctx.setLineDash([]);
  }

  // ... existing switch/case logic ...

  // After ctx.stroke():
  ctx.setLineDash([]); // reset

The drawOptions object constructed in the legend plugin's draw method (where drawPointLegend is called) would need to include the lineDash property from the legend item:

  // In the legend plugin draw method, where drawOptions is constructed:
  const drawOptions = {
      radius: boxHeight * Math.SQRT2 / 2,
      pointStyle: legendItem.pointStyle,
      rotation: legendItem.rotation,
      borderWidth: lineWidth,
      lineDash: legendItem.lineDash || [],       // ← add this
      lineDashOffset: legendItem.lineDashOffset || 0,  // ← and this
  };

This ensures the dash context is explicitly set within drawPointLegend rather than relying on it being set in the parent scope and surviving through the beginPath() call.

Context

RCA
In the legend rendering code, ctx.setLineDash(valueOrDefault(legendItem.lineDash, [])) is called before the if (labelOpts.usePointStyle) branch. However, drawPointLegend() (in helpers.dataset.js) for case 'line' calls ctx.beginPath() then
ctx.moveTo/lineTo and relies on the parent ctx.stroke(). The lineDash context IS set, but it appears not to be applied to the point-style rendering path.

When usePointStyle: false (box rendering), dashes render correctly on the legend box — confirming legendItem.lineDash is populated. It's only the drawPointLegend path that doesn't produce dashed output.

chart.js version

v4.5.1

Browser name and version

Chrome (all browsers affected - it's a canvas rendering path issue)

Link to your project

Can't share but the framework is Angular 21 via ng2-charts (not framework specific)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions