diff --git a/README.md b/README.md
index dde1a4f..c6f6ca3 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,12 @@ These settings are available:
- `tabInsertsSuggestions: boolean = true` - Control whether the highlighted suggestion is inserted when Tab is pressed (Enter will always insert a suggestion regardless of this setting). When `true`, tab-navigation will be hijacked when open (which can have negative impacts on accessibility) but the combobox will more closely imitate a native IDE experience.
- `defaultFirstOption: boolean = false` - If no options are selected and the user presses Enter, should the first item be inserted? If enabled, the default option can be selected and styled with `[data-combobox-option-default]` . This should be styled differently from the `aria-selected` option.
> **Warning** Screen readers will not announce that the first item is the default. This should be announced explicitly with the use of `aria-live` status text.
+- `scrollIntoViewOptions?: boolean | ScrollIntoViewOptions = undefined` - When
+ controlling the element marked `[aria-selected="true"]` with keyboard navigation, the selected element will be scrolled into the viewport by a call to [Element.scrollIntoView][]. Configure this value to control the scrolling behavior (either with a `boolean` or a [ScrollIntoViewOptions][] object.
+
+[Element.scrollIntoView]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
+[ScrollIntoViewOptions]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView#sect1
+
## Development
diff --git a/src/index.ts b/src/index.ts
index 61a94c8..6537f7c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,7 @@
export type ComboboxSettings = {
tabInsertsSuggestions?: boolean
defaultFirstOption?: boolean
+ scrollIntoViewOptions?: boolean | ScrollIntoViewOptions
}
export default class Combobox {
@@ -13,16 +14,18 @@ export default class Combobox {
ctrlBindings: boolean
tabInsertsSuggestions: boolean
defaultFirstOption: boolean
+ scrollIntoViewOptions?: boolean | ScrollIntoViewOptions
constructor(
input: HTMLTextAreaElement | HTMLInputElement,
list: HTMLElement,
- {tabInsertsSuggestions, defaultFirstOption}: ComboboxSettings = {}
+ {tabInsertsSuggestions, defaultFirstOption, scrollIntoViewOptions}: ComboboxSettings = {}
) {
this.input = input
this.list = list
this.tabInsertsSuggestions = tabInsertsSuggestions ?? true
this.defaultFirstOption = defaultFirstOption ?? false
+ this.scrollIntoViewOptions = scrollIntoViewOptions
this.isComposing = false
@@ -108,7 +111,7 @@ export default class Combobox {
this.input.setAttribute('aria-activedescendant', target.id)
target.setAttribute('aria-selected', 'true')
fireSelectEvent(target)
- scrollTo(this.list, target)
+ target.scrollIntoView(this.scrollIntoViewOptions)
} else {
el.removeAttribute('aria-selected')
}
@@ -209,17 +212,3 @@ function trackComposition(event: Event, combobox: Combobox): void {
combobox.clearSelection()
}
-
-function scrollTo(container: HTMLElement, target: HTMLElement) {
- if (!inViewport(container, target)) {
- container.scrollTop = target.offsetTop
- }
-}
-
-function inViewport(container: HTMLElement, element: HTMLElement): boolean {
- const scrollTop = container.scrollTop
- const containerBottom = scrollTop + container.clientHeight
- const top = element.offsetTop
- const bottom = top + element.clientHeight
- return top >= scrollTop && bottom <= containerBottom
-}