shadcn-ui/ui · error · Error

useDrawer must be used within a Drawer.

Error message

useDrawer must be used within a Drawer.

What it means

Identical contract to [153] but in the `base` style registry. `useDrawer` reads `DrawerContext`; drawer parts rendered outside `<Drawer>` throw so behavior props are never null.

Source

Thrown at apps/v4/registry/bases/base/ui/drawer.tsx:21

import * as React from "react"
import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer"

import { cn } from "@/registry/bases/base/lib/utils"

type DrawerContextProps = {
  hasSnapPoints: boolean
  modal: DrawerPrimitive.Root.Props["modal"]
  showSwipeHandle: boolean
  swipeDirection: NonNullable<DrawerPrimitive.Root.Props["swipeDirection"]>
}

const DrawerContext = React.createContext<DrawerContextProps | null>(null)

function useDrawer() {
  const context = React.useContext(DrawerContext)

  if (!context) {
    throw new Error("useDrawer must be used within a Drawer.")
  }

  return context
}

function Drawer({
  modal = true,
  showSwipeHandle = false,
  snapPoints,
  swipeDirection = "down",
  ...props
}: DrawerPrimitive.Root.Props & {
  showSwipeHandle?: boolean
}) {
  const hasSnapPoints = snapPoints != null && snapPoints.length > 0
  const contextValue = React.useMemo(
    () => ({ hasSnapPoints, modal, showSwipeHandle, swipeDirection }),
    [hasSnapPoints, modal, showSwipeHandle, swipeDirection]

View on GitHub (pinned to efac598707)

Solutions

  1. Keep all Drawer sub-parts inside `<Drawer>` from the `base` style import path.
  2. Ensure portals keep the React subtree under `<Drawer>`.
  3. Decorate tests/stories with `<Drawer>`.

Example fix

// before
<DrawerTrigger>Open</DrawerTrigger>
<Drawer>
  <DrawerContent />
</Drawer>

// after
<Drawer>
  <DrawerTrigger>Open</DrawerTrigger>
  <DrawerContent />
</Drawer>
Defensive patterns

Strategy: type-guard

Validate before calling

render(<Drawer><DrawerTrigger>Open</DrawerTrigger><DrawerContent>...</DrawerContent></Drawer>) // base style imports

Type guard

import React from "react"
import { DrawerContext } from "@/registry/bases/base/ui/drawer"
const insideDrawer = () => React.useContext(DrawerContext) != null

Try / catch

try { useDrawer() } catch (e) { if (e.message.includes("Drawer.")) {/*nest inside Drawer*/} throw e }

Prevention

When it happens

Trigger: Mounting `<DrawerContent />` / `<DrawerTrigger />` outside `<Drawer>` when importing from the `base` style.

Common situations: Using the `base` style and splitting drawer markup; portal-detached content; tests of individual parts.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/cbfcb34000fa64ea. Report an issue: GitHub.