Skip to content

feat(core/ix-select): Add +1 chip#2371

Closed
lzeiml wants to merge 45 commits into
mainfrom
feature/3720_select-overflow
Closed

feat(core/ix-select): Add +1 chip#2371
lzeiml wants to merge 45 commits into
mainfrom
feature/3720_select-overflow

Conversation

@lzeiml

@lzeiml lzeiml commented Feb 3, 2026

Copy link
Copy Markdown
Collaborator

💡 What is the current behavior?

Currently overflow of selected item if ix-select is set to mode="multiple" is just handled by a scrollbar that appears.

🆕 What is the new behavior?

After two items have been selected, the third and every subsequent item will be indicated by a number after the first two selected items:

image

🏁 Checklist

A pull request can only be merged if all of these conditions are met (where applicable):

  • 🦮 Accessibility (a11y) features were implemented
  • 🗺️ Internationalization (i18n) - no hard coded strings
  • 📲 Responsiveness - components handle viewport changes and content overflow gracefully
  • 📕 Add or update a Storybook story
  • 📄 Documentation was reviewed/updated siemens/ix-docs
  • 🧪 Unit tests were added/updated and pass (pnpm test)
  • 📸 Visual regression tests were added/updated and pass (Guide)
  • 🧐 Static code analysis passes (pnpm lint)
  • 🏗️ Successful compilation (pnpm build, changes pushed)

@changeset-bot

changeset-bot Bot commented Feb 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 36c9f3e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@siemens/ix Minor
@siemens/ix-aggrid Major
@siemens/ix-angular Minor
@siemens/ix-docs Minor
@siemens/ix-echarts Major
@siemens/ix-react Minor
@siemens/ix-vue Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @lzeiml, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience of the ix-select component in multiple selection mode. Instead of relying on a scrollbar to handle an overflow of selected items, the component now displays a concise +N chip after the first two selected items. This change provides a cleaner and more intuitive visual representation of numerous selections, enhancing the component's overall usability and aesthetic.

Highlights

  • Overflow Chip Implementation: Introduced a new +N overflow chip for the ix-select component when in multiple selection mode, replacing the previous scrollbar behavior for managing selected item overflow.
  • New Private Methods: Added renderOverflowChip to create the visual ix-filter-chip for the overflow count and renderChips to manage the display logic for visible chips and the new overflow chip.
  • Render Logic Update: Modified the main render method in select.tsx to utilize the new renderChips method, ensuring that only the first two selected items are individually displayed, followed by the +N chip if more items are selected.
Changelog
  • packages/core/src/components/select/select.tsx
    • Added a new private method renderOverflowChip responsible for rendering an ix-filter-chip that displays the count of overflowing selected items (e.g., +3).
    • Introduced a new private method renderChips which orchestrates the rendering of selected items, ensuring that a maximum of two individual item chips are displayed, followed by the renderOverflowChip if more than two items are selected.
    • Modified the main render function within the Select class to invoke this.renderChips() for displaying selected items, replacing the previous direct mapping of selectedItems to renderChip.
Activity
  • The pull request was created by lzeiml.
  • No human activity (comments, reviews, etc.) has occurred yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new feature to handle overflow of selected items in a multi-select by displaying a +N chip. The implementation is straightforward. However, a key concern is the lack of accompanying tests. New features should always be tested to ensure correctness and prevent future regressions. Additionally, the number of visible chips is hardcoded, which could be improved by making it a configurable property for better flexibility.

Comment thread packages/core/src/components/select/select.tsx Outdated

@nuke-ellington nuke-ellington left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Visual tests are failing

Comment thread .changeset/stupid-sheep-grin.md Outdated
Comment thread packages/core/src/components/select/select.tsx Outdated
@danielleroux danielleroux added this to the 4.4.0 milestone Mar 19, 2026
Comment thread packages/core/src/components/select/select.tsx
Comment thread packages/core/src/components/select/select.tsx Outdated
@nuke-ellington nuke-ellington modified the milestones: 4.4.0, 5.0.0 Mar 26, 2026
@lzeiml lzeiml force-pushed the feature/3720_select-overflow branch from 11ce6b3 to eb0979e Compare April 2, 2026 12:51

@danielleroux danielleroux left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Testcase:

    <ix-select mode="multiple" style="width: 200px">
      <ix-select-item value="1" label="1"></ix-select-item>
      <ix-select-item value="2" label="2"></ix-select-item>
      <ix-select-item value="3" label="3"></ix-select-item>
      <ix-select-item value="4" label="4"></ix-select-item>
      <ix-select-item value="5" label="5"></ix-select-item>
      <ix-select-item value="6" label="6"></ix-select-item>
    </ix-select>
    <script>
      const select = document.querySelector('ix-select');
      select.value = ['1', '2', '3', '4'];
    </script>

Result:

  1. No interaction:
Image
  1. Dropdown opened once
Image

Comment thread packages/core/src/components/select/select.tsx Outdated

@danielleroux danielleroux Apr 8, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The +1 implementation is part of the select but if I have #2439 in mind it would make more sense to implement this as a share codebase e.g as mixin

Comment on lines +899 to +904
ref={(el) => {
if (el) {
this.chipElementRefs.set(item.value, el as HTMLElement);
} else {
this.chipElementRefs.delete(item.value);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I dont be happy with the calculation of state related variables inside the render cycle itself. The only reason this will no lead into a infinite re-rendering is the raf-function.

Please find a better solution to calculate the filter chips maybe not during the render cycle itself

<div class="chips">
<div
class="chips"
ref={(el) => (this.chipsEl = el as HTMLDivElement)}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We use normal a MakeRef for this any thoughts on your side you didnt choose it?

variant="subtle-tertiary"
oval
size="16"
ref={(ref) => (this.clearButtonEl = ref ?? undefined)}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We use normal a MakeRef for this any thoughts on your side you didnt choose it?

@danielleroux danielleroux left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Accessibility support is missing at all.

  • "+1" -chip can not be accessed via keyboard
  • Chips and "+1" not visible in the accessibility tree
  • Accessibility testing component-test / framework-tests (aria snapshots) missing

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an overflow “+N” chip to ix-select in mode="multiple" so that, when selected chips exceed the available width, only the visible chips are rendered and the remainder is summarized.

Changes:

  • Implement chip overflow measurement/rendering in packages/core/src/components/select/select.tsx and adjust layout in select.scss.
  • Add Playwright component tests for the overflow chip behavior and update preview examples to select 3 items at a constrained width.
  • Update visual-testing fixtures and refresh screenshot baselines.

Reviewed changes

Copilot reviewed 10 out of 77 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/core/src/components/select/select.tsx Adds overflow chip logic, chip measurement, and Enter-key handling for editable mode.
packages/core/src/components/select/select.scss Switches chips layout to single-line overflow behavior (no wrap/scroll).
packages/core/src/components/select/test/select.ct.ts Adds CT coverage for overflow chip in multiple + editable multiple modes; updates some mounts.
testing/visual-testing/tests/select/mode-multiple-overflow/index.html Adjusts fixture width and adds a long label case for overflow visuals.
packages/*-test-app*/src/preview-examples/select-multiple.* Constrains width and updates initial selection to 3 items to demonstrate “+N”.
testing/visual-testing/__screenshots__/** Updates visual regression baselines for select (and one pagination baseline).
.changeset/stupid-sheep-grin.md Declares a minor release note for the feature.
Comments suppressed due to low confidence (1)

packages/core/src/components/select/select.tsx:1166

  • The chevron button ref callback assigns this.chevronButtonEl = ref!. Stencil ref callbacks may receive null during teardown/re-render; using a non-null assertion can leave chevronButtonEl as null at runtime (despite being typed as undefined) and makes the intent unclear. Prefer this.chevronButtonEl = ref ?? undefined for consistency with clearButtonEl and safer typing.
                      ref={(ref) => {
                        this.chevronButtonEl = ref!;
                        const element = ref as unknown as HTMLButtonElement;
                        // VDOM issue if tabIndex is provided via property <ix-icon-button tabIndex={-1}>
                        // the tabindex will be '0' after expanding the dropdown
                        element.tabIndex = -1;
                        element.ariaHidden = 'true';
                      }}

Comment on lines +478 to +492
this.handleUpdateSelectionMutlipleMode();
}

private handleUpdateSelectionMutlipleMode() {
if (!this.isMultipleMode) {
return;
}

const currentValues = new Set(this.selectedItems.map((i) => i.value));
for (const key of this.chipWidths.keys()) {
if (!currentValues.has(key)) this.chipWidths.delete(key);
}
if (this.pendingChipValue === null) {
this.calculateOverflow();
}

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

handleUpdateSelectionMutlipleMode appears to have a typo in its name ("Mutliple"). Please rename to handleUpdateSelectionMultipleMode (and update the call site) to avoid propagating the misspelling into the public codebase and improve maintainability/searchability.

Copilot uses AI. Check for mistakes.
event.stopPropagation();

if (this.isMultipleMode) {
this.emitAddItem(this.inputFilterText);

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

onInputKeyDown always calls emitAddItem() in multiple mode on Enter, even when the typed text matches an existing item. This can create duplicate ix-select-item entries (same label/value) instead of selecting/toggling the existing item. Consider mirroring the single-mode behavior: if an existing item matches, call itemClick(existingItem.value); otherwise add a new item (or only add when isAddItemVisible() is true).

Suggested change
this.emitAddItem(this.inputFilterText);
const existingItem = this.itemExists(this.inputFilterText);
if (existingItem) {
this.itemClick(existingItem.value);
} else {
this.emitAddItem(this.inputFilterText);
}

Copilot uses AI. Check for mistakes.
if (!this.editable || !this.inputFilterText) {
return;
}

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

When handling Enter in onInputKeyDown, the event is stopped from propagating but not prevented. In a form context, pressing Enter in the input can still trigger a form submit/default action. Consider calling event.preventDefault() alongside stopPropagation() when you handle the key to avoid unintended submits/side-effects.

Suggested change
event.preventDefault();

Copilot uses AI. Check for mistakes.
Comment on lines +619 to +636
const chevronWidth = this.chevronButtonEl?.offsetWidth ?? 0;
const clearWidth = this.clearButtonEl?.offsetWidth ?? 0;
const chipGap = 4;
const reservedInputSpace = 40;

const computeVisibleItems = (extraReservedWidth: number) => {
const availableWidth =
this.chipsEl!.clientWidth -
chevronWidth -
clearWidth -
reservedInputSpace -
extraReservedWidth;
const visibleItems = new Set<string>();
let usedWidth = 0;

for (const item of this.selectedItems) {
const width = (this.chipWidths.get(item.value) ?? 60) + chipGap;

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

calculateOverflow() relies on hard-coded layout constants (chipGap = 4, reservedInputSpace = 40, default chip widths 60 / 54). These values are tightly coupled to CSS (e.g., .trigger has min-width: 4rem and .chips > div has margins), so overflow calculation may drift with theme/font-size/CSS changes. Consider deriving spacing from computed styles (margins/min-width) or centralizing these values (e.g., CSS variables) so layout and measurement stay consistent.

Copilot uses AI. Check for mistakes.
"@siemens/ix": minor
---

In multiple-mode **ix-select** now displays "+<number>" for the number of items that are selected if more than two items have been selected.

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

The changeset text says the "+" indicator is shown "if more than two items have been selected", but the implementation shows the overflow chip based on available width (chips exceeding container width), which may not always correspond to "more than two". Please adjust the changeset wording to match the actual behavior (overflow-based summarization) to avoid misleading release notes.

Suggested change
In multiple-mode **ix-select** now displays "+<number>" for the number of items that are selected if more than two items have been selected.
In multiple-mode **ix-select** now displays "+<number>" to summarize selected items that overflow the available width.

Copilot uses AI. Check for mistakes.
@sonarqubecloud

sonarqubecloud Bot commented Apr 9, 2026

Copy link
Copy Markdown

@danielleroux danielleroux removed this from the 5.0.0 milestone May 5, 2026
@netlify

netlify Bot commented Jun 2, 2026

Copy link
Copy Markdown

Deploy Preview for ix-storybook ready!

Name Link
🔨 Latest commit 36c9f3e
🔍 Latest deploy log https://app.netlify.com/projects/ix-storybook/deploys/6a1edc0e1b5501000873a0f4
😎 Deploy Preview https://deploy-preview-2371--ix-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@lzeiml lzeiml marked this pull request as draft June 9, 2026 08:20
@lzeiml

lzeiml commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

Closing in favor of new PR with more solid fundamentals:

#2619

@lzeiml lzeiml closed this Jun 23, 2026
@sonarqubecloud

Copy link
Copy Markdown

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.

4 participants