diff --git a/packages/dashboard/src/vaadin-dashboard.js b/packages/dashboard/src/vaadin-dashboard.js index 46c4baf398..b211204081 100644 --- a/packages/dashboard/src/vaadin-dashboard.js +++ b/packages/dashboard/src/vaadin-dashboard.js @@ -272,7 +272,7 @@ class Dashboard extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitM // Update the wrapper style this.__updateWrapper(wrapper, item); - if (!wrapper.contains(document.activeElement)) { + if (wrapper !== focusedWrapper) { if (previousWrapper) { // Append the wrapper after the previous one if it's not already there if (wrapper.previousElementSibling !== previousWrapper) { diff --git a/packages/dashboard/test/dashboard.test.ts b/packages/dashboard/test/dashboard.test.ts index 6b9493ba4b..4642b9f42b 100644 --- a/packages/dashboard/test/dashboard.test.ts +++ b/packages/dashboard/test/dashboard.test.ts @@ -543,6 +543,25 @@ describe('dashboard', () => { expect(document.activeElement).to.equal(getElementFromCell(dashboard, 0, 0)!); }); + it('should not lose focus when removing items inside shadow root', async () => { + // Move the dashboard to a shadow root + const wrapper = fixtureSync('
'); + const shadow = wrapper.attachShadow({ mode: 'open' }); + shadow.appendChild(dashboard); + await nextFrame(); + + // Focus the second widget + const secondWidget = dashboard.querySelectorAll('vaadin-dashboard-widget')[1]; + secondWidget.focus(); + + // Remove the first widget + dashboard.items = [dashboard.items[1]]; + await nextFrame(); + + // Expect the second widget to remain focused + expect(shadow.activeElement).to.equal(secondWidget); + }); + it('should not lose focus when reassigning section items', async () => { dashboard.items = [{ title: 'Section', items: [{ id: '0' }] }, { id: '1' }]; await nextFrame();