Skip to content

feat(legend): add "list" layout for horizontal legends#2784

Merged
maryam-saeidi merged 66 commits intoelastic:mainfrom
maryam-saeidi:kibana-238777-list-legend
Feb 25, 2026
Merged

feat(legend): add "list" layout for horizontal legends#2784
maryam-saeidi merged 66 commits intoelastic:mainfrom
maryam-saeidi:kibana-238777-list-legend

Conversation

@maryam-saeidi
Copy link
Copy Markdown
Member

@maryam-saeidi maryam-saeidi commented Jan 27, 2026

Summary

A new List legend layout is now available for horizontal legends (top/bottom), offering a more space-efficient alternative to the existing GridList/Table layout. In the list layout each legend item flows inline — label, color marker, and values are arranged in a compact row that wraps naturally, making it easier to scan many series without excessive scrolling.

The list layout supports all standard legend features: series highlighting, filtering via actions, CurrentAndLastValue display with stable column widths, and label truncation.

image

Example usage

<Chart>
    <Settings
        showLegend
        legendPosition={Position.Bottom}
        legendLayout="list"  // <-- new prop
        legendValues={[LegendValue.CurrentAndLastValue]}
    />
    <Axis id="bottom" position={Position.Bottom} />
    <Axis id="left" position={Position.Left} />
    <BarSeries
        id="bars"
        xScaleType={ScaleType.Ordinal}
        yScaleType={ScaleType.Linear}
        xAccessor={0}
        yAccessors={[1]}
        data={[
            ["A", 10],
            ["B", 20],
            ["C", 15],
        ]}
    />
</Chart>

Demo

Screen.Recording.2026-02-17.at.10.40.26.mov

Details

Layout & rendering

  • Added legendLayout: 'list' option to the Settings spec, enabling the list layout for horizontal legends
  • Created LegendList component (legend_list.tsx) that renders legend items as inline <li> elements with label, color, values, and optional action grouped together
  • Legend values display a title prefix in list layout (e.g. VALUE: 42, AVG: 10)
  • CurrentAndLastValue shows a placeholder when no value is available (e.g. on hover)
  • Labels are truncated by pixel width limit in list layout (controlled by theme.legend.labelOptions.widthLimit)

Stable column widths

  • Added getLegendMaxFormattedValue to the ChartSelectors interface, allowing each chart type to provide the longest formatted Y domain value
  • Implemented the XY chart selector that formats the max Y domain value through each series' tick formatter and returns the longest result
  • The max formatted value width is computed via canvas text measurement (withTextMeasure) and used as minWidth on CurrentAndLastValue cells, preventing layout shift on hover

Legend sizing

  • Added computeHorizontalLegendRowCount utility that measures items and lays them out greedily row-by-row to determine if the legend fits in 1, 2, or 3+ rows — short-circuiting as soon as a third row is reached
  • Legend height is computed based on the row count (single-line, two-line, or multi-line)
  • Added shouldDisplayGridList and shouldDisplayTable helpers to select the correct layout mode based on legend values, position, and layout config

Other

  • Renamed _legend.scss_legend_grid_list.scss for clarity
  • Added storybook story for the new layout (2_legend_layout.story.tsx)
  • Added unit tests for computeHorizontalLegendRowCount and the shouldDisplay* helpers

Issues

Related to elastic/kibana#238777

Checklist

  • The proper feature labels have been added (e.g. :interactions, :axis)
  • All related issues have been linked (i.e. closes #123, fixes #123)
  • New public API exports have been added to packages/charts/src/index.ts
  • Unit tests have been added or updated to match the most common scenarios
  • The proper documentation and/or storybook story has been added or updated
  • The code has been checked for cross-browser compatibility (Chrome, Firefox, Safari, Edge)
  • Visual changes have been tested with light and dark themes

🤖 This pull request was assisted by Cursor

@maryam-saeidi maryam-saeidi self-assigned this Jan 27, 2026
@maryam-saeidi maryam-saeidi added the :legend Legend related issue label Jan 27, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new "list" layout option for chart legends to improve space efficiency and usability when displaying many data series. The list layout is now the default for legends positioned at the top or bottom, while maintaining backward compatibility through an optional legendLayout prop that allows users to switch between list and table views.

Changes:

  • Added new LegendLayout enum with List and Table options as a public API
  • Implemented list-based legend rendering with horizontal wrapping for top/bottom positions
  • Enhanced label truncation to support both line-based and pixel-based width limits

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/charts/src/utils/common.tsx Defines new LegendLayout enum and Layout type
packages/charts/src/specs/settings.tsx Adds legendLayout prop to LegendSpec interface
packages/charts/src/utils/themes/theme.ts Extends LegendLabelOptions with widthLimit property and makes maxLines optional
packages/charts/src/components/legend/legend.tsx Updates rendering logic to conditionally render grid list or list layout
packages/charts/src/components/legend/legend_item_list.tsx New component implementing horizontal list layout for legends
packages/charts/src/components/legend/label.tsx Enhances label truncation with pixel-based width limiting
packages/charts/src/common/legend.ts Adds logic to determine when to display table vs grid list vs list layouts
packages/charts/src/state/selectors/get_legend_size.ts Improves legend height calculation for multi-row list layouts
storybook/stories/legend/2_legend_layout.story.tsx New story demonstrating the legend layout feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@maryam-saeidi
Copy link
Copy Markdown
Member Author

buildkite update vrt

Copy link
Copy Markdown
Collaborator

@markov00 markov00 left a comment

Choose a reason for hiding this comment

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

Thanks for this PR, it really finally improves the Legend in charts.
I've added a couple of comments to be validated/fixed.
I believe there are also a couple of follow ups to fix (adding them after this PR is merged) to improve it:

  • in list mode when you click and disable/hide the items and you have legend values, the legend values of the other series are hidden, causing the legend to shrink. Is a bad UX, we should keep the legend value visible even when hidden
Screen.Recording.2026-02-24.at.17.38.44.mp4
  • the table layout has some issues with its sizing causing the legend to show horizontal scrollbars. It looks like a padding problem of echLegendTable__cell removing this and adding a grid_gap fixes it, but causes another small visible issue in the table header bottom border.
  • (DX) the storybook multiselect knob we are using for the legend values doesn't allow us to remove completely the values and see the default behaviour without values. we should find a quick way to fix it.

@elastic-datavis
Copy link
Copy Markdown
Contributor

@markov00 markov00 self-requested a review February 25, 2026 09:47
Copy link
Copy Markdown
Collaborator

@markov00 markov00 left a comment

Choose a reason for hiding this comment

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

Changes Looks good to me.
There should be a couple of follows ups as wrote in my last review, but overall looks good.
@maryam-saeidi can you please create an issue for the follow ups so we can keep track of them? thanks

@maryam-saeidi maryam-saeidi merged commit 8967ce3 into elastic:main Feb 25, 2026
14 checks passed
@maryam-saeidi maryam-saeidi deleted the kibana-238777-list-legend branch February 25, 2026 10:34
nickofthyme pushed a commit that referenced this pull request Feb 26, 2026
# [71.2.0](v71.1.2...v71.2.0) (2026-02-26)

### Bug Fixes

* **metric:** update badge to pill shape with adjusted padding ([#2786](#2786)) ([80be269](80be269))
* **theme:** expose font weight in text style ([#2788](#2788)) ([02f4afa](02f4afa))

### Features

* **legend:** add "list" layout for horizontal legends ([#2784](#2784)) ([8967ce3](8967ce3))
* **legend:** add legendActionOnHover option to show actions on hover ([#2773](#2773)) ([d1be88f](d1be88f))
maryam-saeidi added a commit to elastic/kibana that referenced this pull request Feb 27, 2026
## Summary

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@elastic/charts](https://togithub.com/elastic/elastic-charts) |
dependencies | minor | [`71.1.2` ->
`71.2.0`](elastic/elastic-charts@v71.1.2...v71.2.0)
|


---

### Release Notes
##
[71.2.0](elastic/elastic-charts@v71.1.2...v71.2.0)
(2026-02-26)


### Bug Fixes

* **metric:** update badge to pill shape with adjusted padding
([#2786](elastic/elastic-charts#2786))
([80be269](elastic/elastic-charts@80be269))
* **theme:** expose font weight in text style
([#2788](elastic/elastic-charts#2788))
([02f4afa](elastic/elastic-charts@02f4afa))


### Features

* **legend:** add "list" layout for horizontal legends
([#2784](elastic/elastic-charts#2784))
([8967ce3](elastic/elastic-charts@8967ce3))
* **legend:** add legendActionOnHover option to show actions on hover
([#2773](elastic/elastic-charts#2773))
([d1be88f](elastic/elastic-charts@d1be88f))
qn895 pushed a commit to qn895/kibana that referenced this pull request Mar 11, 2026
## Summary

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@elastic/charts](https://togithub.com/elastic/elastic-charts) |
dependencies | minor | [`71.1.2` ->
`71.2.0`](elastic/elastic-charts@v71.1.2...v71.2.0)
|


---

### Release Notes
##
[71.2.0](elastic/elastic-charts@v71.1.2...v71.2.0)
(2026-02-26)


### Bug Fixes

* **metric:** update badge to pill shape with adjusted padding
([elastic#2786](elastic/elastic-charts#2786))
([80be269](elastic/elastic-charts@80be269))
* **theme:** expose font weight in text style
([elastic#2788](elastic/elastic-charts#2788))
([02f4afa](elastic/elastic-charts@02f4afa))


### Features

* **legend:** add "list" layout for horizontal legends
([elastic#2784](elastic/elastic-charts#2784))
([8967ce3](elastic/elastic-charts@8967ce3))
* **legend:** add legendActionOnHover option to show actions on hover
([elastic#2773](elastic/elastic-charts#2773))
([d1be88f](elastic/elastic-charts@d1be88f))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request :legend Legend related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Lens] New "List" legend by default

4 participants