{
  "generatedFrom": "notification.contract.json",
  "component": "Notification",
  "slug": "notification",
  "group": "Feedback",
  "tier": "composite-antd",
  "summary": "A richer, stacking message with a title + description — rendered through antd's notification API.",
  "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/notification-theme';",
    "element": null,
    "registers": null
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/notification/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/notification/notification.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/notification.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/notification.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": "message",
      "type": "string",
      "default": "—",
      "desc": "The bold title line"
    },
    {
      "name": "description",
      "type": "string",
      "default": "—",
      "desc": "The supporting body text"
    },
    {
      "name": "type",
      "type": "success | info | warning | error",
      "default": "—",
      "desc": "Status glyph + tone"
    },
    {
      "name": "placement",
      "type": "topLeft | topRight | bottomLeft | bottomRight",
      "default": "topRight",
      "desc": "Which corner it stacks in"
    },
    {
      "name": "duration",
      "type": "number",
      "default": "4.5",
      "desc": "Seconds on screen; 0 keeps it until dismissed"
    },
    {
      "name": "btn",
      "type": "ReactNode",
      "default": "—",
      "desc": "One optional action (e.g. Undo) rendered in the card"
    }
  ],
  "tokens": [
    "colorPrimary",
    "borderRadius",
    "colorText",
    "Notification.width"
  ],
  "spec": [
    {
      "label": "Card",
      "value": "white elevated · 384 wide · radius 8"
    },
    {
      "label": "Title",
      "value": "ink #1A1A1A, SemiBold"
    },
    {
      "label": "Type",
      "value": "success · info · warning · error (status glyph + tone)"
    },
    {
      "label": "Placement",
      "value": "topRight default (4 corners)"
    },
    {
      "label": "Duration",
      "value": "4.5s default (0 = sticky)"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Notification",
        "when": "a message with a title + detail, or one from a background event the user may act on later"
      },
      {
        "what": "Toast",
        "when": "a one-line, past-tense confirmation with nothing to act on"
      },
      {
        "what": "Modal",
        "when": "the user must respond before continuing"
      }
    ],
    "note": "Give it a short title and a one-sentence description. Put at most one action in it; anything more belongs in a Modal or the page itself.",
    "dsv3": "COVERED — antd v6 notification.useNotification() themed by the shared notificationTheme (white card · 384 wide · radius 8), matrix: type {success · info · warning · error} × placement {topLeft · topRight · bottomLeft · bottomRight}, plus duration (0 = sticky) and an optional action btn. The DS forbids the static notification.open()/message() call — only the hook's contextHolder card consumes the ConfigProvider theme; every snippet (HTML/React/Vue) uses the hook. Verified via Figma search_design_system on the DS V3 set (fileKey MwjvUjVI0HnfwD9EwPXRAy): V3 ships no dedicated Notification component set (only Badge lives in V3; Notification remains in v2/Beta), so the DS V3 look is themed antd v6 against the V3 tokens (colorPrimary #6A1EBB, colorError #F5222D, borderRadius 8)."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.\n     Notification is a COMPOSITE (antd's notification API, no framework-free element), so its HTML\n     form is a CDN-React page — React + antd load from a CDN (esm.sh) and mount on open. It consumes\n     the SAME shared `notificationTheme` the React/Vue wrappers use, so it renders the DS V3 look\n     (white card, 384 wide, radius 8). Keeps antd's built-in motion.\n     DS rule: use the useNotification() hook + contextHolder — the static notification.open() is\n     FORBIDDEN (it renders outside the ConfigProvider theme).\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, notification, Button } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';\n  import { notificationTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/notification-theme.js';\n\n  const h = React.createElement;\n\n  function App() {\n    const [api, ctx] = notification.useNotification();\n    // type: success | info | warning | error   ·   placement: topLeft | topRight | bottomLeft | bottomRight\n    const notify = (type, placement) =>\n      api[type]({\n        message: 'Export ready',\n        description: 'Your CSV is ready to download.',\n        placement,             // which corner it stacks in (default topRight)\n        duration: 4.5,         // seconds on screen; 0 keeps it until dismissed\n        btn: h(Button, { type: 'primary', size: 'small', onClick: () => api.destroy() }, 'Undo'), // optional action\n      });\n    return h(ConfigProvider, { theme: notificationTheme },\n      ctx,\n      h(Button, { type: 'primary', onClick: () => notify('success', 'topRight') }, 'Publish'),\n      h(Button, { danger: true, onClick: () => notify('error', 'bottomLeft') }, 'Retry sync')\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 { ConfigProvider, notification, Button } from 'antd';   // antd v6\nimport { notificationTheme } from '@ahaslides-product/design/notification-theme';\n\nfunction Notifications() {\n  // v6 DS rule: use the hook so the card consumes the ConfigProvider theme.\n  // The static notification.open() is FORBIDDEN — it renders outside the theme.\n  const [api, contextHolder] = notification.useNotification();\n\n  // type: success | info | warning | error   ·   placement: topLeft | topRight | bottomLeft | bottomRight\n  const notify = (type, placement) =>\n    api[type]({\n      message: 'Export ready',\n      description: 'Your CSV of responses is ready to download.',\n      placement,                 // which corner it stacks in (default topRight)\n      duration: 4.5,             // seconds on screen; 0 keeps it until dismissed\n      btn: <Button type=\"primary\" size=\"small\" onClick={() => api.destroy()}>Undo</Button>, // optional action\n    });\n\n  return (\n    <ConfigProvider theme={notificationTheme}>\n      {contextHolder}\n      <Button type=\"primary\" onClick={() => notify('success', 'topRight')}>Publish</Button>\n      <Button danger onClick={() => notify('error', 'bottomLeft')}>Retry sync</Button>\n    </ConfigProvider>\n  );\n}\n// One shared notificationTheme → the DS V3 look; keeps antd's built-in motion.\n",
    "vue": "<script setup>\nimport { h } from 'vue';\nimport { ConfigProvider, notification, Button } from 'ant-design-vue';   // ant-design-vue v4\nimport { notificationTheme } from '@ahaslides-product/design/notification-theme';\n\n// v4 DS rule: use the hook so the card consumes the ConfigProvider theme.\n// The static notification.open() is FORBIDDEN — it renders outside the theme.\nconst [notificationApi, contextHolder] = notification.useNotification();\n\n// type: success | info | warning | error   ·   placement: topLeft | topRight | bottomLeft | bottomRight\nconst notify = (type, placement) =>\n  notificationApi[type]({\n    message: 'Export ready',\n    description: 'Your CSV of responses is ready to download.',\n    placement,               // which corner it stacks in (default topRight)\n    duration: 4.5,           // seconds on screen; 0 keeps it until dismissed\n    btn: h(Button, { type: 'primary', size: 'small', onClick: () => notificationApi.destroy() }, () => 'Undo'),\n  });\n</script>\n\n<template>\n  <a-config-provider :theme=\"notificationTheme\">\n    <component :is=\"contextHolder\" />\n    <a-button type=\"primary\" @click=\"notify('success', 'topRight')\">Publish</a-button>\n    <a-button danger @click=\"notify('error', 'bottomLeft')\">Retry sync</a-button>\n  </a-config-provider>\n</template>\n<!-- The SAME notificationTheme as React → one DS V3 look across both vendor libraries. -->\n",
    "theme": "// @ahaslides-product/design/notification-theme — declared ONCE, consumed by both tiers.\nimport { notificationTheme } from '@ahaslides-product/design/notification-theme';\n\nexport const notificationTheme = {\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    Notification: {\n      width: 384,\n      borderRadiusLG: 8,\n      colorBgElevated: '#FFFFFF',\n    },\n  },\n};\n"
  }
}
