Axon 911 Frontend DocsAxon 911 Frontend Docs
Axon 911 Frontend Docs
    Loading navigation…
U
User
Switch to light mode
  1. Blocks
  2. Drawer Host
  3. Usage

Drawer host

Usage

Overview
DrawerHost from @prepared911/ui/blocks/drawer-host is the app drawer a shell mounts once. The shell owns whether it is open and which id it shows. The host renders that one drawer, swaps the content when the id changes, and can show a nav strip under the header. Use it where a shell used to mount a drawer portal and drive several drawers through one module store. A single panel that is not the shared app drawer still uses Drawer. A record with an unsaved-changes guard uses DetailDrawer.
When to use
  • The shell's shared drawer. Diagnostics, layers, and chat take turns in one panel.
  • State the shell already owns. The drawer search param stays on the shell route. Pass open and drawerId, or pass a store the shell created with createDrawerHostStore.
  • A nav strip inside that drawer. Pass nav on the drawer entry. The host renders the same segmented strip as DrawerNav.
When not to use
  • One record with a dirty form. Use DetailDrawer.
  • A form drawer with a sticky footer. Use FormLayoutDrawer.
  • A remote writing the shell URL. Remotes do not set the drawer search param. They ask the shell, and the shell updates the host.
State
Pass open, drawerId, and onOpenChange, or pass store. Do not pass both. createDrawerHostStore returns a new store each call. The shell holds it. The package does not keep a shared store, so two copies of the package do not share open state.
Changing drawerId while open is true replaces the header and the body in the same dialog.
Focus
Escape closes the drawer and focus returns to trigger. Open it from a row and omit trigger: focus returns to the element that was focused before the drawer opened.
Where it mounts
The surface is Drawer. Its dialog renders where the host sits in the React tree, and through Portal into the trigger's owner document when the trigger is in another window. OverlayContainerProvider closes the drawer when that window changes. There is no DrawerPortal element to mount. Mount the host at the shell's root, beside the shell layout, not inside it. A non-modal drawer stacks at --z-overlay in the page's stacking order, below popovers, menus, tooltips, toasts and modal dialogs. An ancestor that creates a stacking context or a containing block (transform, filter, contain, will-change, or a positioned box with a z-index) confines it to that ancestor, so a host rendered inside a panel or a remote's mount covers only that region. See Drawer stacking.
Hosting drawers in a Module Federation shell
A remote does not render a page-level drawer of its own and does not write the shell's drawer search param. It asks the shell through the navigation domain, and the shell's DrawerHost shows the module:
navigation (from @prepared911/core/mfe/react) has openDrawer(moduleId, options?), closeDrawer(moduleId), getOpenDrawer() and onDrawerChanged(callback). The shell implementation writes the module id into the shell-owned drawer search param and reports every change through onDrawerChanged. The id is a module id from the router's ID_REGISTRY, written <remote>/<module>. The shell subscribes to that domain, lists one entry of drawers per module it allows in its drawer, and closes through the domain:
Render <ShellDrawers /> once, beside the shell layout. The pieces:
  • Stable domains. usePortalIntegrations memoizes on the identity of the array it is given, so the domains array must be stable: declare it once at module scope, as SHELL_DOMAINS is. An inline [navigationDefinition] is a new array every render, which reconnects the domain, re-subscribes the effect, and can render the shell in a loop.
  • Open state. onDrawerChanged reports the current drawer as soon as it subscribes, then every change. The shell keeps the last drawerId when the drawer closes, so the panel keeps its content while it slides out. nextDrawerState returns previous itself when a report changes nothing, so a repeated report does not re-render the shell.
  • Allowed modules. Each entry's id is the module id a remote passes to openDrawer, and its content is <RemoteComponent id="…" /> for that module. RemoteComponent takes id, loading (shown while the remote chunk loads) and children; the mount's error boundary renders a failing remote's error inside the drawer body. An id the shell does not list renders no drawer: the search param changes and nothing opens. List every module that may open in the drawer.
  • Closing. Escape, the close button and an outside press reach onOpenChange with false; the shell calls navigation.closeDrawer(moduleId), which clears the search param and reports null. Focus returns to the control that was focused before the drawer opened, such as the remote's button.
The shell also provides what every remote's markup needs, once: the @prepared911/ui/styles.css stylesheet on the document, data-theme on the document element, and DesignSystemEnvironment for the locale, time zone and direction. A remote renders none of them. See remote composition.
Previous
App Header / Accessibility
Next
Drawer host / API and Development
On this page
Overview
When to use
When not to use
State
Focus
Where it mounts
Hosting drawers in a Module Federation shell