{
  "name": "Drawer",
  "source": "src/components/Drawer.tsx",
  "propsType": "DrawerProps",
  "description": "Drawer — a modal panel anchored to an edge.\n\nWHY IT IS A MODAL AND NOT A SIDEBAR\n\nIt takes focus, traps it, closes on Escape and on an outside click, and marks\nthe rest of the page inert — all of `Modal`'s behaviour, differing only in\nwhere the panel sits and how it enters. A persistent side panel that does not\ndo those things is layout, not a drawer, and belongs in the page rather than\nin an overlay.\n\nWHEN TO REACH FOR MODAL INSTEAD\n\nA drawer suits work that is long or list-shaped — filters, a record's detail,\na sequence of settings — because an edge panel can be tall without becoming a\nsquare that fights the viewport. A decision, especially a destructive one,\nbelongs in a Modal: it is centred, it is smaller, and it does not invite\nscrolling past the thing being confirmed.\n\nRENDERS NOTHING WHEN CLOSED, and portals when open, for the reasons recorded\non Modal: a closed overlay left in the tree is still keyboard-focusable, and\nan inline one inherits whatever `overflow` and stacking context surrounds it.",
  "import": "import { Drawer } from 'ionbase-ui';",
  "status": "stable",
  "summary": "A modal panel anchored to an edge. Modal behaviour — focus trap, Escape, scrim — with the shape of a side panel.",
  "useWhen": [
    "work that is long or list-shaped: filters, a record's detail, a run of settings",
    "the page behind should stay visible as context while a task is done beside it",
    "a form long enough that a centred dialog would scroll its own actions off screen"
  ],
  "useInstead": [
    {
      "when": "the user is making a decision, especially a destructive one",
      "use": "Modal",
      "why": "a modal is centred and small enough that the thing being confirmed cannot be scrolled past"
    },
    {
      "when": "the panel should stay open while the user works elsewhere",
      "use": "SidePanel",
      "why": "a drawer traps focus and marks the rest of the page inert. SidePanel opens beside the content and leaves it usable"
    },
    {
      "when": "the content is a short menu of actions",
      "use": "Popover or Menu"
    }
  ],
  "variants": {
    "placement": {
      "start": {
        "use": "navigation and hierarchy, which readers expect at the leading edge"
      },
      "end": {
        "use": "the default — detail and editing beside the record that opened it"
      },
      "top": {
        "use": "rare: a global search or command surface"
      },
      "bottom": {
        "use": "touch-first layouts, where the bottom edge is the reachable one"
      }
    },
    "size": {
      "sm": {
        "use": "a short form or a filter list"
      },
      "md": {
        "use": "the default"
      },
      "lg": {
        "use": "a record detail with its own sections"
      }
    }
  },
  "slots": {
    "title": {
      "accepts": "text",
      "note": "required — it is the dialog's accessible name"
    },
    "description": {
      "accepts": "text"
    },
    "children": {
      "accepts": "any content",
      "note": "the only scrolling region"
    },
    "footer": {
      "accepts": "Button",
      "note": "pinned to the bottom edge, so actions stay reachable in a long panel"
    }
  },
  "a11y": {
    "requires": [
      "`title`, which becomes the dialog's accessible name via aria-labelledby"
    ],
    "notes": [
      "start and end follow writing direction, so a right-hand drawer in English is a left-hand one in Arabic with no second variant",
      "renders nothing when closed and portals when open: a closed overlay left in the tree is still keyboard-focusable",
      "only the body scrolls, so the title stays on screen — the one piece of context a user needs while working down a long list"
    ]
  },
  "antiPatterns": [
    {
      "dont": "a Drawer that stays open while the user edits the page behind it",
      "do": "<SidePanel> inside a SidePanelLayout",
      "why": "it traps focus and marks the rest inert; a keyboard user cannot reach the page behind it"
    },
    {
      "dont": "<Drawer> for a delete confirmation",
      "do": "<Modal>",
      "why": "an edge panel is tall, so the confirm button can sit below the fold — the one control that must never be missed"
    }
  ],
  "stylesheet": "src/styles/drawer.css",
  "tokens": [
    "--border-focus",
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-semibold",
    "--icon-secondary",
    "--icon-size-md",
    "--ion-drawer-size",
    "--ion-duration-base",
    "--ion-ease-out",
    "--radius-lg",
    "--radius-sm",
    "--spacing-12",
    "--spacing-24",
    "--spacing-32",
    "--spacing-4",
    "--spacing-8",
    "--surface-hover",
    "--surface-raised",
    "--surface-scrim",
    "--text-default",
    "--text-secondary",
    "--type-body",
    "--type-body-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height",
    "--type-h5",
    "--type-h5-line-height"
  ],
  "props": {
    "isOpen": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Whether the drawer is shown."
    },
    "onOpenChange": {
      "type": "((isOpen: boolean) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Called with the next open state — `false` when the drawer asks to close."
    },
    "placement": {
      "type": "DrawerPlacement | undefined",
      "required": false,
      "origin": "own",
      "description": "Which edge it enters from. `start` and `end` follow writing direction, so\na right-hand drawer in English is a left-hand one in Arabic without a\nsecond variant.",
      "values": [
        "top",
        "bottom",
        "start",
        "end"
      ],
      "default": "end"
    },
    "size": {
      "type": "DrawerSize | undefined",
      "required": false,
      "origin": "own",
      "values": [
        "sm",
        "md",
        "lg"
      ],
      "default": "md"
    },
    "title": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "Required: the dialog's accessible name, wired via `aria-labelledby`."
    },
    "description": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Supporting copy under the title."
    },
    "footer": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Action row, pinned to the bottom edge."
    },
    "showClose": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "default": true
    },
    "closeLabel": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "default": "Close drawer"
    },
    "children": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own"
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "isDismissable": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "aria",
      "description": "Whether to close the modal when the user interacts outside it.",
      "tags": {
        "default": "false"
      }
    },
    "isKeyboardDismissDisabled": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "aria",
      "description": "Whether pressing the escape key to close the modal should be disabled.",
      "tags": {
        "default": "false"
      }
    },
    "shouldCloseOnInteractOutside": {
      "type": "((element: Element) => boolean) | undefined",
      "required": false,
      "origin": "aria",
      "description": "When user interacts with the argument element outside of the overlay ref,\nreturn true if onClose should be called.  This gives you a chance to filter\nout interaction with elements that should not dismiss the overlay.\nBy default, onClose will always be called on interaction outside the overlay ref."
    }
  },
  "propCounts": {
    "own": 11,
    "aria": 3,
    "dom": 0,
    "other": 0
  }
}
