RouteFocusModal - Admin Components
The RouteFocusModal component renders a full-screen modal that covers the page behind it. The Medusa Admin uses it for forms that need a lot of space, such as the form that creates a region.
Route Modals#
RouteFocusModal is tied to a route, not to a trigger button. You render it as the root element of a UI route that is nested under the page it belongs to. When the user navigates to that route, the modal opens. When the user closes the modal, RouteFocusModal navigates back to the previous route.
So, to open the modal, link the user to the modal's route. For example, link to /brands/create from the brand list page.
Use RouteFocusModal for create forms and multi-step flows, and use the RouteDrawer for smaller edit forms.
Example#
Consider a UI route at src/admin/routes/brands/create/page.tsx that creates a brand:
import { Button, Heading, Input } from "@medusajs/ui"
import {
RouteFocusModal,
useRouteModal,
} from "@medusajs/dashboard/components"
import { useForm } from "react-hook-form"
const BrandCreate = () => {
return (
<RouteFocusModal>
<CreateBrandForm />
</RouteFocusModal>
)
}
const CreateBrandForm = () => {
const { handleSuccess } = useRouteModal()
const form = useForm({
defaultValues: {
name: "",
},
})
const handleSubmit = form.handleSubmit(async (data) => {
const brand = await createBrand(data)
handleSuccess(`../${brand.id}`)
})
return (
<RouteFocusModal.Form form={form}>
<form onSubmit={handleSubmit}>
<RouteFocusModal.Header />
<RouteFocusModal.Body>
<Heading>Create Brand</Heading>
<Input {...form.register("name")} />
</RouteFocusModal.Body>
<RouteFocusModal.Footer>
<RouteFocusModal.Close asChild>
<Button variant="secondary" size="small">
Cancel
</Button>
</RouteFocusModal.Close>
<Button type="submit" size="small">
Create
</Button>
</RouteFocusModal.Footer>
</form>
</RouteFocusModal.Form>
)
}
export default BrandCreate
Call the useRouteModal hook in a child of the RouteFocusModal, since the modal provides its context. The hook returns handleSuccess, which closes the modal after a successful submission. Refer to the Route Drawer documentation for the hook's returned values, including setCloseOnEscape that controls whether the Escape key closes the modal.
Props#
RouteFocusModal accepts the following props, in addition to its children:
prevstring | object | numberOptionalThe route to navigate to when the modal closes. Pass a string, such as "../..", or an object with the path's parts. You can also pass a number, such as -1, to go back that many entries in the browser's history instead of navigating to a route.Default: ..
prevstring | object | numberOptional..Sub-components#
Component | Description |
|---|---|
| The modal's header. It renders the close button, so render it even when it has no children. |
| The modal's title. Pass |
| An accessible description of the modal's purpose. |
| The modal's scrollable content area. |
| The modal's footer. Place the cancel and submit buttons in it. |
| Closes the modal when clicked, which navigates back to the |
| Wraps a React Hook Form form. It provides the form's context to the fields, and shows a confirmation prompt if the user leaves the route while the form has unsaved changes. |
RouteFocusModal.Form Props#
formobjectThe form instance returned by the useForm hook of React Hook Form. Refer to React Hook Form's documentation for all of its properties.
formobjectblockSearchParamsbooleanOptionalDefault: false
onClose(isSubmitSuccessful: boolean) => voidOptionalStacking Modals#
To open another modal above a RouteFocusModal, such as a table for the user to select items from, use the StackedFocusModal or the StackedDrawer components. Both are controlled with the useStackedModal hook.