Skip to content

Commit

Permalink
keep track of a data-headlessui-focus-visible attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinMalfait committed Mar 9, 2023
1 parent 48603f3 commit 4c4c3f9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
41 changes: 41 additions & 0 deletions packages/@headlessui-react/src/utils/focus-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,47 @@ export function restoreFocusIfNecessary(element: HTMLElement | null) {
})
}

// The method of triggering an action, this is used to determine how we should
// restore focus after an action has been performed.
enum ActivationMethod {
/* If the action was triggered by a keyboard event. */
Keyboard = 0,

/* If the action was triggered by a mouse / pointer / ... event.*/
Mouse = 1,
}

// We want to be able to set and remove the `data-headlessui-mouse` attribute on the `html` element.
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
document.addEventListener(
'keydown',
(event) => {
if (event.metaKey || event.altKey || event.ctrlKey) {
return
}

document.documentElement.dataset.headlessuiFocusVisible = ''
},
true
)

document.addEventListener(
'click',
(event) => {
// Event originated from an actual mouse click
if (event.detail === ActivationMethod.Mouse) {
delete document.documentElement.dataset.headlessuiFocusVisible
}

// Event originated from a keyboard event that triggered the `click` event
else if (event.detail === ActivationMethod.Keyboard) {
document.documentElement.dataset.headlessuiFocusVisible = ''
}
},
true
)
}

export function focusElement(element: HTMLElement | null) {
element?.focus({ preventScroll: true })
}
Expand Down
41 changes: 41 additions & 0 deletions packages/@headlessui-vue/src/utils/focus-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,47 @@ export function restoreFocusIfNecessary(element: HTMLElement | null) {
})
}

// The method of triggering an action, this is used to determine how we should
// restore focus after an action has been performed.
enum ActivationMethod {
/* If the action was triggered by a keyboard event. */
Keyboard = 0,

/* If the action was triggered by a mouse / pointer / ... event.*/
Mouse = 1,
}

// We want to be able to set and remove the `data-headlessui-mouse` attribute on the `html` element.
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
document.addEventListener(
'keydown',
(event) => {
if (event.metaKey || event.altKey || event.ctrlKey) {
return
}

document.documentElement.dataset.headlessuiFocusVisible = ''
},
true
)

document.addEventListener(
'click',
(event) => {
// Event originated from an actual mouse click
if (event.detail === ActivationMethod.Mouse) {
delete document.documentElement.dataset.headlessuiFocusVisible
}

// Event originated from a keyboard event that triggered the `click` event
else if (event.detail === ActivationMethod.Keyboard) {
document.documentElement.dataset.headlessuiFocusVisible = ''
}
},
true
)
}

export function focusElement(element: HTMLElement | null) {
element?.focus({ preventScroll: true })
}
Expand Down

0 comments on commit 4c4c3f9

Please sign in to comment.