Skip to content

feat(core/ix-select): overflow chip#2619

Open
lzeiml wants to merge 14 commits into
mainfrom
feature/3720_select-overflow-stable
Open

feat(core/ix-select): overflow chip#2619
lzeiml wants to merge 14 commits into
mainfrom
feature/3720_select-overflow-stable

Conversation

@lzeiml

@lzeiml lzeiml commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

IX-3720

💡 What is the current behavior?

Overflowing chips break into new line when select is in mode="multiple"

image

🆕 What is the new behavior?

Overflowing chips are hidden and a new chip is displayed, indicating how many items are hidden. The chip can be clicked/accessed by keyboard to view/remove the hidden 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)

Summary by CodeRabbit

  • New Features
    • Updated ix-select multiple mode overflow handling: selected items stay in one row and collapse into a non-removable “+N” indicator.
    • The “+N” indicator opens a dropdown to view and remove hidden selections.
    • Added ariaLabelMoreItems for the overflow indicator’s accessible label, and added hideCloseButton to ix-filter-chip.
  • Bug Fixes
    • Refined overflow layout and focus-visible styling, with improved keyboard and tab navigation for the overflow dropdown.
  • Tests
    • Added Playwright coverage for overflow removal and keyboard interactions; updated visual/e2e scenarios (including a long-label case).

@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d2bf63a

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

This PR includes changesets to release 5 packages
Name Type
@siemens/ix Minor
@siemens/ix-angular Minor
@siemens/ix-docs Minor
@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

@netlify

netlify Bot commented Jun 23, 2026

Copy link
Copy Markdown

Deploy Preview for ix-storybook ready!

Name Link
🔨 Latest commit d2bf63a
🔍 Latest deploy log https://app.netlify.com/projects/ix-storybook/deploys/6a43c7ae258a9800080f9f41
😎 Deploy Preview https://deploy-preview-2619--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.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

ix-select in multiple mode now renders selected chips in a single row and hides overflowed chips behind a non-removable “+N” chip. The overflow chip opens a dropdown for hidden items. ix-filter-chip gains hideCloseButton, and ix-select gains ariaLabelMoreItems for the overflow label.

Changes

ix-select multiple-mode chip overflow

Layer / File(s) Summary
ix-filter-chip hideCloseButton
packages/core/src/components.d.ts, packages/core/src/components/filter-chip/filter-chip.tsx, packages/core/src/components/filter-chip/filter-chip.scss, packages/angular/src/components.ts
Adds hideCloseButton to ix-filter-chip, suppresses the close button when set, adjusts padding for that host state, and updates generated typings and Angular inputs.
ix-select overflow state and measurement
packages/core/src/components.d.ts, packages/core/src/components/select/select.tsx, packages/angular/src/components.ts
Adds ariaLabelMoreItems, overflow state, width caching, resize observation, cache invalidation, cache pruning, and pre-render overflow recalculation for multiple-mode selections.
ix-select overflow rendering and styles
packages/core/src/components/select/select.tsx, packages/core/src/components/select/select.scss
Switches the chip container to nowrap hidden overflow, adds focus styling for the overflow chip, defines overflow dropdown content layout, renders the +N chip and hidden-chip dropdown, and measures chip widths during render.
Tests, fixture, and release note
packages/core/src/components/select/test/select.ct.ts, testing/visual-testing/tests/select/mode-multiple-overflow/index.html, testing/visual-testing/tests/select/select.e2e.ts, .changeset/lucky-schools-enter.md
Adds overflow interaction tests, updates the visual fixture layout, removes the old scroll-down regression test, and documents the release change.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • nuke-ellington
  • danielleroux

Poem

🐇 I hopped past chips in a tidy row,
A tiny “+N” began to glow.
Hidden bunnies queued in a dropdown bright,
Click, tab, and escape — all feeling right.
My whiskers twitch at the measured flow,
And one neat row is the way to go.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately highlights the main change: adding an overflow chip to ix-select.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/3720_select-overflow-stable

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lzeiml lzeiml mentioned this pull request Jun 23, 2026
9 tasks

@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 chip overflow handling for the ix-select component in multiple selection mode. When selected chips exceed the available container width, they are hidden and replaced with an overflow indicator chip (+N) that opens a dropdown containing the hidden items. To support this, a hideCloseButton property was added to ix-filter-chip. Feedback on these changes highlights a critical bug where chips rendered inside initially hidden containers fail to measure properly when they become visible, which can be resolved by triggering a re-render. Additionally, the feedback identifies style guide violations regarding a missing @since tag on the new property, a missing axe-based accessibility test for the new interactive overflow chip, and a consistency improvement to rename ariaLabelMoreItems to i18nMoreItems.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +971 to +989
private calculateChipOverflow() {
if (!this.isMultipleMode || this.shouldDisplayAllChip()) {
return;
}

const container = this.chipsContainerRef.current;
if (!container) {
return;
}

const values = this.selectedItems.map((item) => item.value.toString());
if (values.length === 0) {
this.applyOverflowState(null, []);
return;
}

if (!values.every((value) => this.chipWidths.has(value))) {
return;
}

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.

high

If the ix-select component is initially rendered inside a hidden container (e.g., display: none in a tab or modal), the chips will have an offsetWidth of 0 during the initial render. Consequently, this.chipWidths will not be populated, and calculateChipOverflow() will return early. When the container later becomes visible, the ResizeObserver will fire and call calculateChipOverflow(), but it will still return early because this.chipWidths is empty, and no re-render/re-measurement will ever be triggered.

To fix this, when calculateChipOverflow() is called and there are unmeasured chips, we should trigger a re-render using forceUpdate(this) so that componentDidRender can measure the chips now that the container is visible.

  private calculateChipOverflow() {
    if (!this.isMultipleMode || this.shouldDisplayAllChip()) {
      return;
    }

    const container = this.chipsContainerRef.current;
    if (!container) {
      return;
    }

    const values = this.selectedItems.map((item) => item.value.toString());
    if (values.length === 0) {
      this.applyOverflowState(null, []);
      return;
    }

    if (!values.every((value) => this.chipWidths.has(value))) {
      // Trigger a re-render to let componentDidRender measure the chips now that the container is visible
      forceUpdate(this);
      return;
    }

Comment thread packages/core/src/components/filter-chip/filter-chip.tsx
Comment thread packages/core/src/components/select/select.tsx Outdated
Comment thread packages/core/src/components/select/select.tsx Outdated
Comment thread packages/core/src/components/select/test/select.ct.ts
@lzeiml lzeiml changed the title feat(core/select): chip overflow +N logic feat(core/ix-select): overflow chip Jun 24, 2026
@lzeiml lzeiml marked this pull request as ready for review June 24, 2026 07:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/lucky-schools-enter.md:
- Around line 5-7: This changeset only documents the ix-select overflow behavior
and ariaLabelMoreItems, but the public API addition hideCloseButton on
ix-filter-chip is missing. Update the changeset to mention hideCloseButton
alongside the existing API notes, using the ix-filter-chip component name, or
explicitly state that it is internal-only if that is the intent. Keep the entry
aligned with the public API changes so the release note covers all externally
visible updates.

In `@packages/core/src/components.d.ts`:
- Around line 1944-1948: The public prop hideCloseButton is missing the required
JSDoc `@since` tag for a new API. Update the documentation comment on
hideCloseButton in components.d.ts (and the corresponding generated declaration
entry if applicable) to include the correct `@since` version used for this
component’s public API, keeping the existing description intact.

In `@packages/core/src/components/filter-chip/filter-chip.tsx`:
- Around line 39-45: The new public prop hideCloseButton in FilterChip needs a
JSDoc `@since` tag. Update the documentation comment on the hideCloseButton `@Prop`
in filter-chip.tsx to include the correct version marker for when this API was
introduced, keeping the rest of the prop description unchanged.

In `@packages/core/src/components/select/select.tsx`:
- Around line 1115-1118: Clear the stale overflow state in select.tsx when
overflow is no longer applicable. In `calculateChipOverflow()`, if
`isMultipleMode` is false or `shouldDisplayAllChip()` becomes true, reset
`hiddenChipValues` so the overflow dropdown cannot keep rendering from prior
state. Make sure the render path around the overflow trigger and chip display
logic (including the `collapseMultipleSelection`/“All” chip branch) reflects the
cleared state consistently.
- Around line 842-845: The overflow trigger in select.tsx is using listbox
semantics that do not match the actual overflow content. Update the
accessibility attributes on the trigger in the select component so they reflect
the real popup type: either change the aria-haspopup value in the overflow
trigger logic to menu or dialog, or adjust the overflow content markup to use
proper listbox/option semantics. Use the select component’s overflow trigger and
dropdown rendering code to keep the ARIA contract consistent.
- Around line 1088-1113: Update getOverflowChipValues in select.tsx so it does
not always force the first selected chip into visible; instead, calculate
whether the first chip plus the overflow chip fit within available, and allow
visible to be empty when only the overflow chip fits. Use the existing
getChipWidthWithMargin and getOverflowChipWidthWithMargin helpers in this method
to decide whether to place firstValue in visible or move it into hidden,
preserving access to overflow selections in narrow containers.
- Around line 828-932: Add axe coverage for the overflow chip/dropdown
accessibility state in the Select component tests. Update the `select.ct.ts`
test suite to render a scenario that exercises `renderOverflowChip()` and
`renderOverflowDropdown()` (the `+N` chip with keyboard/focus behavior) and run
`makeAxeBuilder()` against that overflow state. Keep the new assertion near the
existing axe test so the accessibility coverage includes the overflow path.

In `@packages/core/src/components/select/test/select.ct.ts`:
- Line 1350: The new component tests in select.ct.ts are using plain test(...)
instead of the required regressionTest(...) convention. Update the affected
cases, including the ones identified by the test names around the hidden-item,
preserve-existing-hover, and item-removed scenarios, to use regressionTest from
`@utils/test` so they match the component test pattern used elsewhere in this
suite.
- Around line 1350-1464: The new overflow-dropdown interaction tests in
select.ct.ts cover focus and keyboard behavior, but they still miss
accessibility verification for the opened overflow state. Add an axe-based
assertion in the relevant multiple-mode overflow dropdown test(s), using the
existing test structure around ix-select, ix-filter-chip.chip-overflow, and
ix-dropdown.overflow-dropdown, so the newly introduced open state is included in
accessibility coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d8bd5142-fa06-4cf7-b48a-b6042a985ffe

📥 Commits

Reviewing files that changed from the base of the PR and between d1cfb47 and 395b4e2.

⛔ Files ignored due to path filters (8)
  • packages/angular/standalone/src/components.ts is excluded by !packages/angular/standalone/src/components.ts
  • packages/react/src/components/components.server.ts is excluded by !packages/react/src/components/**
  • packages/vue/src/components/ix-filter-chip.ts is excluded by !packages/vue/src/components/**
  • packages/vue/src/components/ix-select.ts is excluded by !packages/vue/src/components/**
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-overflow-1-chromium---classic-dark-linux.png is excluded by !**/*.png
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-overflow-1-chromium---classic-light-linux.png is excluded by !**/*.png
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-overflow-scroll-down-1-chromium---classic-dark-linux.png is excluded by !**/*.png
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-overflow-scroll-down-1-chromium---classic-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • .changeset/lucky-schools-enter.md
  • packages/angular/src/components.ts
  • packages/core/src/components.d.ts
  • packages/core/src/components/filter-chip/filter-chip.scss
  • packages/core/src/components/filter-chip/filter-chip.tsx
  • packages/core/src/components/select/select.scss
  • packages/core/src/components/select/select.tsx
  • packages/core/src/components/select/test/select.ct.ts
  • testing/visual-testing/tests/select/mode-multiple-overflow/index.html
  • testing/visual-testing/tests/select/select.e2e.ts
💤 Files with no reviewable changes (1)
  • testing/visual-testing/tests/select/select.e2e.ts

Comment thread .changeset/lucky-schools-enter.md Outdated
Comment thread packages/core/src/components.d.ts
Comment thread packages/core/src/components/filter-chip/filter-chip.tsx
Comment thread packages/core/src/components/select/select.tsx
Comment thread packages/core/src/components/select/select.tsx
Comment thread packages/core/src/components/select/select.tsx
Comment thread packages/core/src/components/select/select.tsx
Comment thread packages/core/src/components/select/test/select.ct.ts
Comment thread packages/core/src/components/select/test/select.ct.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core/src/components/select/select.tsx (1)

1199-1209: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Re-measure the overflow chip when the hidden count changes.

overflowChipWidth is cached after the first measurement, but the rendered text changes from e.g. +9 to +10; using the stale width can compute too many visible chips and clip the overflow trigger.

🐛 Proposed fix
   private async measureOverflowChipWidth() {
-    if (this.hiddenChipValues.length === 0 || this.overflowChipWidth > 0) {
+    if (this.hiddenChipValues.length === 0) {
       return;
     }
 
     const overflowElement = await this.overflowChipRef.waitForCurrent();
     await this.waitForChipLayout([overflowElement]);
 
-    if (overflowElement.offsetWidth > 0) {
+    if (
+      overflowElement.offsetWidth > 0 &&
+      overflowElement.offsetWidth !== this.overflowChipWidth
+    ) {
       this.overflowChipWidth = overflowElement.offsetWidth;
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/select.tsx` around lines 1199 - 1209, The
cached overflow chip width in measureOverflowChipWidth is only measured once, so
it becomes stale when hiddenChipValues changes and the displayed count text
changes (for example from +9 to +10). Update the logic in Select’s
measureOverflowChipWidth to detect when the hidden count differs from the last
measured count and re-measure the overflow chip width in that case, keeping the
cache only when the rendered label is unchanged.
♻️ Duplicate comments (1)
packages/core/src/components/select/test/select.ct.ts (1)

1466-1466: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use regressionTest instead of plain test in this component test.

This new .ct.ts case uses test(...); switch it to regressionTest(...) to match the required suite convention.

Suggested change
-test('multiple mode: focused "+N" chip traps Tab navigation', async ({
+regressionTest('multiple mode: focused "+N" chip traps Tab navigation', async ({

As per path instructions, "packages/core/src/components/**/test/*.ct.ts: Prefer regressionTest from @utils/test (not plain Playwright test)."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/test/select.ct.ts` at line 1466, This
component test currently uses plain test instead of the required regressionTest
convention. Update the new case in select.ct.ts, specifically the test named
multiple mode: focused "+N" chip traps Tab navigation, to use regressionTest
from `@utils/test` so it matches the rest of the component test suite.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/core/src/components/select/select.tsx`:
- Around line 1199-1209: The cached overflow chip width in
measureOverflowChipWidth is only measured once, so it becomes stale when
hiddenChipValues changes and the displayed count text changes (for example from
+9 to +10). Update the logic in Select’s measureOverflowChipWidth to detect when
the hidden count differs from the last measured count and re-measure the
overflow chip width in that case, keeping the cache only when the rendered label
is unchanged.

---

Duplicate comments:
In `@packages/core/src/components/select/test/select.ct.ts`:
- Line 1466: This component test currently uses plain test instead of the
required regressionTest convention. Update the new case in select.ct.ts,
specifically the test named multiple mode: focused "+N" chip traps Tab
navigation, to use regressionTest from `@utils/test` so it matches the rest of the
component test suite.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c25f6693-0dd0-4fcb-a74e-afa74eba84b0

📥 Commits

Reviewing files that changed from the base of the PR and between 395b4e2 and 58419ef.

📒 Files selected for processing (2)
  • packages/core/src/components/select/select.tsx
  • packages/core/src/components/select/test/select.ct.ts

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core/src/components/select/select.tsx (1)

1064-1071: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Invalidate the overflow-chip width when the +N count changes.

measureOverflowChipWidth() returns forever after the first measurement, but the chip text changes from +9 to +10, etc. The overflow calculation can then use a stale, too-small width and leave chips clipped.

Proposed fix
   private applyOverflowState(visible: string[] | null, hidden: string[]) {
     if (!this.sameChipValues(this.visibleChipValues, visible)) {
       this.visibleChipValues = visible;
     }
 
+    const hiddenCountChanged = this.hiddenChipValues.length !== hidden.length;
+
     if (!this.sameChipValues(this.hiddenChipValues, hidden)) {
       this.hiddenChipValues = hidden;
+
+      if (hiddenCountChanged) {
+        this.overflowChipWidth = 0;
+      }
     }
 
     if (hidden.length === 0 && this.overflowDropdownShow) {
       this.overflowDropdownShow = false;
     }

Also applies to: 1199-1209

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/select.tsx` around lines 1064 - 1071, The
overflow-chip width cache is not being invalidated when the `+N` text changes,
so `measureOverflowChipWidth()` can keep returning a stale width after the count
grows from one digit to two digits. Update the overflow-state flow in
`applyOverflowState` and the overflow measurement logic in
`measureOverflowChipWidth` so the cached width is recomputed whenever the
overflow count/text changes, and make sure the same fix is applied anywhere else
the overflow chip width is reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/core/src/components/select/select.tsx`:
- Around line 1064-1071: The overflow-chip width cache is not being invalidated
when the `+N` text changes, so `measureOverflowChipWidth()` can keep returning a
stale width after the count grows from one digit to two digits. Update the
overflow-state flow in `applyOverflowState` and the overflow measurement logic
in `measureOverflowChipWidth` so the cached width is recomputed whenever the
overflow count/text changes, and make sure the same fix is applied anywhere else
the overflow chip width is reused.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4ecc26e4-bb97-4122-ad27-b4ed9cd81839

📥 Commits

Reviewing files that changed from the base of the PR and between 58419ef and 76f6810.

📒 Files selected for processing (1)
  • packages/core/src/components/select/select.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/core/src/components.d.ts (1)

1944-1948: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

hideCloseButton is missing a @since tag.

This was flagged in a previous review and remains unresolved.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components.d.ts` around lines 1944 - 1948, The
hideCloseButton property in components.d.ts is missing its `@since` annotation;
update the JSDoc for the hideCloseButton field in the component declaration to
include the appropriate `@since` tag, matching the existing documentation style
used for other props in this interface.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/components/select/select.scss`:
- Line 113: The select stylesheet introduces hard-coded sizing and spacing
values that should be tokenized instead of fixed rems. Update the rules in
select.scss that use max-width and the spacing/width values around the select
component to reference existing design tokens or CSS custom properties rather
than literal rem values. Keep the changes localized to the affected select
styles and use the existing token patterns already used in the component/theme
system.

---

Duplicate comments:
In `@packages/core/src/components.d.ts`:
- Around line 1944-1948: The hideCloseButton property in components.d.ts is
missing its `@since` annotation; update the JSDoc for the hideCloseButton field in
the component declaration to include the appropriate `@since` tag, matching the
existing documentation style used for other props in this interface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1c05eac5-4f94-4762-b120-42f9b6b746a8

📥 Commits

Reviewing files that changed from the base of the PR and between 76f6810 and 7205319.

⛔ Files ignored due to path filters (2)
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-long-item-label-1-chromium---classic-dark-linux.png is excluded by !**/*.png
  • testing/visual-testing/__screenshots__/tests/select/select.e2e.ts/select-mode-multiple-long-item-label-1-chromium---classic-light-linux.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • packages/core/src/components.d.ts
  • packages/core/src/components/filter-chip/filter-chip.scss
  • packages/core/src/components/select/select.scss
  • testing/visual-testing/tests/select/mode-multiple-long-item-label/index.html
  • testing/visual-testing/tests/select/select.e2e.ts

Comment thread packages/core/src/components/select/select.scss
dmytro-halimov
dmytro-halimov previously approved these changes Jun 26, 2026
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/core/src/components/select/select.tsx (3)

368-375: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Close the overflow popup when the control becomes disabled or readonly.

This watcher invalidates measurements, but it leaves overflowDropdownShow set. If the +N popup is open when disabled or readonly flips, the popup keeps rendering even though the select should be inert.

Suggested fix
   watchDisabledReadonly() {
     // Disabled/readonly hides the chip close button, changing chip widths, so
     // invalidate the measurement cache to force a re-measure on next render.
     this.chipWidths.clear();
     this.overflowChipWidth = 0;
+    this.overflowDropdownShow = false;
+    this.overflowDropdownOpenedByKeyboard = false;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/select.tsx` around lines 368 - 375, The
watchDisabledReadonly() watcher in select.tsx only clears measurement state, but
it should also close the overflow popup when disabled or readonly changes.
Update this watcher to reset overflowDropdownShow (and any related popup open
state) alongside chipWidths and overflowChipWidth so the +N menu stops rendering
when the control becomes inert.

903-927: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Forward enableTopLayer to the overflow dropdown.

ix-select already exposes enableTopLayer for its popup, but the new overflow dropdown ignores it. In the same clipping/z-index scenarios that require top-layer rendering for the main dropdown, the +N popup will still be constrained.

Suggested fix
       <ix-dropdown
         class="overflow-dropdown"
         show={this.overflowDropdownShow}
+        enableTopLayer={this.enableTopLayer}
         anchor={this.overflowChipRef.waitForCurrent()}
         closeBehavior="outside"
         placement="bottom-start"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/select.tsx` around lines 903 - 927, The
overflow popup rendered by renderOverflowDropdown in select.tsx is missing the
existing enableTopLayer behavior, so it can still be clipped in the same
z-index/overflow cases as the main dropdown. Update the ix-dropdown used for the
overflow dropdown to pass through the select component’s enableTopLayer value,
matching the popup configuration already used elsewhere in ix-select.

1197-1207: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Re-measure the overflow chip when the hidden-count label changes.

measureOverflowChipWidth() stops after the first successful measurement, but the rendered chip text changes as the hidden count changes (+9+10, etc.). After that first render, overflow calculation keeps using a stale width and can hide too many or too few chips.

Suggested fix
+  private measuredOverflowChipText?: string;
+
   private async measureOverflowChipWidth() {
-    if (this.hiddenChipValues.length === 0 || this.overflowChipWidth > 0) {
+    const overflowChipText = `+${this.hiddenChipValues.length}`;
+
+    if (this.hiddenChipValues.length === 0) {
+      this.overflowChipWidth = 0;
+      this.measuredOverflowChipText = undefined;
+      return;
+    }
+
+    if (
+      this.overflowChipWidth > 0 &&
+      this.measuredOverflowChipText === overflowChipText
+    ) {
       return;
     }
 
     const overflowElement = await this.overflowChipRef.waitForCurrent();
     await this.waitForChipLayout([overflowElement]);
 
     if (overflowElement.offsetWidth > 0) {
       this.overflowChipWidth = overflowElement.offsetWidth;
+      this.measuredOverflowChipText = overflowChipText;
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/components/select/select.tsx` around lines 1197 - 1207, The
overflow chip width is cached too aggressively in measureOverflowChipWidth(), so
it is never updated when the hidden-count label changes (for example, +9 to
+10). Adjust the Select component logic to detect label/count changes and re-run
the width measurement instead of returning early once overflowChipWidth is set,
using the existing measureOverflowChipWidth(), overflowChipWidth, and
hiddenChipValues paths to keep the cached width in sync with the rendered chip
text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/core/src/components/select/select.tsx`:
- Around line 368-375: The watchDisabledReadonly() watcher in select.tsx only
clears measurement state, but it should also close the overflow popup when
disabled or readonly changes. Update this watcher to reset overflowDropdownShow
(and any related popup open state) alongside chipWidths and overflowChipWidth so
the +N menu stops rendering when the control becomes inert.
- Around line 903-927: The overflow popup rendered by renderOverflowDropdown in
select.tsx is missing the existing enableTopLayer behavior, so it can still be
clipped in the same z-index/overflow cases as the main dropdown. Update the
ix-dropdown used for the overflow dropdown to pass through the select
component’s enableTopLayer value, matching the popup configuration already used
elsewhere in ix-select.
- Around line 1197-1207: The overflow chip width is cached too aggressively in
measureOverflowChipWidth(), so it is never updated when the hidden-count label
changes (for example, +9 to +10). Adjust the Select component logic to detect
label/count changes and re-run the width measurement instead of returning early
once overflowChipWidth is set, using the existing measureOverflowChipWidth(),
overflowChipWidth, and hiddenChipValues paths to keep the cached width in sync
with the rendered chip text.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43cf0b6b-6e19-47ad-8eec-1d43d600878e

📥 Commits

Reviewing files that changed from the base of the PR and between 7205319 and d2bf63a.

📒 Files selected for processing (2)
  • .changeset/lucky-schools-enter.md
  • packages/core/src/components/select/select.tsx

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