feat(component): mobile menu support (#7892)

This commit is contained in:
Cats Juice
2024-08-21 17:05:05 +08:00
committed by GitHub
parent 182b2fd62d
commit 23b0db36b9
57 changed files with 988 additions and 1482 deletions
@@ -9,9 +9,10 @@ import * as Dialog from '@radix-ui/react-dialog';
import * as VisuallyHidden from '@radix-ui/react-visually-hidden';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import type { CSSProperties } from 'react';
import type { CSSProperties, MouseEvent } from 'react';
import { forwardRef, useCallback, useEffect, useState } from 'react';
import { isMobile } from '../../utils/env';
import type { IconButtonProps } from '../button';
import { IconButton } from '../button';
import * as styles from './styles.css';
@@ -32,6 +33,12 @@ export interface ModalProps extends DialogProps {
contentOptions?: DialogContentProps;
overlayOptions?: DialogOverlayProps;
closeButtonOptions?: IconButtonProps;
contentWrapperClassName?: string;
contentWrapperStyle?: CSSProperties;
/**
* @default 'fadeScaleTop'
*/
animation?: 'fadeScaleTop' | 'none' | 'slideBottom';
}
type PointerDownOutsideEvent = Parameters<
Exclude<DialogContentProps['onPointerDownOutside'], undefined>
@@ -128,10 +135,14 @@ export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
overlayOptions: {
className: overlayClassName,
style: overlayStyle,
onClick: onOverlayClick,
...otherOverlayOptions
} = {},
closeButtonOptions,
children,
contentWrapperClassName,
contentWrapperStyle,
animation = 'fadeScaleTop',
...otherProps
} = props;
const { className: closeButtonClassName, ...otherCloseButtonProps } =
@@ -167,6 +178,18 @@ export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
[onEscapeKeyDown, persistent]
);
const handleOverlayClick = useCallback(
(e: MouseEvent<HTMLDivElement>) => {
onOverlayClick?.(e);
if (persistent) {
e.preventDefault();
} else {
onOpenChange?.(false);
}
},
[onOpenChange, onOverlayClick, persistent]
);
if (!container) {
return;
}
@@ -180,13 +203,27 @@ export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
>
<Dialog.Portal container={container} {...portalOptions}>
<Dialog.Overlay
className={clsx(styles.modalOverlay, overlayClassName)}
className={clsx(
`anim-${animation}`,
styles.modalOverlay,
overlayClassName,
{ mobile: isMobile() }
)}
style={{
...overlayStyle,
}}
onClick={handleOverlayClick}
{...otherOverlayOptions}
/>
<div data-modal={modal} className={clsx(styles.modalContentWrapper)}>
<div
data-modal={modal}
className={clsx(
`anim-${animation}`,
styles.modalContentWrapper,
contentWrapperClassName
)}
style={contentWrapperStyle}
>
<Dialog.Content
onPointerDownOutside={handlePointerDownOutSide}
onEscapeKeyDown={handleEscapeKeyDown}