Skip to content

Commit

Permalink
[Dialog, AlertDialog] Fix trigger issues (#808)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak authored Nov 8, 2024
1 parent f5b07ee commit a43de8f
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 286 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"componentDescription": "",
"componentDescription": "Renders a trigger element that opens the Dialog.",
"propDescriptions": {
"className": {
"description": "Class names applied to the element or a function that returns them based on the component's state."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,12 @@ const AlertDialogBackdrop = React.forwardRef(function AlertDialogBackdrop(
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const { render, className, keepMounted = false, ...other } = props;
const { open, hasParentDialog, setBackdropPresent, animated } = useAlertDialogRootContext();

const handleMount = React.useCallback(() => setBackdropPresent(true), [setBackdropPresent]);
const handleUnmount = React.useCallback(() => setBackdropPresent(false), [setBackdropPresent]);
const { open, hasParentDialog, animated } = useAlertDialogRootContext();

const { getRootProps, mounted, transitionStatus } = useDialogBackdrop({
animated,
open,
ref: forwardedRef,
onMount: handleMount,
onUnmount: handleUnmount,
});

const ownerState: AlertDialogBackdrop.OwnerState = { open, transitionStatus };
Expand Down
43 changes: 31 additions & 12 deletions packages/mui-base/src/AlertDialog/Popup/AlertDialogPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,40 @@ const AlertDialogPopup = React.forwardRef(function AlertDialogPopup(
) {
const { className, container, id, keepMounted = false, render, initialFocus, ...other } = props;

const rootContext = useAlertDialogRootContext();
const { open, nestedOpenDialogCount } = rootContext;
const {
descriptionElementId,
floatingRootContext,
getPopupProps,
mounted,
nestedOpenDialogCount,
onOpenChange,
open,
openMethod,
popupRef,
setPopupElement,
setPopupElementId,
titleElementId,
transitionStatus,
} = useAlertDialogRootContext();

const popupRef = React.useRef<HTMLElement | null>(null);
const mergedRef = useForkRef(forwardedRef, popupRef);

const { getRootProps, floatingContext, mounted, transitionStatus, resolvedInitialFocus } =
useDialogPopup({
id,
ref: mergedRef,
isTopmost: nestedOpenDialogCount === 0,
dismissible: false,
initialFocus,
...rootContext,
});
const { getRootProps, floatingContext, resolvedInitialFocus } = useDialogPopup({
descriptionElementId,
floatingRootContext,
getPopupProps,
id,
initialFocus,
modal: true,
mounted,
onOpenChange,
open,
openMethod,
ref: mergedRef,
setPopupElement,
setPopupElementId,
titleElementId,
});

const ownerState: AlertDialogPopup.OwnerState = React.useMemo(
() => ({
Expand Down
13 changes: 7 additions & 6 deletions packages/mui-base/src/AlertDialog/Root/AlertDialogRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@ import { useDialogRoot } from '../../Dialog/Root/useDialogRoot';
* - [AlertDialogRoot API](https://base-ui.netlify.app/components/react-alert-dialog/#api-reference-AlertDialogRoot)
*/
const AlertDialogRoot: React.FC<AlertDialogRoot.Props> = function AlertDialogRoot(props) {
const { children, defaultOpen, onOpenChange, open: openProp, animated = true } = props;
const { animated = true, children, defaultOpen, onOpenChange, open } = props;

const dialogRootContext = React.useContext(AlertDialogRootContext);
const parentDialogRootContext = React.useContext(AlertDialogRootContext);

const dialogRoot = useDialogRoot({
open: openProp,
open,
defaultOpen,
onOpenChange,
modal: true,
onNestedDialogClose: dialogRootContext?.onNestedDialogClose,
onNestedDialogOpen: dialogRootContext?.onNestedDialogOpen,
dismissible: false,
onNestedDialogClose: parentDialogRootContext?.onNestedDialogClose,
onNestedDialogOpen: parentDialogRootContext?.onNestedDialogOpen,
});

const hasParentDialog = Boolean(dialogRootContext);
const hasParentDialog = Boolean(parentDialogRootContext);

const contextValue = React.useMemo(
() => ({ ...dialogRoot, hasParentDialog, animated }),
Expand Down
20 changes: 9 additions & 11 deletions packages/mui-base/src/AlertDialog/Trigger/AlertDialogTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import { useDialogTrigger } from '../../Dialog/Trigger/useDialogTrigger';
import { useAlertDialogRootContext } from '../Root/AlertDialogRootContext';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useForkRef } from '../../utils/useForkRef';
import type { BaseUIComponentProps } from '../../utils/types';
import { triggerOpenStateMapping } from '../../utils/popupOpenStateMapping';

Expand All @@ -22,25 +22,23 @@ const AlertDialogTrigger = React.forwardRef(function AlertDialogTrigger(
forwardedRef: React.ForwardedRef<HTMLButtonElement>,
) {
const { render, className, ...other } = props;
const { open, onOpenChange, onTriggerClick, popupElementId } = useAlertDialogRootContext();
const { open, setTriggerElement, getTriggerProps, modal } = useAlertDialogRootContext();

const { getRootProps } = useDialogTrigger({
open,
onOpenChange,
onTriggerClick,
popupElementId,
});
const ownerState: AlertDialogTrigger.OwnerState = React.useMemo(
() => ({ open, modal }),
[open, modal],
);

const ownerState: AlertDialogTrigger.OwnerState = { open };
const mergedRef = useForkRef(forwardedRef, setTriggerElement);

const { renderElement } = useComponentRenderer({
render: render ?? 'button',
className,
ownerState,
propGetter: getRootProps,
propGetter: getTriggerProps,
extraProps: other,
customStyleHookMapping: triggerOpenStateMapping,
ref: forwardedRef,
ref: mergedRef,
});

return renderElement();
Expand Down
7 changes: 1 addition & 6 deletions packages/mui-base/src/Dialog/Backdrop/DialogBackdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,12 @@ const DialogBackdrop = React.forwardRef(function DialogBackdrop(
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const { render, className, keepMounted = false, ...other } = props;
const { open, modal, hasParentDialog, setBackdropPresent, animated } = useDialogRootContext();

const handleMount = React.useCallback(() => setBackdropPresent(true), [setBackdropPresent]);
const handleUnmount = React.useCallback(() => setBackdropPresent(false), [setBackdropPresent]);
const { open, modal, hasParentDialog, animated } = useDialogRootContext();

const { getRootProps, mounted, transitionStatus } = useDialogBackdrop({
animated,
open,
ref: forwardedRef,
onMount: handleMount,
onUnmount: handleUnmount,
});

const ownerState: DialogBackdrop.OwnerState = React.useMemo(
Expand Down
21 changes: 1 addition & 20 deletions packages/mui-base/src/Dialog/Backdrop/useDialogBackdrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ import * as React from 'react';
import { mergeReactProps } from '../../utils/mergeReactProps';
import { useAnimatedElement } from '../../utils/useAnimatedElement';
import { useForkRef } from '../../utils/useForkRef';
import { useEventCallback } from '../../utils/useEventCallback';
import { useEnhancedEffect } from '../../utils/useEnhancedEffect';
import { type TransitionStatus } from '../../utils/useTransitionStatus';

export function useDialogBackdrop(
params: useDialogBackdrop.Parameters,
): useDialogBackdrop.ReturnValue {
const { animated, open, ref, onMount: onMountParam, onUnmount: onUnmountParam } = params;
const { animated, open, ref } = params;

const backdropRef = React.useRef<HTMLElement | null>(null);
const handleRef = useForkRef(ref, backdropRef);
Expand All @@ -21,15 +19,6 @@ export function useDialogBackdrop(
enabled: animated,
});

const onMount = useEventCallback(onMountParam);
const onUnmount = useEventCallback(onUnmountParam);

useEnhancedEffect(() => {
onMount();

return onUnmount;
}, [onMount, onUnmount]);

const getRootProps = React.useCallback(
(externalProps: React.ComponentPropsWithRef<any>) =>
mergeReactProps(externalProps, {
Expand Down Expand Up @@ -61,14 +50,6 @@ export namespace useDialogBackdrop {
* The ref to the background element.
*/
ref: React.Ref<HTMLElement>;
/**
* Callback to invoke when the backdrop is mounted.
*/
onMount: () => void;
/**
* Callback to invoke when the backdrop is unmounted.
*/
onUnmount: () => void;
}

export interface ReturnValue {
Expand Down
44 changes: 33 additions & 11 deletions packages/mui-base/src/Dialog/Popup/DialogPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,42 @@ const DialogPopup = React.forwardRef(function DialogPopup(
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const { className, container, id, keepMounted = false, render, initialFocus, ...other } = props;
const rootContext = useDialogRootContext();
const { open, modal, nestedOpenDialogCount, dismissible } = rootContext;
const {
descriptionElementId,
dismissible,
floatingRootContext,
getPopupProps,
modal,
mounted,
nestedOpenDialogCount,
onOpenChange,
open,
openMethod,
popupRef,
setPopupElement,
setPopupElementId,
titleElementId,
transitionStatus,
} = useDialogRootContext();

const popupRef = React.useRef<HTMLElement | null>(null);
const mergedRef = useForkRef(forwardedRef, popupRef);

const { getRootProps, floatingContext, mounted, transitionStatus, resolvedInitialFocus } =
useDialogPopup({
id,
ref: mergedRef,
isTopmost: nestedOpenDialogCount === 0,
initialFocus,
...rootContext,
});
const { getRootProps, floatingContext, resolvedInitialFocus } = useDialogPopup({
descriptionElementId,
floatingRootContext,
getPopupProps,
id,
initialFocus,
modal,
mounted,
onOpenChange,
open,
openMethod,
ref: mergedRef,
setPopupElement,
setPopupElementId,
titleElementId,
});

const ownerState: DialogPopup.OwnerState = {
open,
Expand Down
Loading

0 comments on commit a43de8f

Please sign in to comment.