Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e517a6e970 | |||
| 9a715c4cda | |||
| 159337f446 | |||
| 3c5a8ed066 | |||
| 84fbea9137 | |||
| 51835f5b41 | |||
| a4017dbdff | |||
| 023363e6e9 | |||
| d15358cd1a | |||
| 3c3208ef11 | |||
| ecc5927002 | |||
| 507290474d | |||
| 4542a09ab7 | |||
| ddfba8c2c6 | |||
| bedd7f2d0f | |||
| 2f878e926f | |||
| 654a5782c6 | |||
| 3445031205 | |||
| 2ce8331909 | |||
| 6656253749 | |||
| f1ab948a93 |
@@ -0,0 +1 @@
|
||||
dialog-alert-type@9a715c4cda486d249c0a647d9606fdee51b6c9c9
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"src/components/Dialog/index.tsx": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 2
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/Dialog/index.web.tsx": {
|
||||
|
||||
@@ -21,9 +21,11 @@ import {
|
||||
Context as PortalContext,
|
||||
} from './BottomSheetPortal'
|
||||
|
||||
type NativeViewRef = {dismiss: () => void}
|
||||
|
||||
const NativeView: React.ComponentType<
|
||||
BottomSheetViewProps & {
|
||||
ref: React.RefObject<any>
|
||||
ref: React.RefObject<NativeViewRef | null>
|
||||
style: StyleProp<ViewStyle>
|
||||
}
|
||||
> = requireNativeViewManager('BottomSheet')
|
||||
@@ -46,7 +48,7 @@ export class BottomSheetNativeComponent extends Component<
|
||||
viewHeight?: number
|
||||
}
|
||||
> {
|
||||
ref = createRef<any>()
|
||||
ref = createRef<NativeViewRef>()
|
||||
|
||||
static contextType = PortalContext
|
||||
|
||||
@@ -140,7 +142,7 @@ function BottomSheetNativeComponentInner({
|
||||
onStateChange: (
|
||||
event: NativeSyntheticEvent<{state: BottomSheetState}>,
|
||||
) => void
|
||||
nativeViewRef: React.RefObject<View>
|
||||
nativeViewRef: React.RefObject<NativeViewRef | null>
|
||||
onLayout?: (event: LayoutChangeEvent) => void
|
||||
}) {
|
||||
const insets = useSafeAreaInsets()
|
||||
|
||||
@@ -23,6 +23,7 @@ export const Context = createContext<DialogContextProps>({
|
||||
disableDrag: false,
|
||||
setDisableDrag: () => {},
|
||||
isWithinDialog: false,
|
||||
type: 'sheet',
|
||||
isHeightConstrained: false,
|
||||
})
|
||||
Context.displayName = 'DialogContext'
|
||||
|
||||
+119
-48
@@ -10,6 +10,7 @@ import {
|
||||
Keyboard,
|
||||
type KeyboardEventListener,
|
||||
type LayoutChangeEvent,
|
||||
Modal,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
Pressable,
|
||||
@@ -30,9 +31,7 @@ import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||
import {logger} from '#/logger'
|
||||
import {useA11y} from '#/state/a11y'
|
||||
import {useDialogStateControlContext} from '#/state/dialogs'
|
||||
import {List, type ListMethods, type ListProps} from '#/view/com/util/List'
|
||||
import {android, atoms as a, ios, platform, tokens, useTheme} from '#/alf'
|
||||
import {useThemeName} from '#/alf/util/useColorModeTheme'
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
type DialogInnerProps,
|
||||
type DialogOuterProps,
|
||||
} from '#/components/Dialog/types'
|
||||
import {useDialogCallbackQueue} from '#/components/Dialog/utils'
|
||||
import {createInput} from '#/components/forms/TextField'
|
||||
import {useOnKeyboard} from '#/components/hooks/useOnKeyboard'
|
||||
import {IS_ANDROID, IS_IOS, IS_LIQUID_GLASS} from '#/env'
|
||||
@@ -59,7 +59,92 @@ export * from '#/components/Dialog/utils'
|
||||
|
||||
export const Input = createInput(TextInput)
|
||||
|
||||
export function Outer({
|
||||
export function Outer(props: React.PropsWithChildren<DialogOuterProps>) {
|
||||
if (props.type === 'alert') {
|
||||
return <OuterAlert {...props} />
|
||||
}
|
||||
return <OuterSheet {...props} />
|
||||
}
|
||||
|
||||
function OuterAlert({
|
||||
children,
|
||||
control,
|
||||
onClose,
|
||||
testID,
|
||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||
const t = useTheme()
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const {enqueueCallback, handleOpen, handleClose} = useDialogCallbackQueue(
|
||||
control,
|
||||
onClose,
|
||||
)
|
||||
|
||||
const open: DialogControlProps['open'] = () => {
|
||||
handleOpen()
|
||||
setIsOpen(true)
|
||||
}
|
||||
|
||||
const close: DialogControlProps['close'] = cb => {
|
||||
enqueueCallback(cb)
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
const onDismiss = () => {
|
||||
handleClose()
|
||||
}
|
||||
|
||||
useImperativeHandle(control.ref, () => ({open, close}), [open, close])
|
||||
|
||||
const context = useMemo(
|
||||
() => ({
|
||||
close,
|
||||
isNativeDialog: true,
|
||||
nativeSnapPoint: BottomSheetSnapPoint.Hidden,
|
||||
disableDrag: false,
|
||||
setDisableDrag: () => {},
|
||||
isWithinDialog: true,
|
||||
type: 'alert' as const,
|
||||
isHeightConstrained: false,
|
||||
}),
|
||||
[close],
|
||||
)
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={isOpen}
|
||||
transparent
|
||||
animationType="fade"
|
||||
onRequestClose={() => close()}
|
||||
onDismiss={onDismiss}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => close()}
|
||||
style={[
|
||||
a.flex_1,
|
||||
a.justify_center,
|
||||
a.align_center,
|
||||
a.px_xl,
|
||||
{backgroundColor: 'rgba(0,0,0,0.5)'},
|
||||
]}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={e => e.stopPropagation()}
|
||||
style={[
|
||||
t.atoms.bg,
|
||||
a.w_full,
|
||||
{borderRadius: 48, maxWidth: 320, maxHeight: '90%'},
|
||||
a.overflow_hidden,
|
||||
]}>
|
||||
<Context.Provider value={context}>
|
||||
<View testID={testID}>{children}</View>
|
||||
</Context.Provider>
|
||||
</Pressable>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
function OuterSheet({
|
||||
children,
|
||||
control,
|
||||
onClose,
|
||||
@@ -69,9 +154,8 @@ export function Outer({
|
||||
const themeName = useThemeName()
|
||||
const t = useTheme(themeName)
|
||||
const ref = useRef<BottomSheetNativeComponent>(null)
|
||||
const closeCallbacks = useRef<(() => void)[]>([])
|
||||
const {setDialogIsOpen, setFullyExpandedCount} =
|
||||
useDialogStateControlContext()
|
||||
const {enqueueCallback, handleOpen, handleClose, setFullyExpandedCount} =
|
||||
useDialogCallbackQueue(control, onClose)
|
||||
|
||||
const prevSnapPoint = useRef<BottomSheetSnapPoint>(
|
||||
BottomSheetSnapPoint.Hidden,
|
||||
@@ -82,42 +166,20 @@ export function Outer({
|
||||
BottomSheetSnapPoint.Partial,
|
||||
)
|
||||
|
||||
const callQueuedCallbacks = useCallback(() => {
|
||||
for (const cb of closeCallbacks.current) {
|
||||
try {
|
||||
cb()
|
||||
} catch (e: any) {
|
||||
logger.error(e || 'Error running close callback')
|
||||
}
|
||||
}
|
||||
|
||||
closeCallbacks.current = []
|
||||
}, [])
|
||||
|
||||
const open = useCallback<DialogControlProps['open']>(() => {
|
||||
// Run any leftover callbacks that might have been queued up before calling `.open()`
|
||||
callQueuedCallbacks()
|
||||
setDialogIsOpen(control.id, true)
|
||||
const open: DialogControlProps['open'] = () => {
|
||||
handleOpen()
|
||||
ref.current?.present()
|
||||
}, [setDialogIsOpen, control.id, callQueuedCallbacks])
|
||||
}
|
||||
|
||||
// This is the function that we call when we want to dismiss the dialog.
|
||||
const close = useCallback<DialogControlProps['close']>(cb => {
|
||||
if (typeof cb === 'function') {
|
||||
closeCallbacks.current.push(cb)
|
||||
}
|
||||
const close: DialogControlProps['close'] = cb => {
|
||||
enqueueCallback(cb)
|
||||
ref.current?.dismiss()
|
||||
}, [])
|
||||
}
|
||||
|
||||
// This is the actual thing we are doing once we "confirm" the dialog. We want the dialog's close animation to
|
||||
// happen before we run this. It is passed to the `BottomSheet` component.
|
||||
const onCloseAnimationComplete = useCallback(() => {
|
||||
// This removes the dialog from our list of stored dialogs. Not super necessary on iOS, but on Android this
|
||||
// tells us that we need to toggle the accessibility overlay setting
|
||||
setDialogIsOpen(control.id, false)
|
||||
callQueuedCallbacks()
|
||||
onClose?.()
|
||||
}, [callQueuedCallbacks, control.id, onClose, setDialogIsOpen])
|
||||
// Runs after the bottom sheet close animation completes.
|
||||
const onCloseAnimationComplete = () => {
|
||||
handleClose()
|
||||
}
|
||||
|
||||
const onSnapPointChange = (e: BottomSheetSnapPointChangeEvent) => {
|
||||
const {snapPoint} = e.nativeEvent
|
||||
@@ -148,14 +210,7 @@ export function Outer({
|
||||
}
|
||||
}
|
||||
|
||||
useImperativeHandle(
|
||||
control.ref,
|
||||
() => ({
|
||||
open,
|
||||
close,
|
||||
}),
|
||||
[open, close],
|
||||
)
|
||||
useImperativeHandle(control.ref, () => ({open, close}), [open, close])
|
||||
|
||||
const isHeightConstrained = nativeOptions?.maxHeight != null
|
||||
|
||||
@@ -167,6 +222,7 @@ export function Outer({
|
||||
disableDrag,
|
||||
setDisableDrag,
|
||||
isWithinDialog: true,
|
||||
type: 'sheet' as const,
|
||||
isHeightConstrained,
|
||||
}),
|
||||
[close, snapPoint, disableDrag, setDisableDrag, isHeightConstrained],
|
||||
@@ -221,8 +277,14 @@ export const ScrollableInner = forwardRef<ScrollView, DialogInnerProps>(
|
||||
{children, contentContainerStyle, header, style, ...props},
|
||||
ref,
|
||||
) {
|
||||
const {nativeSnapPoint, disableDrag, setDisableDrag, isHeightConstrained} =
|
||||
useDialogContext()
|
||||
const {
|
||||
nativeSnapPoint,
|
||||
disableDrag,
|
||||
setDisableDrag,
|
||||
type,
|
||||
isHeightConstrained,
|
||||
} = useDialogContext()
|
||||
|
||||
const isAtMaxSnapPoint = nativeSnapPoint === BottomSheetSnapPoint.Full
|
||||
const insets = useSafeAreaInsets()
|
||||
const [keyboardHeight, setKeyboardHeight] = useState(() =>
|
||||
@@ -235,6 +297,15 @@ export const ScrollableInner = forwardRef<ScrollView, DialogInnerProps>(
|
||||
useOnKeyboard('keyboardDidShow', keyboardEventHandler)
|
||||
useOnKeyboard('keyboardDidHide', keyboardEventHandler)
|
||||
|
||||
if (type === 'alert') {
|
||||
return (
|
||||
<View style={[a.p_2xl, contentContainerStyle]} {...props}>
|
||||
{header}
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||
if (!IS_ANDROID) {
|
||||
return
|
||||
|
||||
@@ -52,6 +52,7 @@ export function Outer({
|
||||
control,
|
||||
onClose,
|
||||
webOptions,
|
||||
type = 'sheet',
|
||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||
const {_} = useLingui()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -103,6 +104,8 @@ export function Outer({
|
||||
[close, open],
|
||||
)
|
||||
|
||||
const isAlert = type === 'alert'
|
||||
|
||||
const context = useMemo(
|
||||
() => ({
|
||||
close,
|
||||
@@ -111,9 +114,10 @@ export function Outer({
|
||||
disableDrag: false,
|
||||
setDisableDrag: () => {},
|
||||
isWithinDialog: true,
|
||||
type,
|
||||
isHeightConstrained: false,
|
||||
}),
|
||||
[close],
|
||||
[close, type],
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -132,7 +136,9 @@ export function Outer({
|
||||
a.inset_0,
|
||||
a.z_10,
|
||||
a.px_xl,
|
||||
webOptions?.alignCenter ? a.justify_center : undefined,
|
||||
webOptions?.alignCenter || isAlert
|
||||
? a.justify_center
|
||||
: undefined,
|
||||
a.align_center,
|
||||
{
|
||||
overflowY: 'auto',
|
||||
@@ -173,9 +179,10 @@ export function Inner({
|
||||
contentContainerStyle,
|
||||
}: DialogInnerProps) {
|
||||
const t = useTheme()
|
||||
const {close} = useContext(Context)
|
||||
const {close, type} = useContext(Context)
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {reduceMotionEnabled} = useA11y()
|
||||
const isAlert = type === 'alert'
|
||||
FocusGuards.useFocusGuards()
|
||||
return (
|
||||
<FocusScope.FocusScope loop asChild trapped>
|
||||
@@ -198,12 +205,13 @@ export function Inner({
|
||||
t.atoms.bg,
|
||||
{
|
||||
cursor: 'default', // The overlay applies `cursor: 'pointer'` to all children.
|
||||
maxWidth: 600,
|
||||
maxWidth: isAlert ? 320 : 600,
|
||||
borderColor: t.palette.contrast_200,
|
||||
shadowColor: t.palette.black,
|
||||
shadowOpacity: t.name === 'light' ? 0.1 : 0.4,
|
||||
shadowRadius: 30,
|
||||
},
|
||||
isAlert && {borderRadius: 36},
|
||||
!reduceMotionEnabled && a.zoom_fade_in,
|
||||
style,
|
||||
])}>
|
||||
|
||||
@@ -45,6 +45,7 @@ export type DialogContextProps = {
|
||||
setDisableDrag: React.Dispatch<React.SetStateAction<boolean>>
|
||||
// in the event that the hook is used outside of a dialog
|
||||
isWithinDialog: boolean
|
||||
type: 'sheet' | 'alert'
|
||||
isHeightConstrained: boolean
|
||||
}
|
||||
|
||||
@@ -66,6 +67,12 @@ export type DialogOuterProps = {
|
||||
alignCenter?: boolean
|
||||
onBackgroundPress?: (e: GestureResponderEvent) => void
|
||||
}
|
||||
/**
|
||||
* The presentation style of the dialog.
|
||||
* - `sheet` (default): Bottom sheet on native, standard modal on web.
|
||||
* - `alert`: Centered alert modal on all platforms.
|
||||
*/
|
||||
type?: 'sheet' | 'alert'
|
||||
testID?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,53 @@
|
||||
import {useEffect} from 'react'
|
||||
import {useEffect, useRef} from 'react'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {useDialogStateControlContext} from '#/state/dialogs'
|
||||
import {type DialogControlProps} from '#/components/Dialog/types'
|
||||
|
||||
export function useDialogCallbackQueue(
|
||||
control: DialogControlProps,
|
||||
onClose?: () => void,
|
||||
) {
|
||||
const closeCallbacks = useRef<(() => void)[]>([])
|
||||
const {setDialogIsOpen, setFullyExpandedCount} =
|
||||
useDialogStateControlContext()
|
||||
|
||||
const callQueuedCallbacks = () => {
|
||||
for (const cb of closeCallbacks.current) {
|
||||
try {
|
||||
cb()
|
||||
} catch (e) {
|
||||
logger.error('Error running close callback', {safeMessage: e})
|
||||
}
|
||||
}
|
||||
closeCallbacks.current = []
|
||||
}
|
||||
|
||||
const enqueueCallback = (cb?: () => void) => {
|
||||
if (typeof cb === 'function') {
|
||||
closeCallbacks.current.push(cb)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpen = () => {
|
||||
callQueuedCallbacks()
|
||||
setDialogIsOpen(control.id, true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setDialogIsOpen(control.id, false)
|
||||
callQueuedCallbacks()
|
||||
onClose?.()
|
||||
}
|
||||
|
||||
return {
|
||||
enqueueCallback,
|
||||
handleOpen,
|
||||
handleClose,
|
||||
setFullyExpandedCount,
|
||||
}
|
||||
}
|
||||
|
||||
export function useAutoOpen(control: DialogControlProps, showTimeout?: number) {
|
||||
useEffect(() => {
|
||||
if (showTimeout) {
|
||||
|
||||
@@ -34,6 +34,7 @@ export function Outer({
|
||||
control,
|
||||
testID,
|
||||
nativeOptions,
|
||||
type = 'sheet',
|
||||
webOptions,
|
||||
onClose,
|
||||
}: React.PropsWithChildren<{
|
||||
@@ -43,6 +44,12 @@ export function Outer({
|
||||
* Native-specific options for the prompt. Extends `BottomSheetViewProps`
|
||||
*/
|
||||
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
||||
/**
|
||||
* The presentation style of the prompt.
|
||||
* - `sheet` (default): Bottom sheet on native, standard modal on web.
|
||||
* - `alert`: Centered alert modal on all platforms.
|
||||
*/
|
||||
type?: 'sheet' | 'alert'
|
||||
/**
|
||||
* Web-specific options for the prompt
|
||||
*/
|
||||
@@ -63,10 +70,11 @@ export function Outer({
|
||||
<Dialog.Outer
|
||||
control={control}
|
||||
testID={testID}
|
||||
type={type}
|
||||
onClose={onClose}
|
||||
webOptions={{alignCenter: true, ...webOptions}}
|
||||
nativeOptions={{preventExpansion: true, ...nativeOptions}}>
|
||||
<Dialog.Handle />
|
||||
{type !== 'alert' && <Dialog.Handle />}
|
||||
<Context.Provider value={context}>
|
||||
<Dialog.ScrollableInner
|
||||
accessibilityLabelledBy={titleId}
|
||||
@@ -79,11 +87,41 @@ export function Outer({
|
||||
)
|
||||
}
|
||||
|
||||
export function Icon({
|
||||
icon: Comp,
|
||||
color,
|
||||
}: {
|
||||
icon: React.ComponentType<SVGIconProps>
|
||||
color?: ButtonColor
|
||||
}) {
|
||||
const t = useTheme()
|
||||
|
||||
let iconColor: string
|
||||
switch (color) {
|
||||
case 'negative':
|
||||
iconColor = t.palette.negative_500
|
||||
break
|
||||
case 'primary':
|
||||
iconColor = t.palette.primary_500
|
||||
break
|
||||
default:
|
||||
iconColor = t.atoms.text.color
|
||||
break
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[a.pb_sm, a.align_center]}>
|
||||
<Comp size="xl" style={{color: iconColor}} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export function TitleText({
|
||||
children,
|
||||
style,
|
||||
}: React.PropsWithChildren<TextStyleProp>) {
|
||||
const {titleId} = useContext(Context)
|
||||
const {type} = Dialog.useDialogContext()
|
||||
return (
|
||||
<Text
|
||||
nativeID={titleId}
|
||||
@@ -93,6 +131,7 @@ export function TitleText({
|
||||
a.font_semi_bold,
|
||||
a.pb_xs,
|
||||
a.leading_snug,
|
||||
type === 'alert' && a.text_center,
|
||||
style,
|
||||
]}>
|
||||
{children}
|
||||
@@ -107,6 +146,7 @@ export function DescriptionText({
|
||||
}: React.PropsWithChildren<{selectable?: boolean} & TextStyleProp>) {
|
||||
const t = useTheme()
|
||||
const {descriptionId} = useContext(Context)
|
||||
const {type} = Dialog.useDialogContext()
|
||||
return (
|
||||
<Text
|
||||
nativeID={descriptionId}
|
||||
@@ -116,6 +156,7 @@ export function DescriptionText({
|
||||
a.leading_snug,
|
||||
t.atoms.text_contrast_high,
|
||||
a.pb_lg,
|
||||
type === 'alert' && a.text_center,
|
||||
style,
|
||||
]}>
|
||||
{children}
|
||||
@@ -227,6 +268,8 @@ export function Basic({
|
||||
onConfirm,
|
||||
confirmButtonColor,
|
||||
showCancel = true,
|
||||
type,
|
||||
icon,
|
||||
}: React.PropsWithChildren<{
|
||||
control: Dialog.DialogOuterProps['control']
|
||||
title: string
|
||||
@@ -243,10 +286,13 @@ export function Basic({
|
||||
onConfirm: (e: GestureResponderEvent) => void
|
||||
confirmButtonColor?: ButtonColor
|
||||
showCancel?: boolean
|
||||
type?: 'sheet' | 'alert'
|
||||
icon?: React.ComponentType<SVGIconProps>
|
||||
}>) {
|
||||
return (
|
||||
<Outer control={control} testID="confirmModal">
|
||||
<Outer control={control} testID="confirmModal" type={type}>
|
||||
<Content>
|
||||
{icon && <Icon icon={icon} color={confirmButtonColor} />}
|
||||
<TitleText>{title}</TitleText>
|
||||
{description && <DescriptionText>{description}</DescriptionText>}
|
||||
</Content>
|
||||
|
||||
@@ -5,6 +5,8 @@ import {useDialogStateControlContext} from '#/state/dialogs'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
||||
import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning'
|
||||
import * as Menu from '#/components/Menu'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {H3, P, Text} from '#/components/Typography'
|
||||
@@ -14,6 +16,8 @@ export function Dialogs() {
|
||||
const scrollable = Dialog.useDialogControl()
|
||||
const basic = Dialog.useDialogControl()
|
||||
const prompt = Prompt.usePromptControl()
|
||||
const alertPrompt = Prompt.usePromptControl()
|
||||
const alertPromptCustom = Prompt.usePromptControl()
|
||||
const withMenu = Dialog.useDialogControl()
|
||||
const testDialog = Dialog.useDialogControl()
|
||||
const {closeAllDialogs} = useDialogStateControlContext()
|
||||
@@ -111,6 +115,24 @@ export function Dialogs() {
|
||||
<ButtonText>Open prompt</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="solid"
|
||||
color="negative"
|
||||
size="small"
|
||||
onPress={() => alertPrompt.open()}
|
||||
label="Open alert prompt">
|
||||
<ButtonText>Open alert prompt (Basic)</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="solid"
|
||||
color="negative"
|
||||
size="small"
|
||||
onPress={() => alertPromptCustom.open()}
|
||||
label="Open alert prompt with custom content">
|
||||
<ButtonText>Open alert prompt (custom content)</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="solid"
|
||||
color="primary"
|
||||
@@ -175,6 +197,30 @@ export function Dialogs() {
|
||||
</Prompt.Actions>
|
||||
</Prompt.Outer>
|
||||
|
||||
<Prompt.Basic
|
||||
control={alertPrompt}
|
||||
type="alert"
|
||||
icon={Trash}
|
||||
title="Delete this post?"
|
||||
description="This action cannot be undone. The post will be permanently removed from your profile and from everyone's feeds."
|
||||
confirmButtonCta="Delete"
|
||||
confirmButtonColor="negative"
|
||||
onConfirm={() => {}}
|
||||
/>
|
||||
|
||||
<Prompt.Outer control={alertPromptCustom} type="alert">
|
||||
<Prompt.Icon icon={Warning} color="negative" />
|
||||
<Prompt.TitleText>Are you sure?</Prompt.TitleText>
|
||||
<Prompt.DescriptionText>
|
||||
This is the `alert` variant of the prompt. It renders a centered modal
|
||||
on all platforms and supports an optional icon above the title.
|
||||
</Prompt.DescriptionText>
|
||||
<Prompt.Actions>
|
||||
<Prompt.Action cta="Continue" color="negative" onPress={() => {}} />
|
||||
<Prompt.Cancel />
|
||||
</Prompt.Actions>
|
||||
</Prompt.Outer>
|
||||
|
||||
<Dialog.Outer control={basic}>
|
||||
<Dialog.Inner label="test">
|
||||
<H3 nativeID="dialog-title">Dialog</H3>
|
||||
|
||||
Reference in New Issue
Block a user