fix(mobile): disable navigation gesture for swipe-dialog (#8993)

This commit is contained in:
CatsJuice
2024-12-12 06:55:15 +00:00
parent 01b6e43c1f
commit 84df2a1d16
6 changed files with 71 additions and 50 deletions

View File

@@ -17,6 +17,7 @@ export interface NavigationBackButtonProps extends IconButtonProps {
* A button to control the back behavior of the mobile app, as well as manage navigation gesture
*/
export const NavigationBackButton = ({
icon,
backAction,
style: propsStyle,
...otherProps
@@ -46,7 +47,7 @@ export const NavigationBackButton = ({
size={24}
style={style}
onClick={handleRouteBack}
icon={isInsideModal ? <CloseIcon /> : <ArrowLeftSmallIcon />}
icon={icon ?? (isInsideModal ? <CloseIcon /> : <ArrowLeftSmallIcon />)}
data-testid="page-header-back"
{...otherProps}
/>

View File

@@ -1,6 +1,7 @@
import { SafeArea } from '@affine/component';
import clsx from 'clsx';
import { forwardRef, type HtmlHTMLAttributes, type ReactNode } from 'react';
import type { HtmlHTMLAttributes, ReactElement, ReactNode } from 'react';
import { forwardRef } from 'react';
import { NavigationBackButton } from '../navigation-back';
import * as styles from './styles.css';
@@ -11,6 +12,7 @@ export interface PageHeaderProps
* whether to show back button
*/
back?: boolean;
backIcon?: ReactElement;
/**
* Override back button action
*/
@@ -51,6 +53,7 @@ export const PageHeader = forwardRef<HTMLDivElement, PageHeaderProps>(
function PageHeader(
{
back,
backIcon,
backAction,
prefix,
suffix,
@@ -82,7 +85,9 @@ export const PageHeader = forwardRef<HTMLDivElement, PageHeaderProps>(
className={clsx(styles.prefix, prefixClassName)}
style={prefixStyle}
>
{back ? <NavigationBackButton backAction={backAction} /> : null}
{back ? (
<NavigationBackButton icon={backIcon} backAction={backAction} />
) : null}
{prefix}
</section>

View File

@@ -1,5 +1,10 @@
import { Scrollable } from '@affine/component';
import {
InsideModalContext,
ModalConfigContext,
Scrollable,
} from '@affine/component';
import { PageHeader } from '@affine/core/mobile/components';
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import anime from 'animejs';
import {
@@ -146,6 +151,8 @@ export const SwipeDialog = ({
triggerSize = 10,
onOpenChange,
}: SwipeDialogProps) => {
const insideModal = useContext(InsideModalContext);
const { onOpen: globalOnOpen } = useContext(ModalConfigContext);
const swiperTriggerRef = useRef<HTMLDivElement>(null);
const overlayRef = useRef<HTMLDivElement>(null);
const dialogRef = useRef<HTMLDivElement>(null);
@@ -202,39 +209,47 @@ export const SwipeDialog = ({
}
}, [open, prev]);
useEffect(() => {
if (open) return globalOnOpen?.();
return;
}, [globalOnOpen, open]);
if (!open) return null;
return (
<SwipeDialogContext.Provider value={{ stack: [...stack, dialogRef] }}>
{createPortal(
<div className={styles.root}>
<div className={styles.overlay} ref={overlayRef} />
<div role="dialog" className={styles.dialog} ref={dialogRef}>
<div className={styles.content}>
<PageHeader
back
backAction={animateClose}
className={styles.header}
>
<span className={styles.dialogTitle}>{title}</span>
</PageHeader>
<InsideModalContext.Provider value={insideModal + 1}>
{createPortal(
<div className={styles.root}>
<div className={styles.overlay} ref={overlayRef} />
<div role="dialog" className={styles.dialog} ref={dialogRef}>
<div className={styles.content}>
<PageHeader
back
backIcon={<ArrowLeftSmallIcon />}
backAction={animateClose}
className={styles.header}
>
<span className={styles.dialogTitle}>{title}</span>
</PageHeader>
<Scrollable.Root className={styles.scrollArea}>
<Scrollable.Viewport>{children}</Scrollable.Viewport>
<Scrollable.Scrollbar orientation="vertical" />
</Scrollable.Root>
<Scrollable.Root className={styles.scrollArea}>
<Scrollable.Viewport>{children}</Scrollable.Viewport>
<Scrollable.Scrollbar orientation="vertical" />
</Scrollable.Root>
</div>
<div
ref={swiperTriggerRef}
className={styles.swipeBackTrigger}
style={assignInlineVars({
[styles.triggerSizeVar]: `${triggerSize}px`,
})}
/>
</div>
<div
ref={swiperTriggerRef}
className={styles.swipeBackTrigger}
style={assignInlineVars({
[styles.triggerSizeVar]: `${triggerSize}px`,
})}
/>
</div>
</div>,
document.body
)}
</div>,
document.body
)}
</InsideModalContext.Provider>
</SwipeDialogContext.Provider>
);
};