{
  "version": "0.2.0-preview.1",
  "content_digest": "70ac710f4d22dce040e7ac593379ba8aca9dcb59a0b9c0f839819cae0e2bb721",
  "status": "preview",
  "authority": {
    "repository": "cloakedinc/design",
    "path": "packages/design-system",
    "catalog": "packages/design-system/catalog.json",
    "status": "preview"
  },
  "provenance": {
    "repo": "cloakedinc/automation",
    "commit": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "path": "packages/design-system",
    "imported_spec_status": "approved"
  },
  "adaptations": [
    {
      "id": "button-content-gap",
      "status": "preview",
      "description": "Use the specification's 4px content gap instead of the inherited 8px implementation gap."
    },
    {
      "id": "keyboard-focus",
      "status": "preview",
      "description": "Add visible Button and Input keyboard focus and an overridable inset focus default for shared button resets, including FAQ cards and ListItem rows."
    },
    {
      "id": "supporting-text-contrast",
      "status": "preview",
      "description": "Map light secondary text to the existing grey-04-strong primitive for readable helper text on white and cream."
    },
    {
      "id": "danger-text-contrast",
      "status": "preview",
      "description": "Separate readable danger text/borders from destructive fills; preserve the primary danger-button fill and label pair."
    },
    {
      "id": "preview-status",
      "status": "preview",
      "description": "Local components, specs and token adaptations await human sign-off; upstream approved status is provenance only."
    },
    {
      "id": "motion-comparison-accessibility",
      "status": "preview",
      "description": "Preserve the original MotionShowcase comparisons while requiring explicit replay, responding to live reduced-motion changes, and keeping duration tracks usable on small screens."
    },
    {
      "id": "list-item-ownership",
      "status": "preview",
      "description": "List owns listitem wrappers for its content rows, while section labels stay outside the row count and standalone rows retain their existing semantics."
    },
    {
      "id": "card-delta-text-contrast",
      "status": "preview",
      "description": "Mix Card.Delta foregrounds from 60% existing tone solid and 40% primary text for readable contrast in both themes; preserve the four original tone fills."
    },
    {
      "id": "carousel-keyboard-access",
      "status": "preview",
      "description": "Keep all native-scrolling carousel slide controls exposed to assistive technology and keyboard navigation; pause autoplay while focus is inside the carousel."
    }
  ],
  "id": "field",
  "name": "Field",
  "category": "Forms",
  "summary": "Own the label, helper text, and error for exactly one form control.",
  "documentation": {
    "summary": "Own the label, helper text, and error for exactly one form control.",
    "when_to_use": [
      "A control needs a visible label or explanatory message.",
      "A validation error should also mark its control invalid.",
      "A field is required or disabled as a unit."
    ],
    "avoid": [
      "Placing two Field-aware controls inside one Field.",
      "Duplicating error text below the Input.",
      "Overriding control IDs or accessible labels without preserving the visible label association."
    ],
    "accessibility": [
      "Field owns stable IDs for its label, description, and control.",
      "An error replaces helper text and is referenced by aria-describedby.",
      "Required markers are decorative; the child receives native required semantics."
    ],
    "constraints": [
      "Compatible controls consume FieldContext at any nesting depth.",
      "Explicit child props take precedence over context values."
    ]
  },
  "source": {
    "path": "packages/design-system/src/components/forms/Field/Field.tsx",
    "code": "import React, { useId, useMemo } from 'react';\nimport { cn } from '../../../utilities';\nimport { Text } from '../../primitives/Text/Text';\nimport { FieldContext } from '../../../hooks/FieldContext';\nimport styles from './Field.module.scss';\n\n/**\n * Props for the label/helper/error wrapper. Field owns the ids that tie the label,\n * helper, and error to the control; a control that sets one itself keeps its own.\n */\nexport interface FieldProps {\n    /** Visible label text, tied to the control by `htmlFor`. Without it (and `action`) no header renders. */\n    label?: string;\n    /** Supporting copy shown below the control when there is no error. */\n    helperText?: string;\n    /**\n     * Error copy shown below the control, announced through aria-describedby, and\n     * published to the control so it paints its own invalid treatment.\n     */\n    error?: string;\n    /** Optional action aligned with the label, e.g. \"Add\" or \"Use current\". */\n    action?: React.ReactNode;\n    /** Adds the required marker and passes `required` to compatible controls. */\n    required?: boolean;\n    /** Passes disabled state to compatible controls. */\n    disabled?: boolean;\n    /**\n     * The one control to wrap. It reads its label, description, and validation wiring from\n     * context, which reaches any depth — so two Field-aware controls under one Field would\n     * both adopt the same DOM id. Give each control its own Field.\n     */\n    children: React.ReactNode;\n    id?: string;\n    className?: string;\n    /** Test id for the wrapper only; the control keeps whatever test id it was given. */\n    testId?: string;\n}\n\n/**\n * Label, helper, and error wrapper for form controls.\n *\n * Field is the only owner of validation copy: setting `error` renders the message here\n * and marks the child control invalid through context, so neither is set twice.\n */\nexport function Field({\n    label,\n    helperText,\n    error,\n    action,\n    required,\n    disabled,\n    children,\n    id,\n    className,\n    testId,\n}: FieldProps) {\n    const generatedId = useId();\n    const controlId = id ?? `${generatedId}-control`;\n    const labelId = label ? `${controlId}-label` : undefined;\n    const helperId = helperText && !error ? `${controlId}-helper` : undefined;\n    const errorId = error ? `${controlId}-error` : undefined;\n    const describedBy = [helperId, errorId].filter(Boolean).join(' ') || undefined;\n    const fieldContext = useMemo(\n        () => ({\n            controlId,\n            labelledBy: labelId,\n            describedBy,\n            invalid: Boolean(error),\n            required,\n            disabled,\n        }),\n        [controlId, labelId, describedBy, error, required, disabled]\n    );\n\n    return (\n        <FieldContext.Provider value={fieldContext}>\n            <div className={cn(styles.field, className)} data-testid={testId}>\n                {(label || action) && (\n                    <div className={styles.header}>\n                        {label && (\n                            <label className={styles.label} htmlFor={controlId} id={labelId}>\n                                <Text variant='body-small' color='primary'>\n                                    {label}\n                                </Text>\n                                {required && (\n                                    <span className={styles.requiredMark} aria-hidden='true'>\n                                        *\n                                    </span>\n                                )}\n                            </label>\n                        )}\n                        {action && <div className={styles.action}>{action}</div>}\n                    </div>\n                )}\n                {children}\n                {helperText && !error && (\n                    <Text variant='body-small' color='secondary' id={helperId}>\n                        {helperText}\n                    </Text>\n                )}\n                {error && (\n                    <Text variant='body-small' color='danger' id={errorId}>\n                        {error}\n                    </Text>\n                )}\n            </div>\n        </FieldContext.Provider>\n    );\n}\n"
  },
  "spec": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "Field",
      "status": "preview",
      "version": "2.0.0",
      "summary": "A form-control wrapper that owns visible labelling, optional label-side action, required state, helper copy, and validation — including the invalid state the child control renders."
    },
    "parts": [
      {
        "id": "root",
        "label": "Root",
        "description": "Stacks header, one compatible control, and one supporting message."
      },
      {
        "id": "header",
        "label": "Header",
        "description": "Aligns the visible label and optional label-side action."
      },
      {
        "id": "label",
        "label": "Label",
        "description": "Provides the persistent visible and programmatic name for the child control."
      },
      {
        "id": "required-mark",
        "label": "Required mark",
        "description": "Visually indicates required input without becoming part of the label text."
      },
      {
        "id": "action",
        "label": "Label-side action",
        "description": "Optional compact action related to the field, such as Add or Use current."
      },
      {
        "id": "control",
        "label": "Child control",
        "description": "Exactly one compatible form control receiving label, message, required, disabled, and invalid wiring."
      },
      {
        "id": "helper-message",
        "label": "Helper message",
        "description": "Supporting copy shown only while there is no error."
      },
      {
        "id": "error-message",
        "label": "Error message",
        "description": "Corrective copy that replaces helper text and marks the control invalid."
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "labelled": {
          "label": "Labelled",
          "description": "One field wrapper whose optional parts are configured independently."
        }
      },
      "sizes": {}
    },
    "variants": [
      {
        "id": "labelled",
        "label": "Labelled",
        "description": "Persistent label and message scaffolding around one compatible form control.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [],
    "measurements": [
      {
        "id": "stack-gap",
        "label": "Field stack gap",
        "kind": "exact",
        "token": "--cds-space-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "root",
          "header",
          "control",
          "helper-message",
          "error-message"
        ]
      },
      {
        "id": "header-gap",
        "label": "Label-to-action minimum gap",
        "kind": "exact",
        "token": "--cds-space-12",
        "value": 12,
        "unit": "px",
        "appliesTo": [
          "header",
          "label",
          "action"
        ]
      },
      {
        "id": "required-mark-gap",
        "label": "Label-to-required-mark gap",
        "kind": "exact",
        "token": "--cds-space-4",
        "value": 4,
        "unit": "px",
        "appliesTo": [
          "label",
          "required-mark"
        ]
      }
    ],
    "layout": {
      "alignment": "Label begins at the control edge while a label-side action remains trailing; messages align with the control.",
      "flow": "Optional header, exactly one child control, then either helper or error copy.",
      "notes": [
        "Use Field whenever a control needs a persistent visible label, supporting message, or validation; the label itself is optional.",
        "Do not place multiple controls under one Field instance."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Label and messages",
          "description": "Use body-small text for labels, helpers, and validation copy.",
          "token": "--cds-type-body-small-size"
        }
      ],
      "colors": [
        {
          "label": "Label",
          "description": "Use primary text emphasis for the persistent label.",
          "token": "--cds-text-primary"
        },
        {
          "label": "Helper",
          "description": "Use secondary emphasis for non-critical supporting copy.",
          "token": "--cds-text-secondary"
        },
        {
          "label": "Required and error",
          "description": "Use the readable semantic danger role for error indication in both themes.",
          "token": "--cds-text-danger"
        }
      ]
    },
    "states": [
      {
        "id": "default",
        "label": "Default",
        "description": "Shows the label and child control without supporting copy."
      },
      {
        "id": "helper",
        "label": "Helper",
        "description": "Associates non-critical supporting copy with the control."
      },
      {
        "id": "required",
        "label": "Required",
        "description": "Shows the visual mark and forwards required semantics."
      },
      {
        "id": "error",
        "label": "Error",
        "description": "Replaces helper copy, associates the error, and puts the child control into its invalid treatment."
      },
      {
        "id": "disabled",
        "label": "Disabled",
        "description": "Forwards disabled state while retaining label and supporting context."
      }
    ],
    "behavior": [
      {
        "label": "Child wiring",
        "description": "Publish id, disabled, required, labelled-by, described-by, and invalid to the child control, which fills in only the values it does not set itself."
      },
      {
        "label": "Invalid propagation",
        "description": "Publish invalid state to the child control so the control renders its own invalid treatment without the caller setting the error twice. A control that sets invalid itself keeps its own value. The wiring travels by context, so it still reaches a control nested inside a wrapper component."
      },
      {
        "label": "Message precedence",
        "description": "Show and associate error copy instead of helper copy whenever an error is present."
      },
      {
        "label": "Label-side action",
        "description": "Keep the optional action separate from the child control and give the action its own name and test identifier."
      }
    ],
    "accessibility": [
      {
        "label": "Persistent name",
        "description": "Bind the visible label to the child control through id and labelled-by relationships."
      },
      {
        "label": "Message relationship",
        "description": "Associate the one visible helper or error message through described-by."
      },
      {
        "label": "Required mark",
        "description": "Hide the decorative asterisk from assistive technology and forward required state to the control."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Long labels",
        "description": "Allow the label to wrap while preserving space for a compact trailing action."
      },
      {
        "label": "Corrective errors",
        "description": "Write errors as specific correction guidance rather than repeating the label."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "Message replacement",
          "description": "Helper and error copy may replace one another without animating or moving the child control independently."
        }
      ],
      "haptics": [
        {
          "label": "No intrinsic feedback",
          "description": "Field owns no interaction; the child control and label-side action own their haptics."
        }
      ]
    },
    "platformDifferences": [
      {
        "platforms": [
          "web"
        ],
        "description": "Web associates the label and messages with DOM id and ARIA references; native implementations use platform accessibility labels, values, hints, and errors.",
        "rationale": "The visible hierarchy is shared while each platform uses its native form relationship APIs."
      }
    ]
  },
  "spec_source": "packages/design-system/src/components/forms/Field/Field.spec.json",
  "guidance_source": {
    "path": "packages/design-system/src/components/forms/Field/Field.mdx",
    "code": "import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';\nimport { ComponentSpec, UsageTable, Do, Dont, Compare } from '../../../../.storybook/blocks';\nimport * as Stories from './Field.stories';\nimport fieldSpec from './Field.spec.json';\n\n<Meta of={Stories} />\n\n# Field\n\nThe label, helper, and error wrapper around one form control. Field renders no text\nbox of its own — it decorates an `Input`, `Textarea`, `Select`, `DatePicker`, or\n`RadioGroup` and owns everything around it.\n\n<Canvas of={Stories.Playground} />\n\n## Use when\n\nField draws the label and the message; the control draws itself. Setting `error`\ndoes both jobs at once: it renders the copy and marks the child invalid through\ncontext, so the control paints its own red ring. You never set the error twice.\nContext only fills in what the control leaves unset: a control that passes its own\n`invalid` keeps it, so `invalid={false}` opts out of the Field's ring.\n\n<UsageTable\n    axis='You need'\n    rows={[\n        {\n            variant: 'label',\n            use: 'A persistent visible label above the control, tied to it by htmlFor.',\n            avoid: 'A placeholder standing in for a label — it vanishes as soon as the user types.',\n        },\n        {\n            variant: 'error',\n            use: 'Validation copy, plus the invalid treatment on the control. This is the only place errors are set.',\n            avoid: 'A hand-rolled Text below a bare control — nothing wires it to the input.',\n        },\n        {\n            variant: 'helperText',\n            use: 'Supporting copy that explains the field. Replaced by error while one is present.',\n        },\n        {\n            variant: 'required',\n            use: 'The * marker plus forwarded required semantics.',\n        },\n        {\n            variant: 'action',\n            use: 'A compact action on the label row, such as \"Add\" or \"Use current\".',\n        },\n    ]}\n/>\n\n`helperText` and `error` are mutually exclusive: an error replaces the helper.\n\n`label` is optional. Drop it — but keep the Field — when the control already names\nitself elsewhere on the screen and you still want its error wired up. That is what\nthe SSN field and the inbox compose sheet do.\n\n<Canvas of={Stories.WithoutLabel} />\n\nSkip Field entirely only when there is no label and no message to attach: a toolbar\nsearch box, an inline cell editor. Pass `ariaLabel` on the control instead of\nwrapping it in an empty Field.\n\n## Do / Don't\n\n<Compare>\n    <Do caption='One error, on the Field. The ring and the message cannot drift apart.'>\n        <Canvas of={Stories.DoFieldOwnsError} sourceState='none' />\n    </Do>\n    <Dont caption='A loose Text under a bare Input looks right and is wired to nothing.'>\n        <Canvas of={Stories.DontHandRollTheMessage} sourceState='none' />\n    </Dont>\n</Compare>\n\n## States\n\n<Canvas of={Stories.StateMatrix} />\n\n## Accessibility\n\nField owns the ids. It publishes `id`, `aria-labelledby`, `aria-describedby`, and\ninvalid state through context, and every Field-compatible control reads them. A control\nthat sets one itself keeps its own. Because the wiring travels by context rather than by\ncloning the child, it still reaches a control nested inside a wrapper component.\n\nTwo rules the wiring depends on:\n\n-   **One control per Field.** The ids assume a single control reads them.\n-   **Don't pass `ariaLabel` to a control that already has a visible label** — the\n    accessible name would then omit the text the user can see.\n\n## Dark theme\n\n<Canvas of={Stories.DarkTheme} />\n\n## Design Guidelines\n\n<ComponentSpec spec={fieldSpec} />\n\n## Props\n\n<Controls of={Stories.Playground} />\n"
  },
  "props": [
    {
      "name": "label",
      "type": "string",
      "required": false,
      "description": "Visible label text, tied to the control by `htmlFor`. Without it (and `action`) no header renders."
    },
    {
      "name": "helperText",
      "type": "string",
      "required": false,
      "description": "Supporting copy shown below the control when there is no error."
    },
    {
      "name": "error",
      "type": "string",
      "required": false,
      "description": "Error copy shown below the control, announced through aria-describedby, and\npublished to the control so it paints its own invalid treatment."
    },
    {
      "name": "action",
      "type": "React.ReactNode",
      "required": false,
      "description": "Optional action aligned with the label, e.g. \"Add\" or \"Use current\"."
    },
    {
      "name": "required",
      "type": "boolean",
      "required": false,
      "description": "Adds the required marker and passes `required` to compatible controls."
    },
    {
      "name": "disabled",
      "type": "boolean",
      "required": false,
      "description": "Passes disabled state to compatible controls."
    },
    {
      "name": "children",
      "type": "React.ReactNode",
      "required": true,
      "description": "The one control to wrap. It reads its label, description, and validation wiring from\ncontext, which reaches any depth — so two Field-aware controls under one Field would\nboth adopt the same DOM id. Give each control its own Field."
    },
    {
      "name": "id",
      "type": "string",
      "required": false,
      "description": ""
    },
    {
      "name": "className",
      "type": "string",
      "required": false,
      "description": ""
    },
    {
      "name": "testId",
      "type": "string",
      "required": false,
      "description": "Test id for the wrapper only; the control keeps whatever test id it was given."
    }
  ],
  "prop_shapes": {},
  "examples": [
    {
      "id": "input-playground",
      "title": "Field and Input playground",
      "source": "packages/design-system/examples/InputPlayground.tsx",
      "export": "InputPlayground",
      "components": [
        "field",
        "input"
      ],
      "description": "A real controlled input with a connected label, helper text, error and disabled state.",
      "synthetic_data": true,
      "storybook_id": "components-field-and-input--playground",
      "code": "import { useState } from 'react';\nimport { Field, Input } from '../src';\nimport { DemoFrame, SelectControl } from './DemoFrame';\nimport { inputExampleCode, type InputExampleProps } from './code';\n\nexport function InputPlayground() {\n  const [email, setEmail] = useState('');\n  const [size, setSize] = useState<InputExampleProps['size']>('md');\n  const [state, setState] = useState<InputExampleProps['state']>('default');\n  const error = state === 'invalid' ? 'Enter an email address, such as name@example.com.' : undefined;\n  return <DemoFrame code={inputExampleCode({ size, state })} controls={<>\n    <SelectControl label=\"Size\" value={size} options={['md', 'sm']} onChange={value => setSize(value as InputExampleProps['size'])} />\n    <SelectControl label=\"State\" value={state} options={['default', 'invalid', 'disabled']} onChange={value => setState(value as InputExampleProps['state'])} />\n  </>}>\n    <div className=\"demo-input-stage\">\n      <Field label=\"Email address\" helperText=\"Use the address you check regularly.\" error={error} disabled={state === 'disabled'}>\n        <Input type=\"email\" size={size} value={email} onChange={setEmail} autoComplete=\"email\" />\n      </Field>\n    </div>\n  </DemoFrame>;\n}\n"
    },
    {
      "id": "protected-email-flow",
      "title": "Create a protected email",
      "source": "packages/design-system/examples/ProtectedEmailFlow.tsx",
      "export": "ProtectedEmailFlow",
      "components": [
        "button",
        "field",
        "input"
      ],
      "description": "A local-only sample flow with validation, loading, success and restart. No data is sent or saved.",
      "synthetic_data": true,
      "storybook_id": "patterns-protected-email--create",
      "code": "import { useEffect, useLayoutEffect, useRef, useState, type FormEvent } from 'react';\nimport { Button, Field, Input } from '../src';\nimport { DemoFrame } from './DemoFrame';\nimport { createSampleIdentity, validateIdentity, type IdentityDraft, type IdentityErrors } from './protected-email';\n\nconst EMPTY_DRAFT: IdentityDraft = { name: '', website: '' };\n\nexport function ProtectedEmailFlow() {\n  const [draft, setDraft] = useState<IdentityDraft>(EMPTY_DRAFT);\n  const [errors, setErrors] = useState<IdentityErrors>({});\n  const [stage, setStage] = useState<'editing' | 'loading' | 'success'>('editing');\n  const form = useRef<HTMLFormElement>(null);\n  const success = useRef<HTMLHeadingElement>(null);\n  useEffect(() => {\n    if (stage !== 'loading') return;\n    const timer = window.setTimeout(() => setStage('success'), 700);\n    return () => window.clearTimeout(timer);\n  }, [stage]);\n  useEffect(() => { if (stage === 'success') success.current?.focus(); }, [stage]);\n  useLayoutEffect(() => {\n    if (Object.keys(errors).length) form.current?.querySelector<HTMLInputElement>('[aria-invalid=\"true\"]')?.focus();\n  }, [errors]);\n  const restart = () => {\n    setDraft(EMPTY_DRAFT); setErrors({}); setStage('editing');\n    requestAnimationFrame(() => form.current?.querySelector<HTMLInputElement>('input')?.focus());\n  };\n  const submit = (event: FormEvent) => {\n    event.preventDefault();\n    if (stage !== 'editing') return;\n    const nextErrors = validateIdentity(draft);\n    setErrors(nextErrors);\n    if (Object.keys(nextErrors).length) return;\n    setStage('loading');\n  };\n  return <DemoFrame><section className=\"demo-flow\" aria-label=\"Create a protected email example\">\n    <p className=\"demo-sample-note\">Interactive example · Sample data only. Nothing is sent or saved.</p>\n    {stage === 'success' ? <FlowSuccess draft={draft} headingRef={success} restart={restart} /> :\n      <form ref={form} noValidate onSubmit={submit} aria-busy={stage === 'loading'}>\n        <FlowHeading />\n        <FlowFields draft={draft} errors={errors} loading={stage === 'loading'} change={setDraft} submit={() => form.current?.requestSubmit()} />\n        <Button variant=\"primary\" size=\"md\" fullWidth loading={stage === 'loading'} onPress={() => form.current?.requestSubmit()}>Create protected email</Button>\n        <p className=\"demo-feedback\" role=\"status\">{stage === 'loading' ? 'Creating your sample address…' : 'Your personal email stays yours.'}</p>\n      </form>}\n  </section></DemoFrame>;\n}\n\nfunction FlowHeading() {\n  return <div className=\"demo-flow-heading\">\n    <span className=\"demo-symbol\" aria-hidden=\"true\">@</span>\n    <span className=\"demo-eyebrow\">A little more privacy</span>\n    <h2>An email for this part of your life.</h2>\n    <p>Give it a name so you know where you used it.</p>\n  </div>;\n}\n\nfunction FlowFields({ draft, errors, loading, change, submit }: {\n  draft: IdentityDraft; errors: IdentityErrors; loading: boolean;\n  change: (draft: IdentityDraft) => void; submit: () => void;\n}) {\n  return <div className=\"demo-flow-fields\">\n    <Field label=\"Name\" helperText=\"For example, shopping or a newsletter.\" error={errors.name} required disabled={loading}>\n      <Input value={draft.name} onChange={name => change({ ...draft, name })} placeholder=\"Shopping\"\n        name=\"identity-name\" autoComplete=\"off\" maxLength={80} enterKeyHint=\"next\" />\n    </Field>\n    <Field label=\"Website (optional)\" helperText=\"A reminder of where you'll use this address.\" error={errors.website} disabled={loading}>\n      <Input value={draft.website} onChange={website => change({ ...draft, website })} placeholder=\"example.com\"\n        name=\"identity-website\" autoComplete=\"off\" inputMode=\"url\" autoCapitalize=\"none\" maxLength={200}\n        enterKeyHint=\"done\" enterBehavior=\"callback\" onEnter={submit} />\n    </Field>\n  </div>;\n}\n\nfunction FlowSuccess({ draft, headingRef, restart }: {\n  draft: IdentityDraft; headingRef: React.RefObject<HTMLHeadingElement>; restart: () => void;\n}) {\n  const identity = createSampleIdentity(draft);\n  return <div className=\"demo-flow-success\">\n    <span className=\"demo-symbol demo-symbol-success\" aria-hidden=\"true\">✓</span>\n    <span className=\"demo-eyebrow\">Ready to use</span>\n    <h2 ref={headingRef} tabIndex={-1}>A fresh address for {identity.name}.</h2>\n    <p>This sample address demonstrates the result. It cannot receive email.</p>\n    <div className=\"demo-email-result\"><span>Protected email</span><strong>{identity.email}</strong></div>\n    <Button variant=\"secondary\" size=\"md\" fullWidth onPress={restart}>Try the flow again</Button>\n  </div>;\n}\n"
    },
    {
      "id": "foundation-surfaces",
      "title": "Surfaces",
      "source": "packages/design-system/examples/foundations/FoundationSurfaces.tsx",
      "export": "FoundationSurfaces",
      "components": [
        "field",
        "input"
      ],
      "description": "Theme-aware page, card, and real Input layers plus an appropriately paired inverse surface.",
      "synthetic_data": true,
      "storybook_id": "foundations-surfaces--explore",
      "code": "import { useState } from 'react';\nimport { Field, Input, Text } from '../../src';\nimport { FoundationFrame } from './FoundationShared';\n\nexport function FoundationSurfaces() {\n  const [name, setName] = useState('Shopping');\n  return <FoundationFrame code={`const page = { background: 'var(--cds-bg-page)', color: 'var(--cds-text-primary)' };\\nconst card = { background: 'var(--cds-bg-surface)' };\\nconst inverse = { background: 'var(--cds-bg-inverse)', color: 'var(--cds-text-inverse)' };`}>\n    <div className=\"foundation-surface-page\">\n      <code>--cds-bg-page</code>\n      <div className=\"foundation-surface-card\">\n        <code>--cds-bg-surface</code>\n        <Text as=\"h2\" variant=\"h3-serif\">Give your address a home.</Text>\n        <Field label=\"Address name\" helperText=\"A useful label makes it easier to find later.\">\n          <Input value={name} onChange={setName} placeholder=\"Shopping\" autoComplete=\"off\" />\n        </Field>\n        <code>Input → --cds-input-container</code>\n      </div>\n    </div>\n    <div className=\"foundation-surface-inverse\" data-testid=\"surface-inverse\" style={{ background: 'var(--cds-bg-inverse)', color: 'var(--cds-text-inverse)' }}>\n      <div><span className=\"demo-eyebrow\">A deliberate change of context</span><Text as=\"h2\" variant=\"h3-serif\">Private feels different.</Text></div>\n      <code>--cds-bg-inverse + --cds-text-inverse</code>\n    </div>\n    <p className=\"foundation-caption\">Page, card, and input surfaces adapt to the selected theme. An inverse surface stays dark and keeps its own light foreground in both themes.</p>\n  </FoundationFrame>;\n}\n"
    }
  ],
  "tokens": [
    {
      "name": "--cds-space-8",
      "light": "8px",
      "dark": "8px"
    },
    {
      "name": "--cds-space-12",
      "light": "12px",
      "dark": "12px"
    },
    {
      "name": "--cds-space-4",
      "light": "4px",
      "dark": "4px"
    },
    {
      "name": "--cds-type-body-small-size",
      "light": "0.875rem",
      "dark": "0.875rem"
    },
    {
      "name": "--cds-text-primary",
      "light": "#141410",
      "dark": "#f3f1ed"
    },
    {
      "name": "--cds-text-secondary",
      "light": "#646260",
      "dark": "#ffffff99"
    },
    {
      "name": "--cds-text-danger",
      "light": "#b83100",
      "dark": "color-mix(in srgb, #b83100 60%, #ffffff)"
    }
  ],
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-forms-field--playground",
        "name": "Playground",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "Playground",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--playground&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--with-helper-text",
        "name": "With Helper Text",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "WithHelperText",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-helper-text&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--with-action",
        "name": "With Action",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "WithAction",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-action&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--with-error",
        "name": "With Error",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "WithError",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-error&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--without-label",
        "name": "Without Label",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "WithoutLabel",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--without-label&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--do-field-owns-error",
        "name": "Do Field Owns Error",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "DoFieldOwnsError",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--do-field-owns-error&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--dont-hand-roll-the-message",
        "name": "Dont Hand Roll The Message",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "DontHandRollTheMessage",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--dont-hand-roll-the-message&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--required",
        "name": "Required",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "Required",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--required&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--disabled",
        "name": "Disabled",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "Disabled",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--disabled&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--state-matrix",
        "name": "State Matrix",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "StateMatrix",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--state-matrix&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--long-label-and-helper",
        "name": "Long Label And Helper",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "LongLabelAndHelper",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--long-label-and-helper&viewMode=story"
      },
      {
        "id": "cloaked-design-system-forms-field--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Forms/Field",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
        "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--dark-theme&viewMode=story"
      }
    ],
    "name": "Field",
    "id": "field",
    "category": "Forms"
  },
  "stories": [
    {
      "id": "cloaked-design-system-forms-field--playground",
      "name": "Playground",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "Playground",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--playground&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--with-helper-text",
      "name": "With Helper Text",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "WithHelperText",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-helper-text&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--with-action",
      "name": "With Action",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "WithAction",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-action&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--with-error",
      "name": "With Error",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "WithError",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--with-error&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--without-label",
      "name": "Without Label",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "WithoutLabel",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--without-label&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--do-field-owns-error",
      "name": "Do Field Owns Error",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "DoFieldOwnsError",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--do-field-owns-error&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--dont-hand-roll-the-message",
      "name": "Dont Hand Roll The Message",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "DontHandRollTheMessage",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--dont-hand-roll-the-message&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--required",
      "name": "Required",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "Required",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--required&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--disabled",
      "name": "Disabled",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "Disabled",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--disabled&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--state-matrix",
      "name": "State Matrix",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "StateMatrix",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--state-matrix&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--long-label-and-helper",
      "name": "Long Label And Helper",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "LongLabelAndHelper",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--long-label-and-helper&viewMode=story"
    },
    {
      "id": "cloaked-design-system-forms-field--dark-theme",
      "name": "Dark Theme",
      "title": "Cloaked Design System/Forms/Field",
      "exportName": "DarkTheme",
      "source_path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
      "source_digest": "daffd21dfde07251f850f0a6b8a09bb7d45935278540f188cc4a70b06e0564f2",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-forms-field--dark-theme&viewMode=story"
    }
  ],
  "stories_source": {
    "path": "packages/design-system/src/components/forms/Field/Field.stories.tsx",
    "code": "import React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { Input } from '../../primitives/Input/Input';\nimport { Button } from '../../primitives/Button/Button';\nimport { Text } from '../../primitives/Text/Text';\nimport { disabledControl } from '../../../storybook/controlOptions';\nimport { Field } from './Field';\n\nconst meta: Meta<typeof Field> = {\n    title: 'Cloaked Design System/Forms/Field',\n    component: Field,\n    parameters: {\n        a11y: { test: 'error' },\n        stage: 'form-control',\n        docs: {\n            description: {\n                component:\n                    'The label + validation wrapper for a single form control, and the only owner of ' +\n                    'validation copy. Wrap `Input`, `Textarea`, `Select`, `DatePicker`, or `RadioGroup` and ' +\n                    'Field owns the visible `label`, the `*` required marker, `helperText`, and `error` — ' +\n                    'wiring `id`/`aria-describedby`/`aria-invalid` onto the child so screen readers announce ' +\n                    'them together. Setting `error` also marks the child invalid through context, so `Input` ' +\n                    'paints its red ring without the caller setting the error twice. `helperText` and `error` ' +\n                    'are mutually exclusive: an `error` replaces the helper text. `label` is optional — a ' +\n                    'label-less Field is the way to attach an error to a control that names itself.',\n            },\n        },\n    },\n    decorators: [\n        Story => (\n            <div style={{ width: '100%', maxWidth: 354 }}>\n                <Story />\n            </div>\n        ),\n    ],\n    args: {\n        label: 'Email',\n        children: <Input value='' type='email' testId='field-email' />,\n    },\n    argTypes: {\n        children: {\n            ...disabledControl,\n            description: 'The single form control to wrap; Field clones it to inject id and aria wiring.',\n        },\n        action: {\n            ...disabledControl,\n            description: 'Optional control aligned to the right of the label, e.g. an \"Add\" or \"Use current\" Button.',\n        },\n        label: { control: 'text', description: 'Visible label text rendered above the control.' },\n        helperText: {\n            control: 'text',\n            description: 'Supporting copy shown below the control. Hidden while an `error` is present.',\n        },\n        error: {\n            control: 'text',\n            description: 'Validation message shown below the control; replaces `helperText` and sets `aria-invalid`.',\n        },\n        required: { control: 'boolean', description: 'Adds the `*` marker and forwards `required` to the control.' },\n        disabled: { control: 'boolean', description: 'Forwards the disabled state to the wrapped control.' },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof Field>;\n\nexport const Playground: Story = {};\n\nexport const WithHelperText: Story = {\n    parameters: {\n        docs: { description: { story: 'Helper text sits below the control and clears once an error appears.' } },\n    },\n    args: {\n        label: 'Phone number',\n        helperText: 'Used only for account recovery.',\n        children: <Input value='' type='tel' testId='field-phone' />,\n    },\n};\n\nexport const WithAction: Story = {\n    parameters: {\n        docs: { description: { story: 'A label-row action (here an \"Add\" link) for repeatable or shortcut fields.' } },\n    },\n    args: {\n        label: 'Names',\n        action: (\n            <Button variant='link' size='sm' onPress={() => {}} testId='field-add-name'>\n                Add\n            </Button>\n        ),\n        children: <Input value='' placeholder='Legal name' testId='field-name' />,\n    },\n};\n\nexport const WithError: Story = {\n    parameters: {\n        docs: {\n            description: { story: 'An `error` replaces helper text and flags the control invalid to assistive tech.' },\n        },\n    },\n    args: {\n        label: 'Password',\n        error: 'Password is required.',\n        children: <Input value='' type='password' testId='field-password' />,\n    },\n};\n\nexport const WithoutLabel: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'Omit `label` to attach an error to a control that already names itself elsewhere on the screen.',\n            },\n        },\n    },\n    args: {\n        label: undefined,\n        error: 'Enter a 9-digit number.',\n        children: <Input value='123' ariaLabel='Social security number' testId='field-unlabelled' />,\n    },\n};\n\nexport const DoFieldOwnsError: Story = {\n    parameters: {\n        docs: { description: { story: 'One `error`, on the Field. The ring and the message stay in step.' } },\n    },\n    args: {\n        label: 'Zip code',\n        error: 'Enter a 5-digit zip code.',\n        children: <Input value='021' testId='field-do-error' />,\n    },\n};\n\nexport const DontHandRollTheMessage: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'A loose Text below a bare Input looks the same and is not wired to it: no red ring, no aria-describedby.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={8}>\n            <Input value='021' ariaLabel='Zip code' testId='field-dont-error' />\n            <Text variant='body-small' color='danger'>\n                Enter a 5-digit zip code.\n            </Text>\n        </VStack>\n    ),\n};\n\nexport const Required: Story = {\n    parameters: {\n        docs: { description: { story: 'The `*` marker plus forwarded `required` for native form semantics.' } },\n    },\n    args: {\n        label: 'Recovery email',\n        required: true,\n        children: <Input value='' type='email' testId='field-recovery-email' />,\n    },\n};\n\nexport const Disabled: Story = {\n    parameters: { docs: { description: { story: 'Disabled state forwarded from the wrapper onto the control.' } } },\n    args: {\n        label: 'Disabled field',\n        disabled: true,\n        helperText: 'This field cannot be edited right now.',\n        children: <Input value='Locked value' testId='field-disabled' />,\n    },\n};\n\nexport const StateMatrix: Story = {\n    parameters: {\n        docs: {\n            description: { story: 'Default, required, helper, error, and disabled fields stacked for comparison.' },\n        },\n    },\n    render: () => (\n        <VStack gap={16}>\n            <Field label='Default'>\n                <Input value='' testId='field-matrix-default' />\n            </Field>\n            <Field label='Required' required>\n                <Input value='' testId='field-matrix-required' />\n            </Field>\n            <Field label='With helper text' helperText='Used only for account recovery.'>\n                <Input value='' testId='field-matrix-helper' />\n            </Field>\n            <Field label='With error' error='Enter a valid value.'>\n                <Input value='Invalid value' testId='field-matrix-error' />\n            </Field>\n            <Field label='Disabled' disabled helperText='This field cannot be edited right now.'>\n                <Input value='Locked value' testId='field-matrix-disabled' />\n            </Field>\n        </VStack>\n    ),\n};\n\nexport const LongLabelAndHelper: Story = {\n    parameters: {\n        docs: { description: { story: 'Long label and helper copy stay attached to the control on narrow screens.' } },\n    },\n    args: {\n        label: 'A longer field label that wraps on small mobile screens',\n        helperText: 'Long helper text should remain readable and stay attached to its control.',\n        children: <Input value='' testId='field-long' />,\n    },\n};\n\nexport const DarkTheme: Story = {\n    globals: { theme: 'dark' },\n    parameters: { docs: { description: { story: 'Label, helper, and error tokens rendered on the dark theme.' } } },\n    args: {\n        label: 'Recovery email',\n        error: 'Enter a valid email.',\n        children: <Input value='invalid' type='email' testId='field-dark' />,\n    },\n};\n"
  },
  "platforms": {
    "implemented": [
      "web"
    ],
    "native": "Imported design guidance only; no native implementation or parity verification in this preview.",
    "react": {
      "implementation": "local",
      "status": "preview",
      "parity": "web-reference"
    },
    "vue": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "swift": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "kotlin": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    }
  },
  "links": {
    "human": "/component-field",
    "json": "/data/components/field.json",
    "markdown": "/data/components/field.md",
    "storybook": "/storybook/?path=/story/cloaked-design-system-forms-field--playground"
  },
  "contract_status": "preview",
  "contract_kind": "curated",
  "approval": "required",
  "api": {
    "method": "typescript-type-checker",
    "typescript_version": "5.9.3",
    "public_export": "Field",
    "public_path": "Field",
    "import_path": "@cloakedinc/design-system",
    "root_kind": "component",
    "entrypoints": [
      {
        "name": "Field",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/forms/Field/Field.tsx",
          "line": 45
        },
        "props_type": "FieldProps",
        "props": [
          {
            "name": "label",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Visible label text, tied to the control by `htmlFor`. Without it (and `action`) no header renders.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 13
            }
          },
          {
            "name": "helperText",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Supporting copy shown below the control when there is no error.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 15
            }
          },
          {
            "name": "error",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Error copy shown below the control, announced through aria-describedby, and\npublished to the control so it paints its own invalid treatment.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 20
            }
          },
          {
            "name": "action",
            "type": "React.ReactNode",
            "declared_type": "React.ReactNode",
            "required": false,
            "description": "Optional action aligned with the label, e.g. \"Add\" or \"Use current\".",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 22
            }
          },
          {
            "name": "required",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Adds the required marker and passes `required` to compatible controls.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 24
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "disabled",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Passes disabled state to compatible controls.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 26
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "children",
            "type": "React.ReactNode",
            "declared_type": "React.ReactNode",
            "required": true,
            "description": "The one control to wrap. It reads its label, description, and validation wiring from\ncontext, which reaches any depth — so two Field-aware controls under one Field would\nboth adopt the same DOM id. Give each control its own Field.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 32
            }
          },
          {
            "name": "id",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 33
            }
          },
          {
            "name": "className",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 34
            }
          },
          {
            "name": "testId",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Test id for the wrapper only; the control keeps whatever test id it was given.",
            "source": {
              "path": "packages/design-system/src/components/forms/Field/Field.tsx",
              "line": 36
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      }
    ],
    "type_sources": [
      {
        "path": "packages/design-system/src/components/forms/Field/Field.tsx",
        "line": 11,
        "name": "FieldProps",
        "code": "export interface FieldProps {\n    /** Visible label text, tied to the control by `htmlFor`. Without it (and `action`) no header renders. */\n    label?: string;\n    /** Supporting copy shown below the control when there is no error. */\n    helperText?: string;\n    /**\n     * Error copy shown below the control, announced through aria-describedby, and\n     * published to the control so it paints its own invalid treatment.\n     */\n    error?: string;\n    /** Optional action aligned with the label, e.g. \"Add\" or \"Use current\". */\n    action?: React.ReactNode;\n    /** Adds the required marker and passes `required` to compatible controls. */\n    required?: boolean;\n    /** Passes disabled state to compatible controls. */\n    disabled?: boolean;\n    /**\n     * The one control to wrap. It reads its label, description, and validation wiring from\n     * context, which reaches any depth — so two Field-aware controls under one Field would\n     * both adopt the same DOM id. Give each control its own Field.\n     */\n    children: React.ReactNode;\n    id?: string;\n    className?: string;\n    /** Test id for the wrapper only; the control keeps whatever test id it was given. */\n    testId?: string;\n}"
      }
    ],
    "defaults_policy": "Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source."
  },
  "missing_facts": [
    {
      "code": "human-review-pending",
      "detail": "This local preview has no recorded human design or engineering sign-off."
    },
    {
      "code": "platform-parity-unverified",
      "detail": "Vue, Swift and Kotlin implementations are absent from this package; platform parity has not been verified."
    },
    {
      "code": "figma-mapping-unverified",
      "detail": "No current component-level Figma node and immutable revision have been verified for this contract."
    }
  ],
  "review": {
    "local_status": "not-reviewed",
    "source_approval": null,
    "imported_spec_status": "approved",
    "spec_origin": "imported-adapted",
    "local_spec_source_status": "preview",
    "imported_source_revision": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "note": "Inherited specification status is provenance, not approval of the current local implementation or extracted contract."
  }
}
