{
  "generatedFrom": "drawer.contract.json",
  "component": "Drawer",
  "slug": "drawer",
  "group": "Feedback",
  "tier": "composite-antd",
  "summary": "A side panel that slides in for a longer edit or detail view — rendered through the shared Drawer.",
  "install": {
    "package": "@ahaslides-product/design",
    "registry": "https://npm.pkg.github.com",
    "scope": "@ahaslides-product",
    "auth": "Published to GitHub Packages — needs a GitHub token with read:packages. Configure the @ahaslides-product scope in .npmrc before installing.",
    "npmrc": "@ahaslides-product:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}   # a GitHub token with read:packages",
    "command": "npm i @ahaslides-product/design",
    "tokenLayer": "import '@ahaslides-product/design/tokens.css';",
    "import": "import '@ahaslides-product/design/drawer-theme';",
    "element": null,
    "registers": null
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/drawer/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/drawer/drawer.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/drawer.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/drawer.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — a CDN-React runnable page (React + antd loaded from a CDN, no build step) — React/Vue use the same shared-themed DataTable via your bundler. Paste into an .html file and it renders with no build step.",
  "frameworks": {
    "react": {
      "package": "antd",
      "major": 6
    },
    "vue": {
      "package": "ant-design-vue",
      "major": 4
    },
    "html": {
      "via": "cdn-react",
      "runnable": "paste-and-run — React + antd loaded from a CDN, no build step"
    }
  },
  "props": [
    {
      "name": "open",
      "type": "boolean",
      "default": "false",
      "desc": "Controls visibility"
    },
    {
      "name": "title",
      "type": "string",
      "default": "—",
      "desc": "Panel heading"
    },
    {
      "name": "placement",
      "type": "top | right | bottom | left",
      "default": "right",
      "desc": "Which edge it slides from"
    },
    {
      "name": "width",
      "type": "number | string",
      "default": "378",
      "desc": "Panel width for left/right (large ≈ 736)"
    },
    {
      "name": "height",
      "type": "number | string",
      "default": "378",
      "desc": "Panel height for top/bottom (large ≈ 480)"
    },
    {
      "name": "size",
      "type": "default | large",
      "default": "default",
      "desc": "antd preset size (378/736 l·r); the DS default is 378"
    },
    {
      "name": "footer",
      "type": "ReactNode",
      "default": "—",
      "desc": "Pinned actions row (keep the primary action here)"
    },
    {
      "name": "mask",
      "type": "boolean",
      "default": "true",
      "desc": "Dim + scroll-lock the page behind the panel"
    },
    {
      "name": "closable",
      "type": "boolean",
      "default": "true",
      "desc": "Show the header close (X)"
    },
    {
      "name": "onClose",
      "type": "() => void",
      "default": "—",
      "desc": "Dismiss handler"
    }
  ],
  "tokens": [
    "colorPrimary",
    "borderRadius",
    "colorText",
    "Drawer.colorBgElevated"
  ],
  "spec": [
    {
      "label": "Panel",
      "value": "white surface, slides from the right (or any edge)"
    },
    {
      "label": "Title",
      "value": "ink #1A1A1A · SemiBold"
    },
    {
      "label": "Body",
      "value": "24 padding · ink text"
    },
    {
      "label": "Mask",
      "value": "ink overlay rgba(26,26,46,.7)"
    },
    {
      "label": "Motion",
      "value": "antd's built-in slide enter/leave (kept)"
    }
  ],
  "opinion": {
    "dsv3": "COVERED — antd v6 Drawer themed by the shared drawerTheme; matrix: placement (top·right·bottom·left) × size (default 378 · large 736 for left/right; 300/480 height for top/bottom), + title, footer, mask, closable. Right is the DS default for settings/edit, bottom for mobile-style sheets. Verified via Figma search_design_system against the DS V3 Drawer set (component_set componentKey 8c242d8ea431dcfc885d7b0a8c9611704b1039e5, 'A panel which slides in from the edge of the screen').",
    "whenToUse": [
      {
        "what": "Drawer",
        "when": "a longer edit form or detail panel where keeping page context matters"
      },
      {
        "what": "Modal",
        "when": "a short, blocking decision the user must complete first"
      },
      {
        "what": "a page",
        "when": "the task is large enough to deserve its own route"
      }
    ],
    "note": "Give it a clear title and keep the primary action pinned in a footer. Right placement for settings/edit; bottom for mobile-style sheets."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.\n     Drawer is a COMPOSITE (antd, no framework-free element), so its HTML form is a\n     CDN-React page — React + antd load from a CDN (esm.sh) and mount on open. It\n     consumes the SAME shared `drawerTheme` the React/Vue wrappers use, so it renders\n     the DS V3 look (white panel, ink title). Keeps antd's built-in slide motion.\n     No JSX here (JSX needs a compiler) — we use React.createElement via the `h` alias. -->\n<div id=\"root\"></div>\n<script type=\"module\">\n  import React from 'https://esm.sh/react@18';\n  import { createRoot } from 'https://esm.sh/react-dom@18/client';\n  import { ConfigProvider, Drawer, Button, Space } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';\n  import { drawerTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/drawer-theme.js';\n\n  const h = React.createElement;\n  const { useState } = React;\n\n  // Matrix: placement (top | right | bottom | left) × size (default 378 · large 736 for left/right).\n  const placement = 'right';   // right for settings/edit; bottom for mobile-style sheets\n  const size = 'default';      // 'large' → wider panel (736 for left/right)\n  const horiz = placement === 'left' || placement === 'right';\n  const dim = horiz ? { width: size === 'large' ? 736 : 378 } : { height: size === 'large' ? 480 : 300 };\n\n  function App() {\n    const [open, setOpen] = useState(false);\n    return h(ConfigProvider, { theme: drawerTheme },\n      h(Button, { type: 'primary', onClick: () => setOpen(true) }, 'Slide settings'),\n      h(Drawer, {\n        open,\n        title: 'Slide settings',\n        placement,\n        ...dim,\n        mask: true,        // mask + scroll-lock the page (antd default)\n        closable: true,    // header close (X)\n        onClose: () => setOpen(false),\n        footer: h(Space, null, h(Button, { onClick: () => setOpen(false) }, 'Cancel'), h(Button, { type: 'primary' }, 'Save changes')),\n      }, h('p', null, 'Adjust how this slide behaves for your audience.'))\n    );\n  }\n  // Same shared theme the React/Vue wrappers pass to ConfigProvider.\n  createRoot(document.getElementById('root')).render(h(App));\n</script>\n",
    "react": "import { useState } from 'react';\nimport { ConfigProvider, Drawer, Button, Space } from 'antd';   // antd v6\nimport { drawerTheme } from '@ahaslides-product/design/drawer-theme';\n\nfunction SlideSettings() {\n  const [open, setOpen] = useState(false);\n  // Matrix: placement (top | right | bottom | left) × size (default 378 · large 736 for left/right).\n  const placement = 'right';   // right for settings/edit; bottom for mobile-style sheets\n  const size = 'default';      // 'large' → wider panel (736 for left/right)\n  const horiz = placement === 'left' || placement === 'right';\n  const dim = horiz ? { width: size === 'large' ? 736 : 378 } : { height: size === 'large' ? 480 : 300 };\n  return (\n    <ConfigProvider theme={drawerTheme}>\n      <Button type=\"primary\" onClick={() => setOpen(true)}>Slide settings</Button>\n      <Drawer\n        open={open}\n        title=\"Slide settings\"\n        placement={placement}\n        {...dim}\n        mask         /* mask + scroll-lock the page (antd default) */\n        closable     /* header close (X) */\n        onClose={() => setOpen(false)}\n        footer={<Space><Button onClick={() => setOpen(false)}>Cancel</Button><Button type=\"primary\">Save changes</Button></Space>}\n      >\n        <p>Adjust how this slide behaves for your audience.</p>\n      </Drawer>\n    </ConfigProvider>\n  );\n}\n// One shared drawerTheme → the DS V3 look; keeps antd's built-in slide motion.\n",
    "vue": "<script setup>\nimport { ref } from 'vue';\nimport { ConfigProvider, Drawer, Button, Space } from 'ant-design-vue';   // ant-design-vue v4\nimport { drawerTheme } from '@ahaslides-product/design/drawer-theme';\n\nconst open = ref(false);\n// Matrix: placement (top | right | bottom | left) × size (default 378 · large 736 for left/right).\nconst placement = 'right';   // right for settings/edit; bottom for mobile-style sheets\nconst size = 'default';      // 'large' → wider panel (736 for left/right)\n</script>\n\n<template>\n  <a-config-provider :theme=\"drawerTheme\">\n    <a-button type=\"primary\" @click=\"open = true\">Slide settings</a-button>\n    <a-drawer\n      v-model:open=\"open\"\n      title=\"Slide settings\"\n      :placement=\"placement\"\n      :width=\"(placement === 'left' || placement === 'right') ? (size === 'large' ? 736 : 378) : undefined\"\n      :height=\"(placement === 'top' || placement === 'bottom') ? (size === 'large' ? 480 : 300) : undefined\"\n      :mask=\"true\"\n      :closable=\"true\"\n    >\n      <p>Adjust how this slide behaves for your audience.</p>\n      <template #footer>\n        <a-space>\n          <a-button @click=\"open = false\">Cancel</a-button>\n          <a-button type=\"primary\">Save changes</a-button>\n        </a-space>\n      </template>\n    </a-drawer>\n  </a-config-provider>\n</template>\n<!-- The SAME drawerTheme as React → one DS V3 look across both vendor libraries. -->\n",
    "theme": "// @ahaslides-product/design/drawer-theme — declared ONCE, consumed by both tiers.\nimport { drawerTheme } from '@ahaslides-product/design/drawer-theme';\n\nexport const drawerTheme = {\n  token: {\n    colorPrimary: '#6A1EBB',\n    borderRadius: 8,\n    colorText: '#1A1A1A',\n    colorTextHeading: '#1A1A1A',\n    colorBgElevated: '#FFFFFF',\n    fontFamily: 'var(--aha-font-product, \"Plus Jakarta Sans\", sans-serif)',\n  },\n  components: {\n    Drawer: {\n      colorBgElevated: '#FFFFFF',   // white panel surface\n      colorText: '#1A1A1A',\n    },\n  },\n};\n"
  }
}
