Update API
This commit is contained in:
@@ -21,7 +21,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Toast} from '#/components/Toast/Toast'
|
||||
import {type ToastType} from '#/components/Toast/types'
|
||||
import {type ToastApi, type ToastType} from '#/components/Toast/types'
|
||||
|
||||
const TIMEOUT = 2e3
|
||||
const TOAST_ANIMATION_DURATION = 300
|
||||
@@ -30,30 +30,36 @@ export function ToastContainer() {
|
||||
return null
|
||||
}
|
||||
|
||||
export function show(message: string, type: ToastType = 'default'): void {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
return
|
||||
}
|
||||
export const toast: ToastApi = {
|
||||
show(props) {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
return
|
||||
}
|
||||
|
||||
AccessibilityInfo.announceForAccessibility(message)
|
||||
const item = new RootSiblings(
|
||||
(
|
||||
<AnimatedToast
|
||||
message={message}
|
||||
type={type}
|
||||
destroy={() => item.destroy()}
|
||||
/>
|
||||
),
|
||||
)
|
||||
AccessibilityInfo.announceForAccessibility(props.a11yLabel)
|
||||
|
||||
const item = new RootSiblings(
|
||||
(
|
||||
<AnimatedToast
|
||||
type={props.type}
|
||||
content={props.content}
|
||||
a11yLabel={props.a11yLabel}
|
||||
destroy={() => item.destroy()}
|
||||
/>
|
||||
),
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
function AnimatedToast({
|
||||
message,
|
||||
type,
|
||||
content,
|
||||
a11yLabel,
|
||||
destroy,
|
||||
}: {
|
||||
message: string
|
||||
type: ToastType
|
||||
content: React.ReactNode
|
||||
a11yLabel: string
|
||||
destroy: () => void
|
||||
}) {
|
||||
const {top} = useSafeAreaInsets()
|
||||
@@ -169,12 +175,12 @@ function AnimatedToast({
|
||||
onLayout={evt => setCardHeight(evt.nativeEvent.layout.height)}
|
||||
accessibilityRole="alert"
|
||||
accessible={true}
|
||||
accessibilityLabel={message}
|
||||
accessibilityLabel={a11yLabel}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={hideAndDestroyImmediately}
|
||||
style={[a.flex_1, animatedStyle]}>
|
||||
<GestureDetector gesture={panGesture}>
|
||||
<Toast content={message} type={type} />
|
||||
<Toast content={content} type={type} />
|
||||
</GestureDetector>
|
||||
</Animated.View>
|
||||
)}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
*/
|
||||
|
||||
import {useEffect, useState} from 'react'
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {AccessibilityInfo, Pressable, View} from 'react-native'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {atoms as a, web} from '#/alf'
|
||||
import {Toast} from '#/components/Toast/Toast'
|
||||
import {type ToastType} from '#/components/Toast/types'
|
||||
import {type ToastApi, type ToastType} from '#/components/Toast/types'
|
||||
|
||||
const DURATION = 3500
|
||||
const TOAST_ANIMATION_STYLES = {
|
||||
@@ -22,8 +22,9 @@ const TOAST_ANIMATION_STYLES = {
|
||||
}
|
||||
|
||||
interface ActiveToast {
|
||||
text: string
|
||||
type: ToastType
|
||||
content: React.ReactNode
|
||||
a11yLabel: string
|
||||
}
|
||||
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
|
||||
let globalSetActiveToast: GlobalSetActiveToast | undefined
|
||||
@@ -44,6 +45,9 @@ export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||
setIsExiting(false)
|
||||
}, 200)
|
||||
} else {
|
||||
if (t) {
|
||||
AccessibilityInfo.announceForAccessibility(t.a11yLabel)
|
||||
}
|
||||
setActiveToast(t)
|
||||
setIsExiting(false)
|
||||
}
|
||||
@@ -66,7 +70,7 @@ export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||
: TOAST_ANIMATION_STYLES.entering),
|
||||
},
|
||||
]}>
|
||||
<Toast content={activeToast.text} type={activeToast.type} />
|
||||
<Toast content={activeToast.content} type={activeToast.type} />
|
||||
<Pressable
|
||||
style={[a.absolute, a.inset_0]}
|
||||
accessibilityLabel={_(msg`Dismiss toast`)}
|
||||
@@ -79,13 +83,20 @@ export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||
)
|
||||
}
|
||||
|
||||
export function show(text: string, type: ToastType = 'default') {
|
||||
if (toastTimeout) {
|
||||
clearTimeout(toastTimeout)
|
||||
}
|
||||
export const toast: ToastApi = {
|
||||
show(props) {
|
||||
if (toastTimeout) {
|
||||
clearTimeout(toastTimeout)
|
||||
}
|
||||
|
||||
globalSetActiveToast?.({text, type})
|
||||
toastTimeout = setTimeout(() => {
|
||||
globalSetActiveToast?.(undefined)
|
||||
}, DURATION)
|
||||
globalSetActiveToast?.({
|
||||
type: props.type,
|
||||
content: props.content,
|
||||
a11yLabel: props.a11yLabel,
|
||||
})
|
||||
|
||||
toastTimeout = setTimeout(() => {
|
||||
globalSetActiveToast?.(undefined)
|
||||
}, DURATION)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
|
||||
|
||||
export type ToastApi = {
|
||||
show: (props: {
|
||||
type: ToastType
|
||||
content: React.ReactNode
|
||||
a11yLabel: string
|
||||
}) => void
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {show as baseShow} from '#/components/Toast'
|
||||
import {toast} from '#/components/Toast'
|
||||
import {type ToastType} from '#/components/Toast/types'
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ToastType} and {@link baseShow} instead
|
||||
* @deprecated use {@link ToastType} and {@link toast} instead
|
||||
*/
|
||||
export type LegacyToastType =
|
||||
| 'xmark'
|
||||
@@ -39,12 +39,16 @@ export const convertLegacyToastType = (
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link baseShow} instead
|
||||
* @deprecated use {@link toast} instead
|
||||
*/
|
||||
export function show(
|
||||
message: string,
|
||||
type: ToastType | LegacyToastType = 'default',
|
||||
): void {
|
||||
const convertedType = convertLegacyToastType(type)
|
||||
baseShow(message, convertedType)
|
||||
toast.show({
|
||||
type: convertedType,
|
||||
content: message,
|
||||
a11yLabel: message,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {Pressable, View} from 'react-native'
|
||||
import {show as deprecatedShow} from '#/view/com/util/Toast'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {show} from '#/components/Toast'
|
||||
import {toast} from '#/components/Toast'
|
||||
import {Toast} from '#/components/Toast/Toast'
|
||||
import {H1} from '#/components/Typography'
|
||||
|
||||
@@ -15,16 +15,25 @@ export function Toasts() {
|
||||
<View style={[a.gap_md]}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => show('Default toast', 'default')}>
|
||||
onPress={() =>
|
||||
toast.show({
|
||||
type: 'default',
|
||||
content: 'Default toast',
|
||||
a11yLabel: 'Default toast',
|
||||
})
|
||||
}>
|
||||
<Toast content="Default toast" type="default" />
|
||||
</Pressable>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() =>
|
||||
show(
|
||||
'This is a longer message to test how the toast handles multiple lines of text content.',
|
||||
'default',
|
||||
)
|
||||
toast.show({
|
||||
type: 'default',
|
||||
content:
|
||||
'This is a longer message to test how the toast handles multiple lines of text content.',
|
||||
a11yLabel:
|
||||
'This is a longer message to test how the toast handles multiple lines of text content.',
|
||||
})
|
||||
}>
|
||||
<Toast
|
||||
content="This is a longer message to test how the toast handles multiple lines of text content."
|
||||
@@ -33,22 +42,46 @@ export function Toasts() {
|
||||
</Pressable>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => show('Success toast', 'success')}>
|
||||
onPress={() =>
|
||||
toast.show({
|
||||
type: 'success',
|
||||
content: 'Success toast',
|
||||
a11yLabel: 'Success toast',
|
||||
})
|
||||
}>
|
||||
<Toast content="Success toast" type="success" />
|
||||
</Pressable>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => show('Info toast', 'info')}>
|
||||
onPress={() =>
|
||||
toast.show({
|
||||
type: 'info',
|
||||
content: 'Info toast',
|
||||
a11yLabel: 'Info toast',
|
||||
})
|
||||
}>
|
||||
<Toast content="Info" type="info" />
|
||||
</Pressable>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => show('Warning toast', 'warning')}>
|
||||
onPress={() =>
|
||||
toast.show({
|
||||
type: 'warning',
|
||||
content: 'Warning toast',
|
||||
a11yLabel: 'Warning toast',
|
||||
})
|
||||
}>
|
||||
<Toast content="Warning" type="warning" />
|
||||
</Pressable>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => show('Error toast', 'error')}>
|
||||
onPress={() =>
|
||||
toast.show({
|
||||
type: 'error',
|
||||
content: 'Error toast',
|
||||
a11yLabel: 'Error toast',
|
||||
})
|
||||
}>
|
||||
<Toast content="Error" type="error" />
|
||||
</Pressable>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user