From 28d0b11aaca83283f61222b2cf23c54a50000c25 Mon Sep 17 00:00:00 2001 From: Jack Shelton <104264123+thejackshelton@users.noreply.github.com> Date: Mon, 18 Dec 2023 08:44:34 -0600 Subject: [PATCH] docs: update portal cookbook with solved problems (#5600) --- .../src/routes/docs/cookbook/portal/index.mdx | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/docs/src/routes/docs/cookbook/portal/index.mdx b/packages/docs/src/routes/docs/cookbook/portal/index.mdx index fe782c59502..70004b4d03f 100644 --- a/packages/docs/src/routes/docs/cookbook/portal/index.mdx +++ b/packages/docs/src/routes/docs/cookbook/portal/index.mdx @@ -12,17 +12,52 @@ import CodeSandbox, {CodeFile} from '../../../../components/code-sandbox/index.t # Portal -A common problem in front-end development is to pop up a modal dialog from a component. The complication is that the modal dialog needs to be rendered in a different part of the DOM tree, and the component that triggers the modal needs to have a way to affect the location of rendering. +In front-end development, sometimes we need to display a component (like a modal or tooltip) in a different place from where it was triggered. The issue is that the UI element needs to be rendered in a different part of the DOM tree, and the component that triggers the element needs to have a way to affect the location of rendering. -In other frameworks, this is often solved by dedicated API such as [`createPortal()`](https://react.dev/reference/react-dom/createPortal). However such APIs don't work well with server-side rendering and so an alternative approach is needed. +In other frameworks, this is often solved by a dedicated API such as [`createPortal()`](https://react.dev/reference/react-dom/createPortal). However such APIs don't work well with server-side rendering and so an alternative approach is needed. -## Alternatives +## Qwik UI -You may want to consider these modern browser alternatives to modals: -- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog -- https://developer.chrome.com/blog/introducing-popover-api/ +Luckily, there is native behavior that handles this for us, called the [top layer](https://developer.chrome.com/blog/what-is-the-top-layer). The Qwik UI team has done an awesome job of filling in the gaps, and allowing us to use this behavior in production. -## Problem +### Modals + +We use modals when we do not want the user to interact with the rest of the page. The rest of the content is inert, or unable to be interacted with. + +[Qwik UI's modal component](https://qwikui.com/docs/headless/modal/) uses the dialog element's [showModal](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal) method, which is well-supported in browsers and automatically handles placing UI outside of the HTML Document. + +It also includes behavior such as focus and scroll locking, alert dialogs, automatic entry and exit animation support, and backdrop animations. At the time of writing, support for the dialog element is currently at 96%. + +### Non-modal UI + +If the UI element can interact with the rest of the page, then it is not modal. + +Some examples of non-modal components are: +- Popovers +- Overlays +- Toasts +- Tooltips +- Dropdown menus +- Selects +- Comboboxes + +[MDN's popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) replaces the need for portals in non-modal components. Support is also in every major browser. At the time of writing, it's at ~73%. + +Qwik UI has taken it upon themselves by providing a polyfill with feature parity to the native spec. You can use the Popover API's behavior in production today with [Qwik UI's Popover](https://qwikui.com/docs/headless/popover/) component. + +In the case of components like a select or combobox, Qwik UI also provides the abiltiy to opt-in to "floating" behavior. For example, when a listbox anchors to an input element. You can do so by adding `floating={true}` to your Popover component. This will execute a bit of extra javascript needed for floating behavior. + +It is intentionally opt-in, at some point the CSS Anchor API will provide a native solution, and so there should be an easy migration path when that receives more general support. + +> Because these solutions are built on top of the native specs, that also means there's less javascript we need to prefetch, and therefore less work that needs to be done! + +Both Qwik UI's popover and modal components can be used regardless of meta-framework or microfrontend, as long as there is support for Qwik. + +## Custom Portals + +If the behavior of the above components do not fit the use case, there is also the ability to create a custom portal component in Qwik. We'll create a modal component from scratch. + +> The following is an SSR portal implementation using Qwik City. If you are using multiple frontend frameworks alongside Qwik, you may prefer a [React-like portal implementation](https://github.com/qwikifiers/qwik-ui/blob/main/packages/kit-headless/src/components/popover/popover-impl.tsx#L42). The fundamental problems to solve are: 1. decide where the popup should be rendered in the application. (Let's call this ``)