diff --git a/packages/core/src/hooks/__tests__/UseMultiOnClickOutside.test.ts b/packages/core/src/hooks/__tests__/UseMultiOnClickOutside.test.ts index 36bc12886..b7cb48ab2 100644 --- a/packages/core/src/hooks/__tests__/UseMultiOnClickOutside.test.ts +++ b/packages/core/src/hooks/__tests__/UseMultiOnClickOutside.test.ts @@ -3,7 +3,7 @@ import { useRef } from "react"; import { useMultiOnClickOutside } from "../UseMultiOnClickOutside"; import { vi } from "vitest"; -describe("useOnClickOutside", () => { +describe("useMultiOnClickOutside", () => { const options = { altKey: true, bubbles: true, diff --git a/packages/modal/src/dialog/UseDialog.tsx b/packages/modal/src/dialog/UseDialog.tsx index 9a5b4ac07..bfd13bdcb 100644 --- a/packages/modal/src/dialog/UseDialog.tsx +++ b/packages/modal/src/dialog/UseDialog.tsx @@ -1,6 +1,7 @@ import cx from "classnames"; import React, { CSSProperties, + MouseEventHandler, ReactNode, RefObject, useCallback, @@ -75,6 +76,7 @@ export function useDialog( const resolve = useCallback>( (value) => { + // Trigger closing animation. setClosing(true); currentRef.current?.addEventListener( "animationend", @@ -92,8 +94,18 @@ export function useDialog( [currentRef, options] ); + const onClose = useCallback(() => { + // Remove content immediately, since it cannot be animated when closed by browser. + setClosing(false); + setContentVisible(false); + rejectRef.current?.(); + options.onReject?.(); + modalComponentProps.current = undefined; + }, [options]); + const reject = useCallback( (error) => { + // Trigger closing animation. setClosing(true); currentRef.current?.addEventListener( "animationend", @@ -111,53 +123,62 @@ export function useDialog( [currentRef, options] ); + const onClick = useCallback>( + (e) => { + if (e.target !== currentRef.current) { + return; + } + + const rect = currentRef.current.getBoundingClientRect(); + + const clickedInsideDialog = + rect.top <= e.clientY && + e.clientY <= rect.top + rect.height && + rect.left <= e.clientX && + e.clientX <= rect.left + rect.width; + + if (!clickedInsideDialog) { + reject(); + } + }, + [currentRef, reject] + ); + const dialogElement = useMemo( () => ( - - reject() - } - ref={currentRef} - className={cx(options.className, closing && options.closingClassName)} - style={options.dialogStyle} + +
- {options.disableCloseOnClickOutside ? ( - <> - {contentVisible && ( - - )} - - ) : ( -
ev.stopPropagation() - } - > - {contentVisible && ( - - )} -
+ {contentVisible && ( + + + )} -
-
+ + ), [ - resolve, - reject, options.disableCloseOnClickOutside, options.className, options.closingClassName, options.dialogStyle, options.contentWrapperStyle, options.contentWrapperClassName, + onClick, + onClose, currentRef, closing, contentVisible, + resolve, + reject, Comp, key, ] diff --git a/packages/modal/src/dialog/modal/ModalDialog.module.css b/packages/modal/src/dialog/modal/ModalDialog.module.css index 978533e0e..034e3a383 100644 --- a/packages/modal/src/dialog/modal/ModalDialog.module.css +++ b/packages/modal/src/dialog/modal/ModalDialog.module.css @@ -10,6 +10,17 @@ @media (min-width: 769px) { border-radius: var(--swui-border-radius-large); + + &::-webkit-scrollbar-thumb { + background-color: var(--lhds-color-ui-400); + border: 4px solid transparent; + border-radius: 8px; + background-clip: padding-box; + } + + &::-webkit-scrollbar { + width: 16px; + } } &:not([open]) {