Skip to content

Conversation

@jsilll
Copy link
Contributor

@jsilll jsilll commented Sep 16, 2025

Description

Introduces support for dual-axis chart legends, which properly groups and separates legend items based on which Y-axis they belong to.

Key changes:

  • Added oppositeAxis property to legend items to track which Y-axis a series belongs to
  • Updated the chart legend component to display two separate groups of legend items for dual-axis charts
  • Enhanced legend styles to support the new dual-axis layout with appropriate spacing and dividers
  • Added a new demo page showing a dual-axis chart with multiple series on each axis

@pan-kot
Copy link
Member

pan-kot commented Sep 17, 2025

@jsilll some of the existing pages are failing with errors, e.g. the /#/05-demos/website-playground-examples

@pan-kot
Copy link
Member

pan-kot commented Sep 17, 2025

Should the separator line be in the middle between two legends?

Screenshot 2025-09-17 at 10 13 53

@pan-kot
Copy link
Member

pan-kot commented Sep 17, 2025

@jsilll, that is not directly related, but should "Legend bottom max height" include legend's title and the margin between title and items? Currently, only the items are included.

Edit: it turns out, the question was related. In the current implementation, the entire legend is covered by the max height setting.

items={legendItems}
actions={actions}
position={position}
bottomMaxHeight={bottomMaxHeight}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we implement the legend layout inside the legend itself? Instead of passing the bottomMaxHeight down to the legend, you can give extra slot in the chart-container, so that it can render either a single or a double legend.

return null;
}

// TODO: surface the type and defaultTitle and oppositeTitle props
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this comment be removed or is there something still planned?

const resizeObserver = new ResizeObserver((entries) => {
if (entries.length > 0) {
const width = entries[0].borderBoxSize?.[0].inlineSize;
setShouldStack(width < 400);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why id it 400px? Let's extract this into a constant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, 400 was simply my choice for the threshold, let's agree on a sensible value.

if (!containerRef.current) {
return;
}
const resizeObserver = new ResizeObserver((entries) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CDS has useContainerQuery and useResizeObserver utils that can be used instead of this custom code.

tabIndex={-1}
ref={containerRef}
style={{
overflow: "auto",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline styles can only be used when the values are computed dynamically. The overflow: auto should be added via classes instead

}

.legend-dual-group {
inline-size: calc(50% - 20px);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add a comment explaining the values here. Or, better, you can extract the 20px (or 40px) into a variable. E.g. some $legend-horizontal-padding: 40px, and then inline-size: calc(50% - $legend-horizontal-padding / 2)

@georgylobko georgylobko marked this pull request as draft October 24, 2025 09:58
@jsilll jsilll closed this Oct 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants