-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Modal): support custom triggers (#558)
## 📝 Changes - Add `<ModalContainer />` component to support custom triggers - This follows the [`DialogContainer`](https://react-spectrum.adobe.com/react-spectrum/DialogContainer.html) pattern from React Spectrum. - Added a "versions" table to the `Modal` spec but didn't update the spec itself with the new types. Still unsure whether specs should be snapshots or living ## ✅ Checklist - [x] Code is complete and in accordance with our style guide - [x] Unit tests are written and passing - [x] TSDoc is written or updated for any component API surface area - [x] Stories in Storybook accompany any relevant component changes - [x] Ensure no accessibility violations are reported in Storybook - [x] Changeset is added - [x] Specs and documentation are up-to-date - [x] Cross-browser check is performed (Chrome, Safari, Firefox)
- Loading branch information
1 parent
9089d64
commit ecb5e71
Showing
9 changed files
with
197 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@easypost/easy-ui": minor | ||
--- | ||
|
||
feat(Modal): support custom triggers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React, { ReactElement, cloneElement, useContext, useMemo } from "react"; | ||
import { useOverlayTrigger } from "react-aria"; | ||
import { useOverlayTriggerState } from "react-stately"; | ||
import { CloseableModalElement } from "./ModalTrigger"; | ||
import { ModalUnderlay } from "./ModalUnderlay"; | ||
import { ModalTriggerContext } from "./context"; | ||
|
||
type ModalContainerProps = { | ||
/** | ||
* Modal wrap content. | ||
*/ | ||
children: CloseableModalElement | ReactElement | null | undefined | false; | ||
|
||
/** | ||
* Whether or not the modal is dismissable. | ||
*/ | ||
isDismissable?: boolean; | ||
|
||
/** | ||
* Handler that is called when the overlay is closed. | ||
*/ | ||
onDismiss?: () => void; | ||
}; | ||
|
||
/** | ||
* Represents a container for `<Modal />`s. | ||
* | ||
* @remarks | ||
* A `<ModalContainer />` accepts a single Modal as a child, and manages | ||
* showing and hiding it in a modal. Useful in cases where there is no trigger | ||
* element or when the trigger unmounts while the modal is open. | ||
*/ | ||
export function ModalContainer(props: ModalContainerProps) { | ||
const { children, isDismissable = true, onDismiss = () => {} } = props; | ||
|
||
const existingModalTriggerContext = useContext(ModalTriggerContext); | ||
if (existingModalTriggerContext) { | ||
throw new Error("Modal.Container must be used outside of a Modal.Trigger"); | ||
} | ||
|
||
const state = useOverlayTriggerState({ | ||
isOpen: Boolean(children), | ||
onOpenChange: (isOpen) => { | ||
if (!isOpen) { | ||
onDismiss(); | ||
} | ||
}, | ||
}); | ||
const { overlayProps } = useOverlayTrigger({ type: "dialog" }, state); | ||
|
||
const context = useMemo(() => { | ||
return { state, isDismissable }; | ||
}, [state, isDismissable]); | ||
|
||
return ( | ||
<ModalTriggerContext.Provider value={context}> | ||
{state.isOpen && ( | ||
<ModalUnderlay state={state} isDismissable={isDismissable}> | ||
{children | ||
? typeof children === "function" | ||
? children(state.close) | ||
: cloneElement(children, overlayProps) | ||
: null} | ||
</ModalUnderlay> | ||
)} | ||
</ModalTriggerContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters