Programmatic control of drawers
The PlumaDrawer component is used to display drawer dialogs.
Using the PlumaDrawer component directly, however, can be difficult to manage,
as it requires manually keeping track of the drawer's open state. This also makes
it difficult to reuse the same drawer in multiple places, as it involves extra
boilerplate code.
Pluma's Drawer Manager is a utility that simplifies the creation and management of drawers.
To use a drawer via the manager, we first need to define a drawer component, which will later be referenced in the manager.
Pluma exports utility types that help define the component's props - it's highly recommended to use these types to ensure type safety and type hints.
PlumaManagedDrawerProps<Props, ConfirmArg, CloseArg> is a generic type that wraps up the props that are passed
into a drawer component invoked by the drawer manager. It takes three generic parameters:
Props: The custom props you plan to pass into the drawer componentConfirmArg: The argument you will pass into the onConfirm callbackCloseArg: The argument you will pass into the onClose callbackTo define a drawer component, you need to use this type as your components' props type.
When the drawer is opened, the manager will pass any of your custom Props into
the drawer component under the data key. Additionally, two callbacks are available:
onClose: A callback to call when you want to close the drawer when the user cancels an actiononConfirm: A callback for when the user confirms an action, or otherwise performs a CTA-like action
Finally, a drawerState object is also present. It is required to forward this prop
into the PlumaDrawer's state prop - it holds the drawer's open state and other drawer-related props.
Now that we have defined a managed drawer component, we can use it with the manager.
The useDrawers hook returns the drawer manager, which allows you to open and interact with drawers.
To open a drawer, you can use the open method. As the first argument it accepts
the drawer component you previously defined. As the second argument, it expects
the additional props that you expect to see under data.
There is also a useDrawer hook, which accepts a drawer component as its argument
and returns a drawer manager API bound to that specific component. It's a shortcut
to make it a little easier to reuse the same drawer in different places.
The manager's open method returns a unique identifier for the opened drawer.
This identifier can be used in the manager's waitForClose method, which returns
a promise that resolves when the drawer is closed.
The value returned from this resolved promise is an object with the following properties:
reason: The reason the drawer was closed, a string with one of the following values:
close - called when the drawer is closed with the onClose callback,
or when the drawer is closed by clicking the backdrop, the X close button, or by pressing the escape key
(if those are enabled)confirm - called when the drawer is closed with the onConfirm callbackdata: The data that was passed to the drawer's onClose or onConfirm callbackexplanation: The explanation for the drawer closure. Only present when the drawer is closed
through the drawer's "native" close mechanisms, such as clicking the backdrop. The explanation
is a string with one of Floating UI's onOpenChange reasons,
close-button-press if closed by clicking the drawer's X close button, or
drawer-manager:close-all if closed by calling the manager's closeAll methodThis value can be used to handle the drawer closure in the parent component.
Sometimes it might be necessary to update a drawer's data props after it has been opened.
This can be done with the manager's update method. It takes the drawer's identifier
as the first argument, and the new props as the second argument.
The new props will be merged with the existing props, and the drawer will be updated accordingly.
If you need to customize any of the Drawer component's behavior, you can still use
any of it's arguments as usual. For example, if you'd like make the drawer non-dismissable,
you can still use the isDismissable prop to achieve this.
If the configuration needs to depend on arguments you pass into the drawer, you may
use your data props to pass that configuration further into the drawer.
By default, a managed drawer automatically closes when the component that opened it is unmounted - for example, when a route transition happens.
In some cases, you may want to keep the drawer open even after its opening component
unmounts, so it stays open until explicitly closed (either by user action or
programmatically). To opt out of the automatic behavior, pass an additional
configuration argument into the open method: { shouldCloseOnUnmount: false }.
For useDrawers, this will be the third argument, while for useDrawer this will be the second argument.