Fix reactivity of dialogs (Dialogs Pt. 1) (#3146)
* Improve a11y on ios * Format * Remove android * Fix android * Revert some changes * use sharedvalue for `importantForAccessibility` * add back `isOpen` * fix some more types --------- Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
parent
8f623c3bdf
commit
0f9f08b1ef
4 changed files with 49 additions and 38 deletions
|
@ -1,8 +1,9 @@
|
|||
import React from 'react'
|
||||
import {SharedValue, useSharedValue} from 'react-native-reanimated'
|
||||
import {DialogControlRefProps} from '#/components/Dialog'
|
||||
import {Provider as GlobalDialogsProvider} from '#/components/dialogs/Context'
|
||||
|
||||
const DialogContext = React.createContext<{
|
||||
interface IDialogContext {
|
||||
/**
|
||||
* The currently active `useDialogControl` hooks.
|
||||
*/
|
||||
|
@ -13,13 +14,18 @@ const DialogContext = React.createContext<{
|
|||
* The currently open dialogs, referenced by their IDs, generated from
|
||||
* `useId`.
|
||||
*/
|
||||
openDialogs: string[]
|
||||
}>({
|
||||
activeDialogs: {
|
||||
current: new Map(),
|
||||
},
|
||||
openDialogs: [],
|
||||
})
|
||||
openDialogs: React.MutableRefObject<Set<string>>
|
||||
/**
|
||||
* The counterpart to `accessibilityViewIsModal` for Android. This property
|
||||
* applies to the parent of all non-modal views, and prevents TalkBack from
|
||||
* navigating within content beneath an open dialog.
|
||||
*
|
||||
* @see https://reactnative.dev/docs/accessibility#importantforaccessibility-android
|
||||
*/
|
||||
importantForAccessibility: SharedValue<'auto' | 'no-hide-descendants'>
|
||||
}
|
||||
|
||||
const DialogContext = React.createContext<IDialogContext>({} as IDialogContext)
|
||||
|
||||
const DialogControlContext = React.createContext<{
|
||||
closeAllDialogs(): boolean
|
||||
|
@ -41,26 +47,42 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||
const activeDialogs = React.useRef<
|
||||
Map<string, React.MutableRefObject<DialogControlRefProps>>
|
||||
>(new Map())
|
||||
const [openDialogs, setOpenDialogs] = React.useState<string[]>([])
|
||||
const openDialogs = React.useRef<Set<string>>(new Set())
|
||||
const importantForAccessibility = useSharedValue<
|
||||
'auto' | 'no-hide-descendants'
|
||||
>('auto')
|
||||
|
||||
const closeAllDialogs = React.useCallback(() => {
|
||||
activeDialogs.current.forEach(dialog => dialog.current.close())
|
||||
return openDialogs.length > 0
|
||||
}, [openDialogs])
|
||||
return openDialogs.current.size > 0
|
||||
}, [])
|
||||
|
||||
const setDialogIsOpen = React.useCallback(
|
||||
(id: string, isOpen: boolean) => {
|
||||
setOpenDialogs(prev => {
|
||||
const filtered = prev.filter(dialogId => dialogId !== id) as string[]
|
||||
return isOpen ? [...filtered, id] : filtered
|
||||
})
|
||||
if (isOpen) {
|
||||
openDialogs.current.add(id)
|
||||
importantForAccessibility.value = 'no-hide-descendants'
|
||||
} else {
|
||||
openDialogs.current.delete(id)
|
||||
if (openDialogs.current.size < 1) {
|
||||
importantForAccessibility.value = 'auto'
|
||||
}
|
||||
}
|
||||
},
|
||||
[setOpenDialogs],
|
||||
[importantForAccessibility],
|
||||
)
|
||||
|
||||
const context = React.useMemo(
|
||||
() => ({activeDialogs, openDialogs}),
|
||||
[openDialogs],
|
||||
const context = React.useMemo<IDialogContext>(
|
||||
() => ({
|
||||
activeDialogs: {
|
||||
current: new Map(),
|
||||
},
|
||||
openDialogs: {
|
||||
current: new Set(),
|
||||
},
|
||||
importantForAccessibility,
|
||||
}),
|
||||
[importantForAccessibility],
|
||||
)
|
||||
const controls = React.useMemo(
|
||||
() => ({closeAllDialogs, setDialogIsOpen}),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue