Skip to content

Commit 52f5fd5

Browse files
committed
refactor(CDropdown): allow to select the next/previous element by press the up/down arrow
1 parent 4f19d4a commit 52f5fd5

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

packages/coreui-vue/src/components/dropdown/CDropdown.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,28 @@ export type Breakpoints =
1717

1818
export type Alignments = Directions | Breakpoints
1919

20+
export const getNextActiveElement = (
21+
list: HTMLElement[],
22+
activeElement: HTMLElement,
23+
shouldGetNext: boolean,
24+
isCycleAllowed: boolean,
25+
) => {
26+
const listLength = list.length
27+
let index = list.indexOf(activeElement)
28+
29+
if (index === -1) {
30+
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
31+
}
32+
33+
index += shouldGetNext ? 1 : -1
34+
35+
if (isCycleAllowed) {
36+
index = (index + listLength) % listLength
37+
}
38+
39+
return list[Math.max(0, Math.min(index, listLength - 1))]
40+
}
41+
2042
const getPlacement = (
2143
placement: Placement,
2244
direction: string | undefined,
@@ -214,13 +236,19 @@ const CDropdown = defineComponent({
214236
popper.value && initPopper(dropdownToggleRef.value, dropdownMenuRef.value, popperConfig)
215237
window.addEventListener('mouseup', handleMouseUp)
216238
window.addEventListener('keyup', handleKeyup)
239+
dropdownToggleRef.value.addEventListener('keydown', handleKeydown)
240+
dropdownMenuRef.value.addEventListener('keydown', handleKeydown)
217241
emit('show')
218242
return
219243
}
220244

221245
popper.value && destroyPopper()
222246
window.removeEventListener('mouseup', handleMouseUp)
223247
window.removeEventListener('keyup', handleKeyup)
248+
dropdownToggleRef.value &&
249+
dropdownToggleRef.value.removeEventListener('keydown', handleKeydown)
250+
dropdownMenuRef.value &&
251+
dropdownMenuRef.value.removeEventListener('keydown', handleKeydown)
224252
emit('hide')
225253
})
226254

@@ -235,6 +263,15 @@ const CDropdown = defineComponent({
235263
provide('dropdownToggleRef', dropdownToggleRef)
236264
provide('dropdownMenuRef', dropdownMenuRef)
237265

266+
const handleKeydown = (event: KeyboardEvent) => {
267+
if (visible.value && dropdownMenuRef.value && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
268+
event.preventDefault()
269+
const target = event.target as HTMLElement
270+
const items: HTMLElement[] = Array.from(dropdownMenuRef.value.querySelectorAll('.dropdown-item:not(.disabled):not(:disabled)'))
271+
getNextActiveElement(items, target, event.key === 'ArrowDown', true).focus()
272+
}
273+
}
274+
238275
const handleKeyup = (event: KeyboardEvent) => {
239276
if (props.autoClose === false) {
240277
return

0 commit comments

Comments
 (0)