Skip to content

Commit

Permalink
fix(#1564): replace document.activeElement with useActiveElement
Browse files Browse the repository at this point in the history
  • Loading branch information
pmairoldi committed Jan 21, 2025
1 parent 3bdf1d5 commit 700feb3
Show file tree
Hide file tree
Showing 23 changed files with 67 additions and 57 deletions.
6 changes: 3 additions & 3 deletions packages/radix-vue/src/Dialog/DialogContentImpl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
DismissableLayerEmits,
DismissableLayerProps,
} from '@/DismissableLayer'
import { useForwardExpose, useId } from '@/shared'
import { useActiveElement, useForwardExpose, useId } from '@/shared'
export type DialogContentImplEmits = DismissableLayerEmits & {
/**
Expand Down Expand Up @@ -54,8 +54,8 @@ onMounted(() => {
rootContext.contentElement = contentElement
// Preserve the `DialogTrigger` element in case it was triggered programmatically
if (document.activeElement !== document.body)
rootContext.triggerElement.value = document.activeElement as HTMLElement
if (useActiveElement() !== document.body)
rootContext.triggerElement.value = useActiveElement() as HTMLElement
})
if (process.env.NODE_ENV !== 'production') {
Expand Down
8 changes: 4 additions & 4 deletions packages/radix-vue/src/FocusScope/FocusScope.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { PrimitiveProps } from '@/Primitive'
import { useForwardExpose } from '@/shared'
import { useActiveElement, useForwardExpose } from '@/shared'
export type FocusScopeEmits = {
/**
Expand Down Expand Up @@ -142,7 +142,7 @@ watchEffect(async (cleanupFn) => {
if (!container)
return
focusScopesStack.add(focusScope)
const previouslyFocusedElement = document.activeElement as HTMLElement | null
const previouslyFocusedElement = useActiveElement() as HTMLElement | null
const hasFocusedCandidate = container.contains(previouslyFocusedElement)
if (!hasFocusedCandidate) {
Expand All @@ -155,7 +155,7 @@ watchEffect(async (cleanupFn) => {
focusFirst(removeLinks(getTabbableCandidates(container)), {
select: true,
})
if (document.activeElement === previouslyFocusedElement)
if (useActiveElement() === previouslyFocusedElement)
focus(container)
}
}
Expand Down Expand Up @@ -191,7 +191,7 @@ function handleKeyDown(event: KeyboardEvent) {
const isTabKey
= event.key === 'Tab' && !event.altKey && !event.ctrlKey && !event.metaKey
const focusedElement = document.activeElement as HTMLElement | null
const focusedElement = useActiveElement() as HTMLElement | null
if (isTabKey && focusedElement) {
const container = event.currentTarget as HTMLElement
Expand Down
8 changes: 5 additions & 3 deletions packages/radix-vue/src/FocusScope/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useActiveElement } from '@/shared'

export const AUTOFOCUS_ON_MOUNT = 'focusScope.autoFocusOnMount'
export const AUTOFOCUS_ON_UNMOUNT = 'focusScope.autoFocusOnUnmount'
export const EVENT_OPTIONS = { bubbles: false, cancelable: true }
Expand All @@ -9,10 +11,10 @@ type FocusableTarget = HTMLElement | { focus: () => void }
* Stops when focus has actually moved.
*/
export function focusFirst(candidates: HTMLElement[], { select = false } = {}) {
const previouslyFocusedElement = document.activeElement
const previouslyFocusedElement = useActiveElement()
for (const candidate of candidates) {
focus(candidate, { select })
if (document.activeElement !== previouslyFocusedElement)
if (useActiveElement() !== previouslyFocusedElement)
return true
}
}
Expand Down Expand Up @@ -96,7 +98,7 @@ export function focus(
) {
// only focus if that element is focusable
if (element && element.focus) {
const previouslyFocusedElement = document.activeElement
const previouslyFocusedElement = useActiveElement()
// NOTE: we prevent scrolling on focus, to minimize jarring transitions for users
element.focus({ preventScroll: true })
// only select if its not the same element, it supports selection and we need to select
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/Listbox/ListboxVirtualizer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { injectListboxRootContext } from './ListboxRoot.vue'
import { compare, queryCheckedElement } from './utils'
import { MAP_KEY_TO_FOCUS_INTENT } from '@/RovingFocus/utils'
import { refAutoReset } from '@vueuse/shared'
import { findValuesBetween } from '@/shared'
import { findValuesBetween, useActiveElement } from '@/shared'
import { getNextMatch } from '@/shared/useTypeahead'
import { useParentElement } from '@vueuse/core'
import { useCollection } from '@/Collection'
Expand Down Expand Up @@ -186,7 +186,7 @@ rootContext.virtualKeydownHook.on((event) => {
}
else if (!intent && !isMetaKey) {
search.value += event.key
const currentIndex = Number(document.activeElement?.getAttribute('data-index'))
const currentIndex = Number(useActiveElement()?.getAttribute('data-index'))
const currentMatch = optionsWithMetadata.value[currentIndex].textContent
const filteredOptions = optionsWithMetadata.value.map(i => i.textContent)
const next = getNextMatch(filteredOptions, search.value, currentMatch)
Expand Down
3 changes: 2 additions & 1 deletion packages/radix-vue/src/Menu/MenuContentImpl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { PopperContentProps } from '@/Popper'
import {
createContext,
useActiveElement,
useArrowNavigation,
useBodyScrollLock,
useCollection,
Expand Down Expand Up @@ -176,7 +177,7 @@ function handleKeyDown(event: KeyboardEvent) {
const el = useArrowNavigation(
event,
document.activeElement as HTMLElement,
useActiveElement() as HTMLElement,
contentElement.value,
{
loop: loop.value,
Expand Down
6 changes: 4 additions & 2 deletions packages/radix-vue/src/Menu/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useActiveElement } from '@/shared'

export type CheckedState = boolean | 'indeterminate'
export type Direction = 'ltr' | 'rtl'

Expand Down Expand Up @@ -35,13 +37,13 @@ export function getCheckedState(checked: CheckedState) {
}

export function focusFirst(candidates: HTMLElement[]) {
const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement
const PREVIOUSLY_FOCUSED_ELEMENT = useActiveElement()
for (const candidate of candidates) {
// if focus is already where we want to go, we don't want to keep going through the candidates
if (candidate === PREVIOUSLY_FOCUSED_ELEMENT)
return
candidate.focus()
if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)
if (useActiveElement() !== PREVIOUSLY_FOCUSED_ELEMENT)
return
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
FocusOutsideEvent,
} from '@/DismissableLayer'
import type { PointerDownOutsideEvent } from '@/DismissableLayer/utils'
import { useActiveElement, useArrowNavigation, useCollection, useForwardExpose } from '@/shared'
type MotionAttribute = 'to-start' | 'to-end' | 'from-start' | 'from-end'
Expand All @@ -25,7 +26,6 @@ import {
makeTriggerId,
} from './utils'
import { DismissableLayer } from '@/DismissableLayer'
import { useArrowNavigation, useCollection, useForwardExpose } from '@/shared'
import { injectNavigationMenuItemContext } from './NavigationMenuItem.vue'
const props = defineProps<NavigationMenuContentImplProps>()
Expand Down Expand Up @@ -114,7 +114,7 @@ watchEffect((cleanupFn) => {
const handleClose = () => {
menuContext.onItemDismiss()
itemContext.onRootContentClose()
if (content.contains(document.activeElement))
if (content.contains(useActiveElement()))
itemContext.triggerRef.value?.focus()
}
content.addEventListener(EVENT_ROOT_CONTENT_DISMISS, handleClose)
Expand Down Expand Up @@ -145,7 +145,7 @@ function handleKeydown(ev: KeyboardEvent) {
const candidates = getTabbableCandidates(ev.currentTarget as HTMLElement)
if (isTabKey) {
const focusedElement = document.activeElement
const focusedElement = useActiveElement()
const index = candidates.findIndex(
candidate => candidate === focusedElement,
)
Expand All @@ -169,7 +169,7 @@ function handleKeydown(ev: KeyboardEvent) {
const newSelectedElement = useArrowNavigation(
ev,
document.activeElement as HTMLElement,
useActiveElement() as HTMLElement,
undefined,
{ itemsArray: candidates, loop: false, enableIgnoredElement: true },
)
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/NavigationMenu/NavigationMenuItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { Ref } from 'vue'
import type { PrimitiveProps } from '@/Primitive'
import { createContext, useArrowNavigation, useCollection, useForwardExpose, useId } from '@/shared'
import { createContext, useActiveElement, useArrowNavigation, useCollection, useForwardExpose, useId } from '@/shared'
export interface NavigationMenuItemProps extends PrimitiveProps {
/**
Expand Down Expand Up @@ -95,7 +95,7 @@ function handleClose() {
}
function handleKeydown(ev: KeyboardEvent) {
const currentFocus = document.activeElement as HTMLElement
const currentFocus = useActiveElement() as HTMLElement
if (ev.keyCode === 32 || ev.key === 'Enter') {
if (context.modelValue.value === value) {
handleClose()
Expand Down
6 changes: 4 additions & 2 deletions packages/radix-vue/src/NavigationMenu/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useActiveElement } from '@/shared'

export type Orientation = 'vertical' | 'horizontal'
export type Direction = 'ltr' | 'rtl'

Expand Down Expand Up @@ -48,13 +50,13 @@ export function getTabbableCandidates(container: HTMLElement) {
}

export function focusFirst(candidates: HTMLElement[]) {
const previouslyFocusedElement = document.activeElement
const previouslyFocusedElement = useActiveElement()
return candidates.some((candidate) => {
// if focus is already where we want to go, we don't want to keep going through the candidates
if (candidate === previouslyFocusedElement)
return true
candidate.focus()
return document.activeElement !== previouslyFocusedElement
return useActiveElement() !== previouslyFocusedElement
})
}

Expand Down
3 changes: 2 additions & 1 deletion packages/radix-vue/src/NumberField/NumberFieldInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type { PrimitiveProps } from '@/Primitive'
import { injectNumberFieldRootContext } from './NumberFieldRoot.vue'
import { onMounted, ref, watch } from 'vue'
import { useActiveElement } from '@/shared'
export interface NumberFieldInputProps extends PrimitiveProps {
}
Expand All @@ -19,7 +20,7 @@ const rootContext = injectNumberFieldRootContext()
function handleWheelEvent(event: WheelEvent) {
// only handle when in focus
if (event.target !== document.activeElement)
if (event.target !== useActiveElement())
return
// if on a trackpad, users can scroll in both X and Y at once, check the magnitude of the change
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/PinInput/PinInputInput.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { Primitive, type PrimitiveProps, usePrimitiveElement } from '@/Primitive'
import { injectPinInputRootContext } from './PinInputRoot.vue'
import { useArrowNavigation } from '@/shared'
import { useActiveElement, useArrowNavigation } from '@/shared'
export interface PinInputInputProps extends PrimitiveProps {
/** Position of the value this input binds to. */
Expand Down Expand Up @@ -58,7 +58,7 @@ function resetPlaceholder() {
}
function handleKeydown(event: KeyboardEvent) {
useArrowNavigation(event, document.activeElement as HTMLElement, undefined, {
useArrowNavigation(event, useActiveElement() as HTMLElement, undefined, {
itemsArray: inputElements.value,
focus: true,
loop: false,
Expand Down
8 changes: 2 additions & 6 deletions packages/radix-vue/src/RovingFocus/RovingFocusItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface RovingFocusItemProps extends PrimitiveProps {
<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted } from 'vue'
import { injectRovingFocusGroupContext } from './RovingFocusGroup.vue'
import { Primitive, usePrimitiveElement } from '@/Primitive'
import { Primitive } from '@/Primitive'
import { focusFirst, getFocusIntent, wrapArray } from './utils'
import { useId } from '@/shared'
import { CollectionItem, useCollection } from '@/Collection'
Expand All @@ -31,9 +31,6 @@ const isCurrentTabStop = computed(
const { getItems } = useCollection()
const { primitiveElement, currentElement } = usePrimitiveElement()
const rootNode = computed(() => currentElement.value?.getRootNode() as Document | ShadowRoot)
onMounted(() => {
if (props.focusable)
context.onFocusableItemAdd()
Expand Down Expand Up @@ -79,15 +76,14 @@ function handleKeydown(event: KeyboardEvent) {
: candidateNodes.slice(currentIndex + 1)
}
nextTick(() => focusFirst(candidateNodes, false, rootNode.value))
nextTick(() => focusFirst(candidateNodes))
}
}
</script>

<template>
<CollectionItem>
<Primitive
ref="primitiveElement"
:tabindex="isCurrentTabStop ? 0 : -1"
:data-orientation="context.orientation.value"
:data-active="active"
Expand Down
8 changes: 5 additions & 3 deletions packages/radix-vue/src/RovingFocus/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useActiveElement } from '@/shared'

export type Orientation = 'horizontal' | 'vertical'
export type Direction = 'ltr' | 'rtl'

Expand Down Expand Up @@ -40,14 +42,14 @@ export function getFocusIntent(
return MAP_KEY_TO_FOCUS_INTENT[key]
}

export function focusFirst(candidates: HTMLElement[], preventScroll = false, rootNode?: Document | ShadowRoot) {
const PREVIOUSLY_FOCUSED_ELEMENT = rootNode?.activeElement ?? document.activeElement
export function focusFirst(candidates: HTMLElement[], preventScroll = false) {
const PREVIOUSLY_FOCUSED_ELEMENT = useActiveElement()
for (const candidate of candidates) {
// if focus is already where we want to go, we don't want to keep going through the candidates
if (candidate === PREVIOUSLY_FOCUSED_ELEMENT)
return
candidate.focus({ preventScroll })
if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)
if (useActiveElement() !== PREVIOUSLY_FOCUSED_ELEMENT)
return
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/Select/SelectItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { Ref } from 'vue'
import type { PrimitiveProps } from '@/Primitive'
import { createContext, useForwardExpose, useId } from '@/shared'
import { createContext, useActiveElement, useForwardExpose, useId } from '@/shared'
interface SelectItemContext {
value: string
Expand Down Expand Up @@ -84,7 +84,7 @@ async function handlePointerLeave(event: PointerEvent) {
await nextTick()
if (event.defaultPrevented)
return
if (event.currentTarget === document.activeElement)
if (event.currentTarget === useActiveElement())
contentContext.onItemLeave?.()
}
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/Select/SelectScrollButtonImpl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { onBeforeUnmount, ref, watchEffect } from 'vue'
import { SelectContentDefaultContextValue, injectSelectContentContext } from './SelectContentImpl.vue'
import { Primitive } from '@/Primitive'
import { useCollection } from '@/shared'
import { useActiveElement, useCollection } from '@/shared'
export type SelectScrollButtonImplEmits = {
autoScroll: []
Expand All @@ -24,7 +24,7 @@ function clearAutoScrollTimer() {
watchEffect(() => {
const activeItem = collectionItems.value.find(
item => item === document.activeElement,
item => item === useActiveElement(),
)
activeItem?.scrollIntoView({ block: 'nearest' })
})
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/Stepper/StepperTrigger.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { PrimitiveProps } from '@/Primitive'
import { useArrowNavigation, useForwardExpose, useKbd } from '@/shared'
import { useActiveElement, useArrowNavigation, useForwardExpose, useKbd } from '@/shared'
import { computed, onMounted, onUnmounted } from 'vue'
export interface StepperTriggerProps extends PrimitiveProps {
Expand Down Expand Up @@ -54,7 +54,7 @@ function handleKeyDown(event: KeyboardEvent) {
rootContext.changeModelValue(itemContext.step.value)
if ([kbd.ARROW_LEFT, kbd.ARROW_RIGHT, kbd.ARROW_UP, kbd.ARROW_DOWN].includes(event.key)) {
useArrowNavigation(event, document.activeElement as HTMLElement, undefined, {
useArrowNavigation(event, useActiveElement() as HTMLElement, undefined, {
itemsArray: stepperItems.value,
focus: true,
loop: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/radix-vue/src/Toast/ToastRootImpl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { isClient } from '@vueuse/shared'
import type { PrimitiveProps } from '@/Primitive'
import type { SwipeEvent } from './utils'
import { createContext, useForwardExpose } from '@/shared'
import { createContext, useActiveElement, useForwardExpose } from '@/shared'
export type ToastRootImplEmits = {
close: []
Expand Down Expand Up @@ -98,7 +98,7 @@ function startTimer(duration: number) {
function handleClose() {
// focus viewport if focus is within toast to read the remaining toast
// count to SR users and ensure focus isn't lost
const isFocusInToast = currentElement.value?.contains(document.activeElement)
const isFocusInToast = currentElement.value?.contains(useActiveElement())
if (isFocusInToast)
providerContext.viewport.value?.focus()
Expand Down
Loading

0 comments on commit 700feb3

Please sign in to comment.