diff --git a/packages/dnb-eufemia/src/components/autocomplete/__tests__/Autocomplete.test.js b/packages/dnb-eufemia/src/components/autocomplete/__tests__/Autocomplete.test.js
index e4e42eee1b4..d6003b6b0bd 100644
--- a/packages/dnb-eufemia/src/components/autocomplete/__tests__/Autocomplete.test.js
+++ b/packages/dnb-eufemia/src/components/autocomplete/__tests__/Autocomplete.test.js
@@ -1154,6 +1154,39 @@ describe('Autocomplete component', () => {
expect(on_type).toBeCalledTimes(4)
})
+ it('should have a button for screen readers to open options – regardless', () => {
+ const Comp = mount(
+ ,
+ { attachTo: attachToBody() }
+ )
+
+ const buttonElem = Comp.find('.dnb-sr-only').find('button')
+
+ expect(buttonElem.text()).toBe(
+ 'Bla gjennom alternativer, lukk med esc knappen'
+ )
+ expect(buttonElem.exists()).toBe(true)
+ expect(buttonElem.instance().getAttribute('tabindex')).toBe('-1')
+
+ buttonElem.simulate('click')
+
+ expect(
+ Comp.find('.dnb-autocomplete').hasClass('dnb-autocomplete--opened')
+ ).toBe(true)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-drawer-list__options'
+ )
+
+ buttonElem.simulate('click')
+
+ expect(
+ Comp.find('.dnb-autocomplete').hasClass('dnb-autocomplete--opened')
+ ).toBe(false)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-input__input'
+ )
+ })
+
it('should keep input focus when using show-all or select item', () => {
const Comp = mount(, {
attachTo: attachToBody(),
@@ -1161,9 +1194,9 @@ describe('Autocomplete component', () => {
Comp.find('input').simulate('change', { target: { value: 'cc' } })
- expect(
- document.activeElement.classList.contains('dnb-drawer-list__options')
- ).toBe(true)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-input__input'
+ )
expect(
Comp.find(
'li.dnb-drawer-list__option:not(.dnb-autocomplete__show-all)'
@@ -1172,9 +1205,9 @@ describe('Autocomplete component', () => {
Comp.find('input').instance().focus()
- expect(
- document.activeElement.classList.contains('dnb-input__input')
- ).toBe(true)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-input__input'
+ )
Comp.find('li.dnb-autocomplete__show-all').simulate('click')
@@ -1184,9 +1217,9 @@ describe('Autocomplete component', () => {
.hasClass('dnb-drawer-list__option--focus')
).toBe(true)
- expect(
- document.activeElement.classList.contains('dnb-input__input')
- ).toBe(true)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-input__input'
+ )
expect(
Comp.find(
@@ -1197,9 +1230,9 @@ describe('Autocomplete component', () => {
Comp.find('input').instance().blur()
Comp.find('li.dnb-drawer-list__option').at(0).simulate('click')
- expect(
- document.activeElement.classList.contains('dnb-input__input')
- ).toBe(true)
+ expect(Array.from(document.activeElement.classList)).toContain(
+ 'dnb-input__input'
+ )
})
it('will open drawer-list when open_on_focus is set to true', () => {
@@ -1583,10 +1616,6 @@ describe('Autocomplete component', () => {
// open
keydown(Comp, 40) // down
- expect(Array.from(document.activeElement.classList)).toContain(
- 'dnb-drawer-list__options'
- )
-
Comp.find('input').instance().focus()
// focus the first item
@@ -1622,6 +1651,24 @@ describe('Autocomplete component', () => {
runTabs()
})
+ it('will keep focus on input when opening', () => {
+ const mockData = ['first item', 'one more item']
+
+ const Comp = mount(
+ ,
+ {
+ attachTo: attachToBody(),
+ }
+ )
+
+ Comp.find('input').instance().focus()
+
+ // open
+ keydown(Comp, 40) // down
+
+ expect(document.activeElement.tagName).toBe('INPUT')
+ })
+
it('submit_element will replace the internal SubmitButton', () => {
const Comp = mount(
{
.getAttribute('data-test-id')
).toContain('bell')
})
-
- it('should have a button for screen readers to open options – regardless', () => {
- const Comp = mount(
- ,
- { attachTo: attachToBody() }
- )
-
- const buttonElem = Comp.find('.dnb-sr-only').find('button')
-
- expect(buttonElem.exists()).toBe(true)
- expect(buttonElem.instance().getAttribute('tabindex')).toBe('-1')
-
- buttonElem.simulate('click')
-
- expect(
- Comp.find('.dnb-autocomplete').hasClass('dnb-autocomplete--opened')
- ).toBe(true)
- expect(
- document.activeElement.classList.contains('dnb-drawer-list__options')
- ).toBe(true)
-
- buttonElem.simulate('click')
-
- expect(
- Comp.find('.dnb-autocomplete').hasClass('dnb-autocomplete--opened')
- ).toBe(false)
- expect(
- document.activeElement.classList.contains('dnb-input__input')
- ).toBe(true)
- })
})
describe('Autocomplete markup', () => {
diff --git a/packages/dnb-eufemia/src/fragments/drawer-list/DrawerListProvider.js b/packages/dnb-eufemia/src/fragments/drawer-list/DrawerListProvider.js
index 171f2e1f131..89639bc75b9 100644
--- a/packages/dnb-eufemia/src/fragments/drawer-list/DrawerListProvider.js
+++ b/packages/dnb-eufemia/src/fragments/drawer-list/DrawerListProvider.js
@@ -520,63 +520,57 @@ export default class DrawerListProvider extends React.PureComponent {
}, 1) // to make sure we are after all DOM updates, else we don't get this scrolling
}
+ /**
+ * During opening (Dropdown, Autocomplete),
+ * and if noting is selected,
+ * set scroll to item.
+ *
+ * @param {number} active_item The item to set as active
+ * @param {object} param1
+ * @property {boolean} fireSelectEvent Wheter the onSelect event should get emitted
+ * @property {boolean} scrollTo Wheter the list should scroll to the new active item nor not
+ * @property {event} event The event object to forward to the emitted events
+ */
setActiveItemAndScrollToIt = (
active_item,
{ fireSelectEvent = false, scrollTo = true, event = null } = {}
) => {
- // during opening, and if noting is selected, set focus and scroll to item
- if (parseFloat(active_item) === -1) {
- this.setState(
- {
- active_item: -1,
- },
- () => {
- if (this._refUl.current) {
- this._refUl.current.focus({ preventScroll: true })
- }
- dispatchCustomElementEvent(this, 'on_show_focus', {
- element: this._refUl.current,
- })
+ this.setState({ active_item }, () => {
+ if (parseFloat(active_item) === -1) {
+ // Select the first item to NVDA is more easily navigateable,
+ // without using the alt + arrow key
+ // else we set the focus on the "ul" element
+ if (document.activeElement?.tagName !== 'INPUT') {
+ this._refUl.current?.focus({ preventScroll: true })
}
- )
-
- return // stop here
- }
-
- if (parseFloat(active_item) > -1) {
- this.setState(
- {
- active_item,
- },
- () => {
- const { selected_item } = this.state
-
- if (fireSelectEvent) {
- const attributes = this.attributes
- const ret = dispatchCustomElementEvent(
- this.state,
- 'on_select',
- {
- active_item,
- value: getSelectedItemValue(selected_item, this.state),
- data: getEventData(active_item, this.state.data),
- event,
- attributes,
- }
- )
- if (ret === false) {
- return // stop here!
- }
- }
- if (isTrue(this.props.no_animation)) {
- scrollTo = false
+ dispatchCustomElementEvent(this, 'on_show_focus', {
+ element: this._refUl.current,
+ })
+ } else if (parseFloat(active_item) > -1) {
+ const { selected_item } = this.state
+
+ if (fireSelectEvent) {
+ const attributes = this.attributes
+ const ret = dispatchCustomElementEvent(this.state, 'on_select', {
+ active_item,
+ value: getSelectedItemValue(selected_item, this.state),
+ data: getEventData(active_item, this.state.data),
+ event,
+ attributes,
+ })
+ if (ret === false) {
+ return // stop here!
}
+ }
- this.scrollToItem(active_item, { scrollTo })
+ if (isTrue(this.props.no_animation)) {
+ scrollTo = false
}
- )
- }
+
+ this.scrollToItem(active_item, { scrollTo })
+ }
+ })
}
removeDirectionObserver() {
@@ -1087,9 +1081,6 @@ export default class DrawerListProvider extends React.PureComponent {
ulElement: this._refUl.current,
})
- // Select the first item to NVDA is more easily navigateable,
- // without using the alt + arrow key
- // else we set the focus on the "ul" element
this.setActiveItemAndScrollToIt(
parseFloat(active_item) > -1 ? active_item : -1,
{ scrollTo: false }