diff --git a/examples/index.html b/examples/index.html index 48ae4f7..698ee51 100644 --- a/examples/index.html +++ b/examples/index.html @@ -85,6 +85,23 @@

Autofocus example

+
+ Scroll into view radio group + + + +
+ diff --git a/src/index.ts b/src/index.ts index 81a4cf1..1b99115 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,6 +39,7 @@ class DetailsMenuElement extends HTMLElement { fromEvent(details, 'keydown', e => keydown(details, this, e)), fromEvent(details, 'toggle', () => loadFragment(details, this), {once: true}), fromEvent(details, 'toggle', () => closeCurrentMenu(details)), + fromEvent(details, 'toggle', () => scrollIntoView(details)), this.preload ? fromEvent(details, 'mouseover', () => loadFragment(details, this), {once: true}) : NullSubscription, @@ -137,6 +138,22 @@ function autofocus(details: Element): boolean { } } +// Scroll entire details menu into view, center on it. +function scrollIntoView(details: Element): boolean { + if (!details.hasAttribute('open')) return false + const detailsMenu = details.querySelector('details-menu [scrollIntoView]') + if (detailsMenu) { + const innerMenu = detailsMenu.closest('[role="menu"], [role="radiogroup"]') + if (innerMenu) { + innerMenu.scrollIntoView({behavior: 'smooth', block: 'center'}) + } else { + return false + } + return true + } + return false +} + // Focus first item unless an item is already focused. function focusFirstItem(details: Element) { const selected = document.activeElement diff --git a/test/test.js b/test/test.js index 20ff162..27468c2 100644 --- a/test/test.js +++ b/test/test.js @@ -629,6 +629,45 @@ describe('details-menu element', function () { }) }) + describe('with input[scrollIntoView]', function () { + beforeEach(function () { + const container = document.createElement('div') + container.innerHTML = ` +
+ Scroll into view radio group + +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ ` + document.body.append(container) + }) + + afterEach(function () { + document.body.innerHTML = '' + }) + + it('scrolls the inner menu into view on mouse click', function () { + const details = document.querySelector('details') + const detailsMenu = details.querySelector('details-menu') + const innerMenu = detailsMenu.closest('[role="menu"]') + + details.open = true + details.dispatchEvent(new CustomEvent('toggle')) + assert.equal(0, innerMenu.scrollTop) + }) + }) + describe('closing the menu', function () { beforeEach(function () { const container = document.createElement('div')