diff --git a/packages/ui-react/lib/Sheet/Sheet.mdx b/packages/ui-react/lib/Sheet/Sheet.mdx index b2b6e7d..ff3f20f 100644 --- a/packages/ui-react/lib/Sheet/Sheet.mdx +++ b/packages/ui-react/lib/Sheet/Sheet.mdx @@ -19,8 +19,7 @@ export const ShowSheet = () => { onCancel={() => setVisible(false)} /> - -); + ); }; diff --git a/packages/ui-react/lib/Sheet/Sheet.module.scss b/packages/ui-react/lib/Sheet/Sheet.module.scss index 66e5069..6d11a1a 100644 --- a/packages/ui-react/lib/Sheet/Sheet.module.scss +++ b/packages/ui-react/lib/Sheet/Sheet.module.scss @@ -9,71 +9,96 @@ $padding-left-right-distance: 20px; animation-fill-mode: forwards; } -.base { +@property --blur { + syntax: ''; + inherits: false; + initial-value: 0px; +} + +@property --opacity-background { + syntax: ''; + inherits: false; + initial-value: 0%; +} + +@property --opacity-sheet { + syntax: ''; + inherits: false; + initial-value: 0%; +} + +@property --slide { + syntax: ''; + inherits: false; + initial-value: 0%; +} + +@mixin sheet-animation() { + &.sheet-in { + @include animation(sheet-in); + } + &.sheet-hide { + @include animation(sheet-hide); + } +} + +.sheet-container { height: 100vh; width: 100vw; position: fixed; left: 0; top: 0; - z-index: 2; + z-index: 1; box-sizing: border-box; - background-color: $background-shadow-color; - &.showAnimation { - @include animation(showShadow); - } - &.hideAnimation { - @include animation(hideShadow); + &.mask { + backdrop-filter: blur(var(--blur)); + background-color: rgb($black-color, var(--opacity-background)); } - .sheetContent { + @include sheet-animation(); + .sheet { top: 0; height: 100vh; - background-color: var(--white-color); + background-color: $white-color; position: absolute; - z-index: 3; + z-index: 2; box-sizing: border-box; - opacity: 1; right: 0; padding: $padding-left-right-distance; - opacity: 1; - &.showAnimation { - @include animation(showSlideSheet); - } - &.hideAnimation { - @include animation(hideSlideSheet); + transform: translateX(var(--slide)); + opacity: var(--opacity-sheet); + @include sheet-animation(); + display: flex; + flex-direction: column; + &.left { + left: 0; + transform: translateX(calc(-1 * var(--slide))); } .sheetMainContent { - padding: 10px 0; overflow-y: scroll; display: flex; - position: relative; - height: calc(100vh - 32px - 60px); top: 30px; + flex-grow: 1; + margin-top: 10px; } .sheetFooter { height: 50px; - position: absolute; - bottom: 20px; - width: -webkit-fill-available; - padding-right: $padding-left-right-distance; text-align: end; - background-color: var(--white-color); + background-color: $white-color; + z-index: 1; } .sheet-header { height: 32px; - background-color: var(--white-color); - position: absolute; - display: flex; - width: -webkit-fill-available; - padding-right: 20px; - flex-direction: column; + background-color: $white-color; + width: 100%; .sheet-header-content { display: flex; width: 100%; align-items: center; justify-content: space-between; + flex-direction: row; span { font-size: 16px; - font-weight: 700; + font-weight: bolder; white-space: nowrap; } .svg-container { @@ -109,39 +134,32 @@ $padding-left-right-distance: 20px; } } } - -@keyframes showShadow { - from { - background-color: rgb(var(--black-color-rgb), 0); - } - to { - background-color: $background-shadow-color; - } -} - -@keyframes hideShadow { - from { - background-color: $background-shadow-color; +@keyframes sheet-in { + 0% { + --blur: 0px; + --opacity-background: 0%; + --slide: 100%; + --opacity-sheet: 0%; } - to { - background-color: rgb(var(--black-color-rgb), 0); + 100% { + --blur: 4px; + --opacity-background: 40%; + --slide: 0%; + --opacity-sheet: 100%; } } -@keyframes showSlideSheet { - from { - right: -30%; - } - to { - right: 0; - } -} - -@keyframes hideSlideSheet { - from { - right: 0; +@keyframes sheet-hide { + 0% { + --blur: 4px; + --opacity-background: 40%; + --slide: 0%; + --opacity-sheet: 100%; } - to { - right: -30%; + 100% { + --blur: 0px; + --opacity-background: 0%; + --slide: 100%; + --opacity-sheet: 0%; } } diff --git a/packages/ui-react/lib/Sheet/Sheet.tsx b/packages/ui-react/lib/Sheet/Sheet.tsx index dea8663..4e97d80 100644 --- a/packages/ui-react/lib/Sheet/Sheet.tsx +++ b/packages/ui-react/lib/Sheet/Sheet.tsx @@ -1,10 +1,10 @@ -import classnames from 'classnames'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, type CSSProperties } from 'react'; import styles from './Sheet.module.scss'; // import SheetTrigger from './SheetTrigger'; import { SheetHeader } from './SheetHeader'; import { SheetFooter } from './SheetFooter'; import { useWrapperVisibleStore } from './useWrapperVisibleStore'; +import { createPortal } from 'react-dom'; export interface SheetProps extends React.HtmlHTMLAttributes { /** @@ -31,70 +31,105 @@ export interface SheetProps extends React.HtmlHTMLAttributes { * width, the width of the sheet */ width?: number; + /** + * classname , the classname of the sidesheet + */ + className?: string; + /** + * mask, Whether to display the mask + */ + mask?: boolean; + /** + * Whether or not to allow closing the dialog by clicking on the mask + */ + maskClosable?: boolean; + /** + * the style of the mask + */ + maskStyle?: CSSProperties; + /** + * placement : left|right + */ + placement?: 'left' | 'right'; } export const Sheet = React.forwardRef( - ({ visible, onCancel, sheetTitle, sheetFooter, mainContent, width = 500, ...rest }, ref) => { - const [innerVisible, setInnerVisible] = useState(false); - const [isShowAnimation, setIsShowAnimation] = useState(false); - const [isHideAnimation, setIsHideAnimation] = useState(false); + ( + { + visible, + onCancel, + sheetTitle, + sheetFooter, + mainContent, + width = 500, + className, + maskClosable = true, + mask = true, + maskStyle, + placement = 'right', + ...rest + }, + ref, + ) => { + const [sheetVisible, setSheetVisible] = useState(false); + const [sheetIn, setSheetIn] = useState(false); + const [sheetHide, setSheetHide] = useState(false); const [open, close] = useWrapperVisibleStore((state) => [state.open, state.close]); - const stopPropagation = (e: React.MouseEvent) => { - e.stopPropagation(); - }; - useEffect(() => { - if (visible) { - setInnerVisible(true); - setIsShowAnimation(true); - open(); - document.body.style.overflow = 'hidden'; - setTimeout(() => { - setIsShowAnimation(false); - }, 400); - } - if (!visible) { - setIsHideAnimation(true); - close(); - setTimeout(() => { - setIsHideAnimation(false); - setInnerVisible(false); - document.body.style.overflow = ''; - }, 400); - } - }, [visible, open, close]); + visible ? openSheet() : closeSheet(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [visible]); - const sheetClass = classnames( - `${styles['base']} - ${styles[isShowAnimation ? 'showAnimation' : '']} - ${styles[isHideAnimation ? 'hideAnimation' : '']}`, - ); + const closeSheet = () => { + setSheetIn(false); + setSheetHide(true); + close(); + setTimeout(() => { + setSheetHide(false); + setSheetVisible(false); + document.body.style.overflow = ''; + }, 400); + }; + + const openSheet = () => { + setSheetVisible(true); + setSheetIn(true); + open(); + document.body.style.overflow = 'hidden'; + }; return ( <> - {innerVisible && ( -
-
- -
{mainContent}
- {sheetFooter} -
-
+ {createPortal( +
+ {sheetVisible && ( +
maskClosable && onCancel && onCancel()} + ref={ref} + {...rest} + > +
e.stopPropagation()} + > + +
{mainContent}
+ {sheetFooter} +
+
+ )} +
, + document.body, )} ); diff --git a/packages/ui-react/lib/Sheet/SheetFooter.tsx b/packages/ui-react/lib/Sheet/SheetFooter.tsx index 572d5f4..e07fcad 100644 --- a/packages/ui-react/lib/Sheet/SheetFooter.tsx +++ b/packages/ui-react/lib/Sheet/SheetFooter.tsx @@ -7,10 +7,14 @@ export interface SheetFooterProps { * content of the sheetheader */ children?: React.ReactNode; + /** + * onCancel, the exit of the sheet + */ + onCancel?: () => void; } export const SheetFooter = React.forwardRef( - ({ children, ...rest }, ref) => { + ({ children, onCancel, ...rest }, ref) => { return ( <>
( className={styles['sheetFooter']} >
( marginBottom: '8px', }} >
- {children || } + {children || ( + + )}
); diff --git a/packages/ui-react/lib/Sheet/SheetWrapper.tsx b/packages/ui-react/lib/Sheet/SheetWrapper.tsx index 138cf12..0860976 100644 --- a/packages/ui-react/lib/Sheet/SheetWrapper.tsx +++ b/packages/ui-react/lib/Sheet/SheetWrapper.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { useWrapperVisibleStore } from './useWrapperVisibleStore'; import styles from './Sheet.module.scss'; +import { createPortal } from 'react-dom'; export interface SheetWrapperProps { /** @@ -19,14 +20,17 @@ export const SheetWrapper = React.forwardRef( return ( <> -
-
- {children} -
-
+ {createPortal( +
+
+ {children} +
+
, + document.body, + )} ); }, diff --git a/packages/ui-react/lib/Sheet/index.ts b/packages/ui-react/lib/Sheet/index.ts index c0c1863..b19dfa4 100644 --- a/packages/ui-react/lib/Sheet/index.ts +++ b/packages/ui-react/lib/Sheet/index.ts @@ -1,2 +1,5 @@ export * from './Sheet'; +// The wrapper is under development, +// please use it with caution, +// there will be a lot of bugs. export * from './SheetWrapper';