Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update portal and add nesting opt out #3210

Merged
merged 10 commits into from
Jan 30, 2021
24 changes: 24 additions & 0 deletions .changeset/chatty-students-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"@chakra-ui/modal": minor
"@chakra-ui/tooltip": minor
---

Add support for forwarding props to the underlying `Portal` component. Pass the
`portalProps` prop to achive this.

The 2 props you can pass to the portalProps are:

- `containerRef`: `ref` for the element where to mount the portal
- `appendToParentPortal`: If `false`, it'll opt out of portal nesting

```jsx
<Modal portalProps={{ containerRef: ref }}>
<ModalOverlay />
<ModalContent>
<Box>Modal content</Box>
<Tooltip portalProps={{ appendToParentPortal: false }}>
Some tooltip
</Tooltip>
</ModalContent>
</Modal>
```
10 changes: 8 additions & 2 deletions .changeset/hungry-donkeys-unite.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@
"@chakra-ui/menu": minor
---

The `MenuItem` now accepts a `commandSpacing` prop that can be used to adjust
the space between the command and label.
- The `MenuItem` now accepts a `commandSpacing` prop that can be used to adjust
the space between the command and label.

- Add support `rootProps` to `MenuList` so it's possible override the styles for
root container for menu list. Common use case is to change the applied
`zIndex` of the menulist.

- Make it possible to override `zIndex` by passing props to `MenuList`
20 changes: 20 additions & 0 deletions .changeset/violet-hotels-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@chakra-ui/portal": minor
---

- Add support for changing the container that portal is appended to. You can now
pass `containerRef` to portal.
- Update portal `README.md` and tests.
- Add support for `appendToParentPortal={false}` to opt out of nested portals.
- Fix issue with portal `zIndex` container where it renders elements outside of
view.
- Renamed `getContainer` prop to `containerRef` to make it possible to pass the
`ref` directly. This affects the `Modal` component primarily

```jsx live=false
// Before
<Portal getContainer={() => ref.current}>{/** Content */}</Portal>

// After
<Portal containerRef={ref}>{/** Content */}</Portal>
```
1 change: 1 addition & 0 deletions .changeset/wild-pandas-suffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
- Correct capitalization of `rightIcon` prop
- Add `LinkOverlay` docs
- Restructure component groupings and add permanent redirects
- Add docs for `Portal` component
76 changes: 0 additions & 76 deletions packages/menu/migration.md

This file was deleted.

27 changes: 14 additions & 13 deletions packages/menu/src/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,17 @@ export const MenuButton = forwardRef<MenuButtonProps, "button">(

const buttonProps = useMenuButton(rest, ref)

const ButtonComp = As || StyledMenuButton
const Element = As || StyledMenuButton

return (
<ButtonComp
<Element
{...buttonProps}
className={cx("chakra-menu__menu-button", props.className)}
>
<chakra.span
__css={{
pointerEvents: "none",
flex: "1 1 auto",
}}
>
<chakra.span __css={{ pointerEvents: "none", flex: "1 1 auto" }}>
{props.children}
</chakra.span>
</ButtonComp>
</Element>
)
},
)
Expand All @@ -119,7 +114,9 @@ if (__DEV__) {
MenuButton.displayName = "MenuButton"
}

export interface MenuListProps extends HTMLChakraProps<"div"> {}
export interface MenuListProps extends HTMLChakraProps<"div"> {
rootProps?: HTMLChakraProps<"div">
}

const motionVariants: Variants = {
enter: {
Expand Down Expand Up @@ -147,15 +144,19 @@ const motionVariants: Variants = {
const Motion = chakra(motion.div)

export const MenuList = forwardRef<MenuListProps, "div">((props, ref) => {
const { rootProps, ...rest } = props
const { isOpen, onTransitionEnd } = useMenuContext()

const listProps = useMenuList(props, ref)
const positionerProps = useMenuPositioner()
const listProps = useMenuList(rest, ref)
const positionerProps = useMenuPositioner(rootProps)

const styles = useStyles()

return (
<chakra.div {...positionerProps} __css={{ zIndex: styles.list?.zIndex }}>
<chakra.div
{...positionerProps}
__css={{ zIndex: props.zIndex ?? styles.list?.zIndex }}
>
<Motion
{...listProps}
/**
Expand Down
11 changes: 4 additions & 7 deletions packages/modal/src/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,9 @@ export interface ModalProps extends UseModalProps, ModalOptions, ThemingProps {
*/
scrollBehavior?: ScrollBehavior
/**
* Function that will be called to get the parent element
* that the modal will be attached to.
* Props to be forwarded to the portal component
*/
getContainer?: PortalProps["getContainer"]
portalProps?: Pick<PortalProps, "appendToParentPortal" | "containerRef">
/**
* The transition that should be used for the modal
*/
Expand Down Expand Up @@ -139,7 +138,7 @@ export { ModalContextProvider, useModalContext }
*/
export const Modal: React.FC<ModalProps> = (props) => {
const {
getContainer,
portalProps,
children,
autoFocus,
trapFocus,
Expand Down Expand Up @@ -174,9 +173,7 @@ export const Modal: React.FC<ModalProps> = (props) => {
<ModalContextProvider value={context}>
<StylesProvider value={styles}>
<AnimatePresence>
{context.isOpen && (
<Portal getContainer={getContainer}>{children}</Portal>
)}
{context.isOpen && <Portal {...portalProps}>{children}</Portal>}
</AnimatePresence>
</StylesProvider>
</ModalContextProvider>
Expand Down
15 changes: 6 additions & 9 deletions packages/portal/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# @chakra-ui/portal

A wrapper for rendering components in React Portals, with support for nested
portals and stacking. No need to use `z-index` at all with this portal, that's
right!
portals and stacking.

## Installation

Expand Down Expand Up @@ -38,8 +37,6 @@ function App() {
Portals are render into the portal manager's node by default not
`document.body`.

> It'll only render into `document.body` if you don't include `PortalManager`.

```jsx
<div>
<p>Welcome</p>
Expand All @@ -61,14 +58,14 @@ popovers, modal, etc.

### Custom container

You can also portal elements into a custom containers. Simply pass a `container`
prop that points to the `node` of that element.
You can also portal elements into a custom containers. Simply pass a
`containerRef` prop that points to the `node` of that element.

```jsx
<>
<div data-testid="container" ref={ref} />
<Portal container={() => ref.current}>
<h1 data-testid="heading">Hello world</h1>
<div ref={ref} />
<Portal containerRef={ref}>
<h1>Hello world</h1>
</Portal>
</>
```
18 changes: 0 additions & 18 deletions packages/portal/migration.md

This file was deleted.