{
  "generatedFrom": "form.contract.json",
  "component": "Form",
  "slug": "form",
  "group": "Data Entry",
  "tier": "composite-antd",
  "summary": "A labelled, validated set of fields — sign-in, settings, create dialogs — rendered through the shared Form.",
  "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/form-theme';",
    "element": null,
    "registers": null
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/form/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/form/form.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/form.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/form.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": "layout",
      "type": "vertical | horizontal | inline",
      "default": "vertical",
      "desc": "Label placement"
    },
    {
      "name": "size",
      "type": "small | default | large",
      "default": "default",
      "desc": "Control height for every field (24 / 32 / 40)"
    },
    {
      "name": "fields",
      "type": "FormItem[]",
      "default": "[]",
      "desc": "name / label / rules / control per row"
    },
    {
      "name": "requiredMark",
      "type": "boolean | 'optional'",
      "default": "true",
      "desc": "Show the required asterisk (or mark optional fields instead)"
    },
    {
      "name": "validateStatus",
      "type": "error | warning | success | validating",
      "default": "—",
      "desc": "Per-Form.Item validation state — coloured border + help text"
    },
    {
      "name": "initialValues",
      "type": "object",
      "default": "—",
      "desc": "Seed values"
    },
    {
      "name": "onFinish",
      "type": "(values) => void",
      "default": "—",
      "desc": "Fires on a valid submit"
    },
    {
      "name": "disabled",
      "type": "boolean",
      "default": "false",
      "desc": "Disables the whole form"
    }
  ],
  "tokens": [
    "colorPrimary",
    "borderRadius",
    "controlHeight",
    "colorBorder",
    "colorError",
    "Form.labelColor"
  ],
  "spec": [
    {
      "label": "Controls",
      "value": "height 32 · radius 8 · 1px #E3E3E3 border"
    },
    {
      "label": "Label",
      "value": "#4A4A4A, above the field (vertical layout)"
    },
    {
      "label": "Submit",
      "value": "primary Button #6A1EBB"
    },
    {
      "label": "Error",
      "value": "#F5222D border + message below the field"
    },
    {
      "label": "Item gap",
      "value": "20px between items"
    },
    {
      "label": "Size",
      "value": "control height 24 (small) · 32 (default) · 40 (large)"
    },
    {
      "label": "Validation",
      "value": "error / warning / success — coloured border + help text"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Form",
        "when": "two or more related fields submitted together, with validation"
      },
      {
        "what": "a single Input/Select",
        "when": "one value that applies on its own — no submit step"
      },
      {
        "what": "Settings pattern",
        "when": "a settings surface — see the Settings pattern for grouping and spacing"
      }
    ],
    "note": "Label every field with a noun phrase above the control (vertical layout reads best on narrow surfaces). Validate on blur and on submit; show the error below the field with how to fix it. One primary submit per form.",
    "dsv3": "COVERED — antd v6 Form + ant-design-vue v4, one shared formTheme. Matrix: layout {vertical, horizontal, inline} × size {small 24, default 32, large 40} × disabled {off, on}, plus requiredMark and per-Form.Item validation states {error, warning, success} with help text below the field. Verified via Figma search_design_system against the DS V3 Form set (system-form + the Form-Item/* component sets: Input, Textarea, Select, Select-Multiple, Input number, Date-Picker, Checkbox, Radio, Segmented-radio, Switcher — all sized small/default/large with rest/focus/disabled/error states). Sizes cross-checked against the measured contract (inp|sm/md/lg = 24/32/40px, radius 8, error border). The playground exposes layout · size · disabled with a live errored field."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step, no bundler.\n     Form 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 `formTheme` the React/Vue wrappers use, so it renders\n     the DS V3 look (32px controls, radius 8, #E3E3E3 border, brand primary submit).\n     Matrix props: layout (vertical|horizontal|inline) · size (small|default|large) ·\n     disabled · requiredMark · per-Item validation (error|warning|success) + help text.\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, Form, Input, Button } from 'https://esm.sh/antd@6?deps=react@18,react-dom@18';\n  import { formTheme } from 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/form-theme.js';\n\n  const h = React.createElement;\n  const Item = Form.Item;\n\n  createRoot(document.getElementById('root')).render(\n    h(ConfigProvider, { theme: formTheme },\n      h(Form, { layout: 'vertical', size: 'default', disabled: false, requiredMark: true,\n                style: { maxWidth: 360 }, initialValues: { name: 'AhaSlides' }, onFinish: (v) => console.log(v) },\n        h(Item, { label: 'Workspace name', name: 'name', rules: [{ required: true }] }, h(Input, { placeholder: 'AhaSlides' })),\n        // Validation state — error | warning | success — colours the border + shows help text\n        h(Item, { label: 'Contact email', name: 'email', rules: [{ type: 'email', required: true, message: 'Enter a valid email — e.g. you@company.com' }] }, h(Input, { placeholder: 'you@company.com' })),\n        h(Item, null, h(Button, { type: 'primary', htmlType: 'submit' }, 'Save changes'))\n      )\n    )\n  );\n</script>\n",
    "react": "import { ConfigProvider, Form, Input, Button } from 'antd';   // antd v6\nimport { formTheme } from '@ahaslides-product/design/form-theme';\n\n// layout: vertical | horizontal | inline · size: small | default | large · disabled toggles the whole form\n<ConfigProvider theme={formTheme}>\n  <Form layout=\"vertical\" size=\"default\" disabled={false} requiredMark\n        initialValues={{ name: 'AhaSlides' }} onFinish={save}>\n    <Form.Item label=\"Workspace name\" name=\"name\" rules={[{ required: true }]}>\n      <Input placeholder=\"AhaSlides\" />\n    </Form.Item>\n    {/* Validation state — error | warning | success — colours the border + shows help text */}\n    <Form.Item label=\"Contact email\" name=\"email\"\n               rules={[{ type: 'email', required: true, message: 'Enter a valid email — e.g. you@company.com' }]}>\n      <Input placeholder=\"you@company.com\" />\n    </Form.Item>\n    <Form.Item>\n      <Button type=\"primary\" htmlType=\"submit\">Save changes</Button>\n    </Form.Item>\n  </Form>\n</ConfigProvider>\n// One shared formTheme → the DS V3 look; labels above the field, one primary submit.\n",
    "vue": "<script setup>\nimport { reactive } from 'vue';\nimport { ConfigProvider, Form, FormItem, Input, Button } from 'ant-design-vue';   // ant-design-vue v4\nimport { formTheme } from '@ahaslides-product/design/form-theme';\n\nconst model = reactive({ name: 'AhaSlides', email: '' });\n</script>\n\n<!-- layout: vertical | horizontal | inline · size: small | default | large · disabled toggles the whole form -->\n<template>\n  <a-config-provider :theme=\"formTheme\">\n    <a-form layout=\"vertical\" size=\"default\" :disabled=\"false\" required-mark :model=\"model\" @finish=\"save\">\n      <a-form-item label=\"Workspace name\" name=\"name\" :rules=\"[{ required: true }]\">\n        <a-input v-model:value=\"model.name\" placeholder=\"AhaSlides\" />\n      </a-form-item>\n      <!-- Validation state — error | warning | success — colours the border + shows help text -->\n      <a-form-item label=\"Contact email\" name=\"email\"\n                   :rules=\"[{ type: 'email', required: true, message: 'Enter a valid email — e.g. you@company.com' }]\">\n        <a-input v-model:value=\"model.email\" placeholder=\"you@company.com\" />\n      </a-form-item>\n      <a-form-item>\n        <a-button type=\"primary\" html-type=\"submit\">Save changes</a-button>\n      </a-form-item>\n    </a-form>\n  </a-config-provider>\n</template>\n<!-- The SAME formTheme as React → one DS V3 look across both vendor libraries. -->\n",
    "theme": "// @ahaslides-product/design/form-theme — declared ONCE, consumed by both tiers.\nimport { formTheme } from '@ahaslides-product/design/form-theme';\n\nexport const formTheme = {\n  token: {\n    colorPrimary: '#6A1EBB',\n    borderRadius: 8,\n    controlHeight: 32,\n    colorBorder: '#E3E3E3',\n    colorTextPlaceholder: '#8A8A8A',\n    colorError: '#F5222D',\n    fontFamily: 'var(--aha-font-product, \"Plus Jakarta Sans\", sans-serif)',\n  },\n  components: {\n    Form: { labelColor: '#4A4A4A', itemMarginBottom: 20, verticalLabelPadding: '0 0 4px' },\n    Input: { borderRadius: 8, controlHeight: 32 },\n    Button: { borderRadius: 8, controlHeight: 32 },\n  },\n};\n"
  }
}
