When building modals or dropdown menus, you need to know which elements can receive focus. This selector list covers the usual suspects — links, inputs, buttons, and anything with a non-negative tabindex.
export const FOCUSABLE_ELEMENTS = [
'a[href]',
'area[href]',
'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
'select:not([disabled]):not([aria-hidden])',
'textarea:not([disabled]):not([aria-hidden])',
'button:not([disabled]):not([aria-hidden])',
'iframe',
'object',
'embed',
'[contenteditable]',
'[tabindex]:not([tabindex^="-"])',
]
export const getFocusableNodes = (context: HTMLElement) =>
context.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENTS.join(','))
export const getOffset = (element: HTMLElement) => {
const rect = element.getBoundingClientRect()
return {
top: rect.top + window.scrollY,
left: rect.left + window.scrollX,
}
}