StackedDrawer - Admin Components

Note: This component is available since Medusa v2.21.0.

The StackedDrawer component renders a drawer above a route modal. The Medusa Admin uses it to let the user pick resources without leaving the form, such as choosing customer groups while configuring a price list.

Code
import { StackedDrawer } from "@medusajs/dashboard/components"

Stacked Modals#

Render a StackedDrawer inside a RouteDrawer or a RouteFocusModal, which both provide the stacked modal context. Unlike route modals, a StackedDrawer is not tied to a route. The user opens it with a trigger, and the parent modal stays mounted underneath.

Every StackedDrawer requires an id prop. The parent modal uses the ID to track which stacked modal is open, so you can render more than one stacked modal in the same form.


Example#

The following UI route renders a StackedDrawer inside a RouteFocusModal to select a brand:

src/admin/routes/products/[id]/brand/page.tsx
import { Button, Heading } from "@medusajs/ui"
import {
  RouteFocusModal,
  StackedDrawer,
} from "@medusajs/dashboard/components"

const STACKED_MODAL_ID = "select-brand"

const ProductBrand = () => {
  return (
    <RouteFocusModal>
      <RouteFocusModal.Header />
      <RouteFocusModal.Body>
        <StackedDrawer id={STACKED_MODAL_ID}>
          <StackedDrawer.Trigger asChild>
            <Button variant="secondary" size="small">
              Select Brand
            </Button>
          </StackedDrawer.Trigger>
          <StackedDrawer.Content>
            <StackedDrawer.Header>
              <StackedDrawer.Title asChild>
                <Heading>Select Brand</Heading>
              </StackedDrawer.Title>
            </StackedDrawer.Header>
            <StackedDrawer.Body>
              <BrandList />
            </StackedDrawer.Body>
            <StackedDrawer.Footer>
              <StackedDrawer.Close asChild>
                <Button variant="secondary" size="small">
                  Cancel
                </Button>
              </StackedDrawer.Close>
            </StackedDrawer.Footer>
          </StackedDrawer.Content>
        </StackedDrawer>
      </RouteFocusModal.Body>
    </RouteFocusModal>
  )
}

export default ProductBrand

Props#

idstring
A unique identifier for the drawer. It differentiates stacked modals registered to the same parent modal. This prop is required.

Sub-components#

Component

Description

StackedDrawer.Trigger

Opens the drawer when clicked. Pass asChild to use your own button.

StackedDrawer.Content

The drawer's content. It renders a transparent overlay so that the parent modal stays visible.

StackedDrawer.Header

The drawer's header. Place the title and description in it.

StackedDrawer.Title

The drawer's title. Pass asChild to render your own heading element.

StackedDrawer.Description

An accessible description of the drawer's purpose.

StackedDrawer.Body

The drawer's scrollable content area.

StackedDrawer.Footer

The drawer's footer. Place the cancel and confirm buttons in it.

StackedDrawer.Close

Closes the drawer when clicked, keeping the parent modal open. Pass asChild to use your own button.


useStackedModal#

Use the useStackedModal hook to control a stacked modal programmatically. For example, close the drawer after the user confirms their selection.

Code
import { useStackedModal } from "@medusajs/dashboard/components"

Call the hook in a component rendered inside a route modal. It throws an error if you use it elsewhere.

Returned Values#

getIsOpen(id: string) => boolean
Returns whether the stacked modal of the specified ID is open.
setIsOpen(id: string, open: boolean) => void
Opens or closes the stacked modal of the specified ID.
register(id: string) => void
Registers a stacked modal in the parent modal. StackedDrawer and StackedFocusModal call it for you when they mount.
unregister(id: string) => void
Removes a stacked modal from the parent modal. The components call it for you when they unmount.

Example#

src/admin/routes/products/[id]/brand/page.tsx
import { Button } from "@medusajs/ui"
import { useStackedModal } from "@medusajs/dashboard/components"

const BrandList = () => {
  const { setIsOpen } = useStackedModal()

  const handleSave = () => {
    setIsOpen("select-brand", false)
  }

  return (
    <Button size="small" onClick={handleSave}>
      Save
    </Button>
  )
}
Found a problem with this page?Report Issue
Edited Nov 14·Edit this page