{
  "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": "dialog",
  "name": "Dialog",
  "category": "Overlays",
  "summary": "A controlled alert dialog for explicit decisions, with slotted title and supporting-copy parts, a required primary action, an optional safe secondary action, and an optional transient error region.",
  "documentation": {
    "summary": "A controlled alert dialog for explicit decisions, with slotted title and supporting-copy parts, a required primary action, an optional safe secondary action, and an optional transient error region.",
    "guidance": [
      {
        "heading": "Overview",
        "body": "A controlled confirmation surface for decisions that require an explicit action.\nA title slot, a body slot, and a primary action are required. Add a secondary\nsafe action when the context needs one."
      },
      {
        "heading": "Composition",
        "body": "Copy is slotted, not passed as props. `Dialog.Title` and each `Dialog.Description`\ntake plain strings, so a dialog can carry several paragraphs without the surface\naccepting arbitrary markup.\n\n```tsx\n<Dialog isOpen={isOpen} testId='chat-disable-dialog' primaryAction={confirm} secondaryAction={cancel}>\n    <Dialog.Title>Turn off the assistant?</Dialog.Title>\n    <Dialog.Body>\n        <Dialog.Description color='secondary'>We'll immediately delete every chat.</Dialog.Description>\n        <Dialog.Description>Once deleted, this cannot be recovered.</Dialog.Description>\n    </Dialog.Body>\n</Dialog>\n```\n\nHierarchy comes from color and order, not weight: `color='secondary'` drops the\nsupporting paragraphs back so the one consequence the reader must not skim past\nkeeps primary text and sits last, directly above the actions. There is no bold\nparagraph to reach for — a `<strong>` tag would inherit the user-agent 700 and a\nshared emphasis variant would be reachable from anywhere.\n\nThe actions stay props on purpose. Their order, focus, and tone are the alert\ngrammar this component exists to enforce, so they are not open to composition.\n`Dialog.Body` owns the `aria-describedby` target, which keeps the accessible\ndescription to the copy and excludes the title."
      },
      {
        "heading": "Behavior",
        "body": "`Dialog` does not dismiss from the backdrop or Escape. The caller owns `isOpen`\nand closes it from an action callback. Focus moves to an enabled secondary\naction, or to the dialog itself when no safe action is available, and returns to\nthe launcher after the close animation.\n\nPass `error` when the last action attempt failed. It renders in a `role=\"alert\"`\nregion below the copy and stays out of `aria-describedby`, so a retryable message\nis announced once rather than joining the dialog's standing description."
      }
    ],
    "usage": [
      {
        "variant": "Two actions",
        "use": "The user can safely cancel or confirm. The enabled secondary action receives initial focus.",
        "axis": "Configuration"
      },
      {
        "variant": "Primary only",
        "use": "The user only needs to acknowledge a completed or informational state.",
        "avoid": "High-risk actions where the user needs a clear way to cancel.",
        "axis": "Configuration"
      }
    ],
    "examples": [],
    "source": "packages/design-system/src/components/overlays/Dialog/Dialog.mdx",
    "status": "local-preview",
    "note": "Guidance is read from local documentation, originally imported from the frozen source. Platform assertions in guidance are not parity verification."
  },
  "source": {
    "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
    "code": "import React, { useEffect, useId, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../../utilities';\nimport { HStack } from '../../layout/HStack/HStack';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { useCdsTheme } from '../../../hooks/useCdsTheme';\nimport { Button } from '../../primitives/Button/Button';\nimport { Text } from '../../primitives/Text/Text';\nimport { DialogBody } from './DialogBody';\nimport { DialogContext } from './DialogContext';\nimport { DialogDescription } from './DialogDescription';\nimport { DialogTitle } from './DialogTitle';\nimport type { DialogBodyProps } from './DialogBody';\nimport type { DialogTitleProps } from './DialogTitle';\nimport { useDialogSurface } from './useDialogSurface';\nimport { warnOnUnexpectedSlots } from './warnOnUnexpectedSlots';\nimport styles from './Dialog.module.scss';\n\n/**\n * Required primary action shown on the right when two actions are present.\n */\nexport interface DialogPrimaryAction {\n    label: string;\n    onPress: () => void;\n    /** Use `danger` for irreversible actions. */\n    tone?: 'default' | 'danger';\n    loading?: boolean;\n    disabled?: boolean;\n}\n\n/**\n * Optional safe action shown on the left and focused first when enabled.\n */\nexport interface DialogSecondaryAction {\n    label: string;\n    onPress: () => void;\n    disabled?: boolean;\n}\n\n/**\n * Props for `Dialog`: the controlled open state, the two copy slots, and the action descriptors.\n */\nexport interface DialogProps {\n    /** Presents the surface when true; closing remains mounted until the exit animation completes. */\n    isOpen: boolean;\n    /** The title and body slots, in that order. */\n    children: [React.ReactElement<DialogTitleProps>, React.ReactElement<DialogBodyProps>];\n    /** Required confirming or acknowledging action; it never receives initial focus. */\n    primaryAction: DialogPrimaryAction;\n    /** Optional safe action; when enabled, it receives initial focus. */\n    secondaryAction?: DialogSecondaryAction;\n    /** Transient failure from the last action attempt. Kept out of `aria-describedby`. */\n    error?: string;\n    /** Root selector used to derive slot, action, and overlay test ids. */\n    testId: string;\n    /** Portal mount node. Defaults to `document.body`. */\n    portalTarget?: HTMLElement | null;\n}\n\n/**\n * Renders the modal surface: the slotted copy, an optional error region, and the action row.\n * Reach for it through `Dialog` so the slots are in scope.\n */\nfunction DialogRoot({ isOpen, children, primaryAction, secondaryAction, error, testId, portalTarget }: DialogProps) {\n    const titleId = useId();\n    const descriptionId = useId();\n    const theme = useCdsTheme();\n    const { mounted, open, dialogRef, handleKeyDown } = useDialogSurface(isOpen);\n    const context = useMemo(() => ({ titleId, descriptionId, testId }), [titleId, descriptionId, testId]);\n\n    const secondaryTestId = `${testId}-secondary`;\n    const hasEnabledSecondary = secondaryAction !== undefined && !secondaryAction.disabled;\n\n    // Focus the safe secondary action (or the dialog itself) on open, and restore\n    // focus to the launcher on close. This runs only when `mounted` flips, so it\n    // captures the launcher and target at presentation time — later action-state\n    // changes (loading/disabled) don't re-run it and so can't steal focus.\n    useEffect(() => {\n        if (!mounted) return;\n        const launcher = document.activeElement as HTMLElement | null;\n        // Button takes no ref, so the data-testid it renders is the only handle on the element.\n        const secondaryButton = hasEnabledSecondary\n            ? dialogRef.current?.querySelector<HTMLElement>(`[data-testid=\"${secondaryTestId}\"]`)\n            : undefined;\n        (secondaryButton ?? dialogRef.current)?.focus({ preventScroll: true });\n        return () => launcher?.focus?.({ preventScroll: true });\n        // eslint-disable-next-line react-hooks/exhaustive-deps -- capture focus intent once at presentation; re-running on action-state changes would steal focus\n    }, [mounted, dialogRef]);\n\n    if (!mounted) return null;\n\n    warnOnUnexpectedSlots('Dialog', children, [DialogTitle, DialogBody]);\n\n    // fullWidth only in the single-action layout: in the two-action row the flex container\n    // owns sizing, and width:100% there would force every label onto its own line.\n    const primaryButton = (\n        <Button\n            variant='primary'\n            tone={primaryAction.tone}\n            size='md'\n            fullWidth={!secondaryAction}\n            loading={primaryAction.loading}\n            disabled={primaryAction.disabled}\n            onPress={primaryAction.onPress}\n            testId={`${testId}-primary`}\n        >\n            {primaryAction.label}\n        </Button>\n    );\n\n    const secondaryButton = secondaryAction ? (\n        <Button\n            variant='secondary'\n            tone='default'\n            size='md'\n            disabled={secondaryAction.disabled}\n            onPress={secondaryAction.onPress}\n            testId={secondaryTestId}\n        >\n            {secondaryAction.label}\n        </Button>\n    ) : null;\n\n    return createPortal(\n        <div\n            className={cn(styles.overlay, open && styles.overlayOpen)}\n            data-theme={theme}\n            data-testid={`${testId}-overlay`}\n        >\n            <div\n                ref={dialogRef}\n                role='alertdialog'\n                aria-modal='true'\n                aria-labelledby={titleId}\n                aria-describedby={descriptionId}\n                tabIndex={-1}\n                onKeyDown={handleKeyDown}\n                className={cn(styles.dialog, open && styles.dialogOpen)}\n                data-testid={testId}\n            >\n                <DialogContext.Provider value={context}>\n                    <VStack gap={16} align='stretch'>\n                        <VStack gap={8}>{children}</VStack>\n                        {error && (\n                            <div role='alert' data-testid={`${testId}-error`}>\n                                <Text variant='body-small' color='danger' as='p'>\n                                    {error}\n                                </Text>\n                            </div>\n                        )}\n                        {secondaryButton ? (\n                            <HStack gap={8} className={styles.actions}>\n                                {secondaryButton}\n                                {primaryButton}\n                            </HStack>\n                        ) : (\n                            primaryButton\n                        )}\n                    </VStack>\n                </DialogContext.Provider>\n            </div>\n        </div>,\n        portalTarget ?? document.body\n    );\n}\n\n/**\n * Controlled confirmation dialog for decisions that require an explicit action. It cannot be\n * dismissed through its backdrop or Escape; callers own `isOpen` and close it from an action\n * callback. Copy is composed from the slots below; actions stay props because their order, focus,\n * and tone are the alert grammar.\n */\nexport const Dialog = Object.assign(DialogRoot, {\n    Title: DialogTitle,\n    Body: DialogBody,\n    Description: DialogDescription,\n});\n"
  },
  "spec": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "Dialog",
      "status": "preview",
      "version": "1.1.1",
      "summary": "A controlled alert dialog for explicit decisions, with slotted title and supporting-copy parts, a required primary action, an optional safe secondary action, and an optional transient error region."
    },
    "parts": [
      {
        "id": "root",
        "label": "Root",
        "description": "Centered alert-dialog surface containing the decision content and actions.",
        "required": true
      },
      {
        "id": "overlay",
        "label": "Overlay",
        "description": "Modal backdrop behind the dialog."
      },
      {
        "id": "title",
        "label": "Title",
        "description": "Required heading slot that names the decision and supplies the accessible name.",
        "required": true
      },
      {
        "id": "body",
        "label": "Body",
        "description": "Required supporting-copy slot. It stacks one or more description paragraphs and is the target of the dialog's accessible description.",
        "required": true
      },
      {
        "id": "description",
        "label": "Description",
        "description": "One paragraph of plain supporting copy. Multi-paragraph content is sibling descriptions. A paragraph may drop to secondary text so the paragraph that must not be skimmed past reads first.",
        "required": true
      },
      {
        "id": "primary-action",
        "label": "Primary action",
        "description": "Required confirming or acknowledging action.",
        "required": true
      },
      {
        "id": "secondary-action",
        "label": "Secondary action",
        "description": "Optional safe or cancelling action."
      },
      {
        "id": "error",
        "label": "Error",
        "description": "Optional transient failure from the last action attempt, announced on appearance."
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "default": {
          "label": "Default",
          "description": "Centered explicit-action dialog with default or danger primary-action tone."
        }
      },
      "sizes": {}
    },
    "variants": [
      {
        "id": "default",
        "label": "Default",
        "description": "Centered modal decision surface.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [],
    "measurements": [
      {
        "id": "overlay-inset",
        "label": "Overlay inset",
        "kind": "exact",
        "token": "--cds-space-24",
        "value": 24,
        "unit": "px",
        "appliesTo": [
          "overlay"
        ]
      },
      {
        "id": "dialog-maximum-width",
        "label": "Dialog maximum width",
        "kind": "at-most",
        "token": "--cds-size-320",
        "value": 320,
        "unit": "px",
        "appliesTo": [
          "root"
        ]
      },
      {
        "id": "dialog-padding",
        "label": "Dialog padding",
        "kind": "exact",
        "token": "--cds-space-24",
        "value": 24,
        "unit": "px",
        "appliesTo": [
          "root"
        ]
      },
      {
        "id": "content-action-gap",
        "label": "Content-to-action gap",
        "kind": "exact",
        "token": "--cds-space-16",
        "value": 16,
        "unit": "px",
        "appliesTo": [
          "root"
        ]
      },
      {
        "id": "title-description-gap",
        "label": "Title-to-description gap",
        "kind": "exact",
        "token": "--cds-space-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "title",
          "body"
        ]
      },
      {
        "id": "action-gap",
        "label": "Action gap",
        "kind": "exact",
        "token": "--cds-space-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "primary-action",
          "secondary-action"
        ]
      },
      {
        "id": "corner-radius",
        "label": "Corner radius",
        "kind": "exact",
        "token": "--cds-radius-2xl",
        "value": 32,
        "unit": "px",
        "appliesTo": [
          "root"
        ]
      },
      {
        "id": "description-gap",
        "label": "Paragraph gap",
        "kind": "exact",
        "token": "--cds-space-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "body",
          "description"
        ]
      }
    ],
    "layout": {
      "alignment": "The overlay centers the dialog in the available viewport while allowing vertical scrolling when content is taller than the viewport.",
      "flow": "The title and the stacked description paragraphs sit above an optional error region and then either one full-width primary action or a wrapping row containing the safe secondary action followed by the primary action.",
      "notes": [
        "Two actions remain side by side while their labels fit and wrap into a stack with the primary action first when space is constrained."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Title",
          "description": "The dialog title uses the h4 ramp.",
          "token": "--cds-type-h4-size"
        },
        {
          "label": "Description",
          "description": "Each description paragraph uses the body-small ramp.",
          "token": "--cds-type-body-small-size"
        }
      ],
      "colors": [
        {
          "label": "Surface",
          "description": "The dialog uses the raised surface background.",
          "token": "--cds-bg-surface"
        },
        {
          "label": "Primary text",
          "description": "The title and default supporting content use primary text.",
          "token": "--cds-text-primary"
        },
        {
          "label": "Secondary text",
          "description": "A description paragraph subordinate to the consequence uses secondary text.",
          "token": "--cds-text-secondary"
        },
        {
          "label": "Overlay",
          "description": "The modal backdrop uses the shared overlay token.",
          "token": "--cds-overlay-backdrop"
        },
        {
          "label": "Error text",
          "description": "The transient error region uses danger text.",
          "token": "--cds-status-danger-solid"
        }
      ]
    },
    "states": [
      {
        "id": "closed",
        "label": "Closed",
        "description": "Not mounted after the exit animation completes."
      },
      {
        "id": "open",
        "label": "Open",
        "description": "Mounted as a modal alert dialog with actions available."
      },
      {
        "id": "primary-loading",
        "label": "Primary loading",
        "description": "The primary action communicates pending work and blocks repeated activation."
      },
      {
        "id": "action-disabled",
        "label": "Action disabled",
        "description": "Either action may be disabled while its operation is unavailable."
      },
      {
        "id": "error",
        "label": "Error",
        "description": "The last action attempt failed and the dialog shows a retryable message."
      }
    ],
    "behavior": [
      {
        "label": "Controlled visibility",
        "description": "The caller owns isOpen and closes the dialog from an action callback."
      },
      {
        "label": "Explicit decision",
        "description": "Backdrop interaction does not dismiss the dialog; the user chooses an action."
      },
      {
        "label": "Slotted content",
        "description": "Copy is composed from a title slot and one description slot per paragraph, each taking plain text. The surface accepts no arbitrary markup, so multi-paragraph dialogs stay on the type ramp; a description sets its rank through primary or secondary text color instead of inline markup."
      },
      {
        "label": "Action priority",
        "description": "Use the danger primary-action tone for irreversible actions and provide a safe secondary action when cancellation is meaningful."
      },
      {
        "label": "Transient error",
        "description": "An error from the last action attempt is announced through an alert region and is kept out of the dialog's standing accessible description."
      }
    ],
    "accessibility": [
      {
        "label": "Alert dialog semantics",
        "description": "The root uses alertdialog and aria-modal, is named by the title slot, and is described by the body slot, which contains only the supporting paragraphs."
      },
      {
        "label": "Focus placement",
        "description": "An enabled safe secondary action receives initial focus when present; otherwise the dialog surface receives focus. Closing restores focus to the launcher. The surface suppresses the focus outline: the runtime is touch-only, so a ring around the whole card signals nothing."
      },
      {
        "label": "Action labels",
        "description": "Both actions expose their visible labels through the shared Button primitive."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Multi-paragraph copy",
        "description": "Split supporting copy into one description per paragraph when separate points communicate consequences more clearly."
      },
      {
        "label": "Long action labels",
        "description": "The two-action row wraps into a vertical stack instead of clipping or shrinking labels."
      },
      {
        "label": "Viewport constraints",
        "description": "The overlay scrolls vertically when the dialog cannot fit within the available viewport."
      },
      {
        "label": "Ranked paragraphs",
        "description": "When a dialog carries several paragraphs, drop the supporting ones to secondary text and keep the irreversible consequence in primary text as the last paragraph before the actions."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "Presentation",
          "description": "The overlay fades in while the dialog fades and scales to its resting size; scaling is removed under reduced motion."
        }
      ],
      "haptics": [
        {
          "label": "Actions",
          "description": "Dialog actions inherit the shared Button haptic behavior."
        }
      ]
    },
    "platformDifferences": []
  },
  "spec_source": "packages/design-system/src/components/overlays/Dialog/Dialog.spec.json",
  "guidance_source": {
    "path": "packages/design-system/src/components/overlays/Dialog/Dialog.mdx",
    "code": "import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';\nimport { ComponentSpec, UsageTable } from '../../../../.storybook/blocks';\nimport * as Stories from './Dialog.stories';\nimport dialogSpec from './Dialog.spec.json';\n\n<Meta of={Stories} />\n\n# Dialog\n\nA controlled confirmation surface for decisions that require an explicit action.\nA title slot, a body slot, and a primary action are required. Add a secondary\nsafe action when the context needs one.\n\n<Canvas of={Stories.Destructive} />\n\n## Composition\n\nCopy is slotted, not passed as props. `Dialog.Title` and each `Dialog.Description`\ntake plain strings, so a dialog can carry several paragraphs without the surface\naccepting arbitrary markup.\n\n```tsx\n<Dialog isOpen={isOpen} testId='chat-disable-dialog' primaryAction={confirm} secondaryAction={cancel}>\n    <Dialog.Title>Turn off the assistant?</Dialog.Title>\n    <Dialog.Body>\n        <Dialog.Description color='secondary'>We'll immediately delete every chat.</Dialog.Description>\n        <Dialog.Description>Once deleted, this cannot be recovered.</Dialog.Description>\n    </Dialog.Body>\n</Dialog>\n```\n\nHierarchy comes from color and order, not weight: `color='secondary'` drops the\nsupporting paragraphs back so the one consequence the reader must not skim past\nkeeps primary text and sits last, directly above the actions. There is no bold\nparagraph to reach for — a `<strong>` tag would inherit the user-agent 700 and a\nshared emphasis variant would be reachable from anywhere.\n\nThe actions stay props on purpose. Their order, focus, and tone are the alert\ngrammar this component exists to enforce, so they are not open to composition.\n`Dialog.Body` owns the `aria-describedby` target, which keeps the accessible\ndescription to the copy and excludes the title.\n\n<Canvas of={Stories.MultipleParagraphs} />\n\n## Use when\n\n<UsageTable\n    axis='Configuration'\n    rows={[\n        {\n            variant: 'Two actions',\n            use: 'The user can safely cancel or confirm. The enabled secondary action receives initial focus.',\n        },\n        {\n            variant: 'Primary only',\n            use: 'The user only needs to acknowledge a completed or informational state.',\n            avoid: 'High-risk actions where the user needs a clear way to cancel.',\n        },\n    ]}\n/>\n\n## Behavior\n\n`Dialog` does not dismiss from the backdrop or Escape. The caller owns `isOpen`\nand closes it from an action callback. Focus moves to an enabled secondary\naction, or to the dialog itself when no safe action is available, and returns to\nthe launcher after the close animation.\n\nPass `error` when the last action attempt failed. It renders in a `role=\"alert\"`\nregion below the copy and stays out of `aria-describedby`, so a retryable message\nis announced once rather than joining the dialog's standing description.\n\n<Canvas of={Stories.WithError} />\n<Canvas of={Stories.TwoActions} />\n<Canvas of={Stories.PrimaryOnly} />\n<Canvas of={Stories.LoadingDisabled} />\n\n## Dark theme\n\n<Canvas of={Stories.DarkTheme} />\n\n## Design Guidelines\n\n<ComponentSpec spec={dialogSpec} />\n\n## Props\n\n<Controls of={Stories.Destructive} />\n"
  },
  "props": [
    {
      "name": "isOpen",
      "type": "boolean",
      "declared_type": "boolean",
      "required": true,
      "description": "Presents the surface when true; closing remains mounted until the exit animation completes.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 45
      },
      "values": [
        false,
        true
      ],
      "values_complete": true
    },
    {
      "name": "children",
      "type": "[React.ReactElement<DialogTitleProps, string | React.JSXElementConstructor<any>>, React.ReactElement<DialogBodyProps, string | React.JSXElementConstructor<any>>]",
      "declared_type": "[React.ReactElement<DialogTitleProps>, React.ReactElement<DialogBodyProps>]",
      "required": true,
      "description": "The title and body slots, in that order.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 47
      }
    },
    {
      "name": "primaryAction",
      "type": "DialogPrimaryAction",
      "declared_type": "DialogPrimaryAction",
      "required": true,
      "description": "Required confirming or acknowledging action; it never receives initial focus.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 49
      }
    },
    {
      "name": "secondaryAction",
      "type": "DialogSecondaryAction | undefined",
      "declared_type": "DialogSecondaryAction",
      "required": false,
      "description": "Optional safe action; when enabled, it receives initial focus.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 51
      }
    },
    {
      "name": "error",
      "type": "string | undefined",
      "declared_type": "string",
      "required": false,
      "description": "Transient failure from the last action attempt. Kept out of `aria-describedby`.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 53
      }
    },
    {
      "name": "testId",
      "type": "string",
      "declared_type": "string",
      "required": true,
      "description": "Root selector used to derive slot, action, and overlay test ids.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 55
      }
    },
    {
      "name": "portalTarget",
      "type": "HTMLElement | null | undefined",
      "declared_type": "HTMLElement | null",
      "required": false,
      "description": "Portal mount node. Defaults to `document.body`.",
      "source": {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 57
      }
    }
  ],
  "prop_shapes": {},
  "examples": [],
  "tokens": [
    {
      "name": "--cds-space-24",
      "light": "24px",
      "dark": "24px"
    },
    {
      "name": "--cds-size-320",
      "light": "320px",
      "dark": "320px"
    },
    {
      "name": "--cds-space-16",
      "light": "16px",
      "dark": "16px"
    },
    {
      "name": "--cds-space-8",
      "light": "8px",
      "dark": "8px"
    },
    {
      "name": "--cds-radius-2xl",
      "light": "32px",
      "dark": "32px"
    },
    {
      "name": "--cds-type-h4-size",
      "light": "1.25rem",
      "dark": "1.25rem"
    },
    {
      "name": "--cds-type-body-small-size",
      "light": "0.875rem",
      "dark": "0.875rem"
    },
    {
      "name": "--cds-bg-surface",
      "light": "#ffffff",
      "dark": "#1b1b18"
    },
    {
      "name": "--cds-text-primary",
      "light": "#141410",
      "dark": "#f3f1ed"
    },
    {
      "name": "--cds-text-secondary",
      "light": "#646260",
      "dark": "#ffffff99"
    },
    {
      "name": "--cds-overlay-backdrop",
      "light": "rgb(0 0 0 / 40%)",
      "dark": "rgb(0 0 0 / 40%)"
    },
    {
      "name": "--cds-status-danger-solid",
      "light": "#b83100",
      "dark": "#b83100"
    }
  ],
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-overlays-dialog--destructive",
        "name": "Destructive",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "Destructive",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--destructive&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--multiple-paragraphs",
        "name": "Multiple Paragraphs",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "MultipleParagraphs",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--multiple-paragraphs&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--with-error",
        "name": "With Error",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "WithError",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--with-error&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--two-actions",
        "name": "Two Actions",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "TwoActions",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--two-actions&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--primary-only",
        "name": "Primary Only",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "PrimaryOnly",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--primary-only&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--loading-disabled",
        "name": "Loading Disabled",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "LoadingDisabled",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--loading-disabled&viewMode=story"
      },
      {
        "id": "cloaked-design-system-overlays-dialog--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Overlays/Dialog",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
        "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--dark-theme&viewMode=story"
      }
    ],
    "name": "Dialog",
    "id": "dialog",
    "category": "Overlays"
  },
  "stories": [
    {
      "id": "cloaked-design-system-overlays-dialog--destructive",
      "name": "Destructive",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "Destructive",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--destructive&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--multiple-paragraphs",
      "name": "Multiple Paragraphs",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "MultipleParagraphs",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--multiple-paragraphs&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--with-error",
      "name": "With Error",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "WithError",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--with-error&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--two-actions",
      "name": "Two Actions",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "TwoActions",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--two-actions&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--primary-only",
      "name": "Primary Only",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "PrimaryOnly",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--primary-only&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--loading-disabled",
      "name": "Loading Disabled",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "LoadingDisabled",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--loading-disabled&viewMode=story"
    },
    {
      "id": "cloaked-design-system-overlays-dialog--dark-theme",
      "name": "Dark Theme",
      "title": "Cloaked Design System/Overlays/Dialog",
      "exportName": "DarkTheme",
      "source_path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
      "source_digest": "478b146944f15a9ef9bea1f49b8ab1bce45c4bcc09067a41bf2969e65f565a62",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-overlays-dialog--dark-theme&viewMode=story"
    }
  ],
  "stories_source": {
    "path": "packages/design-system/src/components/overlays/Dialog/Dialog.stories.tsx",
    "code": "import React, { useState } from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { disabledControl } from '../../../storybook/controlOptions';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { Button } from '../../primitives/Button/Button';\nimport { Dialog } from './Dialog';\nimport type { DialogPrimaryAction, DialogSecondaryAction } from './Dialog';\n\nconst NOOP = () => undefined;\n\nconst meta: Meta<typeof Dialog> = {\n    title: 'Cloaked Design System/Overlays/Dialog',\n    component: Dialog,\n    parameters: {\n        docs: {\n            description: {\n                component:\n                    'A controlled confirmation dialog for decisions that require an explicit action. Copy is composed ' +\n                    'from Dialog.Title and one Dialog.Description per paragraph inside Dialog.Body; the actions stay ' +\n                    'props because their order, focus, and tone are the alert grammar. The backdrop and Escape do not ' +\n                    'dismiss it; callers close it from an action callback.',\n            },\n        },\n    },\n    argTypes: {\n        isOpen: disabledControl,\n        children: disabledControl,\n        primaryAction: disabledControl,\n        secondaryAction: disabledControl,\n        error: { control: 'text' },\n        portalTarget: disabledControl,\n        testId: disabledControl,\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof Dialog>;\n\ninterface DialogParagraph {\n    copy: string;\n    color?: 'primary' | 'secondary';\n}\n\ninterface DialogStageProps {\n    title: string;\n    paragraphs: DialogParagraph[];\n    primaryAction: DialogPrimaryAction;\n    secondaryAction?: DialogSecondaryAction;\n    error?: string;\n    testId: string;\n}\n\nfunction DialogStage({ title, paragraphs, primaryAction, secondaryAction, error, testId }: DialogStageProps) {\n    const [isOpen, setIsOpen] = useState(false);\n    const close = () => setIsOpen(false);\n\n    return (\n        <VStack padding={24}>\n            <Button variant='secondary' size='md' onPress={() => setIsOpen(true)} testId={`${testId}-launch`}>\n                Open dialog\n            </Button>\n            <Dialog\n                isOpen={isOpen}\n                error={error}\n                testId={testId}\n                primaryAction={{\n                    ...primaryAction,\n                    onPress: () => {\n                        primaryAction.onPress();\n                        close();\n                    },\n                }}\n                secondaryAction={\n                    secondaryAction\n                        ? {\n                              ...secondaryAction,\n                              onPress: () => {\n                                  secondaryAction.onPress();\n                                  close();\n                              },\n                          }\n                        : undefined\n                }\n            >\n                <Dialog.Title>{title}</Dialog.Title>\n                <Dialog.Body>\n                    {paragraphs.map(paragraph => (\n                        <Dialog.Description key={paragraph.copy} color={paragraph.color}>\n                            {paragraph.copy}\n                        </Dialog.Description>\n                    ))}\n                </Dialog.Body>\n            </Dialog>\n        </VStack>\n    );\n}\n\nexport const Destructive: Story = {\n    render: () => (\n        <DialogStage\n            title='Delete this identity?'\n            paragraphs={[\n                {\n                    copy: 'Deleting removes this identity and its masked email and phone number. This cannot be undone.',\n                },\n            ]}\n            secondaryAction={{ label: 'Cancel', onPress: NOOP }}\n            primaryAction={{ label: 'Delete identity', onPress: NOOP, tone: 'danger' }}\n            testId='dialog-identity'\n        />\n    ),\n};\n\nexport const MultipleParagraphs: Story = {\n    render: () => (\n        <DialogStage\n            title='Turn off the assistant?'\n            paragraphs={[\n                {\n                    copy: \"We'll immediately delete every chat and everything the assistant learned about you.\",\n                    color: 'secondary',\n                },\n                {\n                    copy: 'Your Cloaked account is not deleted, and your privacy protection and subscription both keep running.',\n                    color: 'secondary',\n                },\n                { copy: 'Once deleted, this data and your Personal File cannot be recovered.' },\n            ]}\n            secondaryAction={{ label: 'Cancel', onPress: NOOP }}\n            primaryAction={{ label: 'Turn off', onPress: NOOP, tone: 'danger' }}\n            testId='dialog-assistant'\n        />\n    ),\n};\n\nexport const WithError: Story = {\n    render: () => (\n        <DialogStage\n            title='Turn off the assistant?'\n            paragraphs={[\n                { copy: \"We'll immediately delete every chat and everything the assistant learned about you.\" },\n            ]}\n            error=\"Couldn't turn off the assistant. Nothing was changed.\"\n            secondaryAction={{ label: 'Cancel', onPress: NOOP }}\n            primaryAction={{ label: 'Try again', onPress: NOOP, tone: 'danger' }}\n            testId='dialog-assistant-error'\n        />\n    ),\n};\n\nexport const TwoActions: Story = {\n    render: () => (\n        <DialogStage\n            title='Turn off VPN?'\n            paragraphs={[{ copy: 'Your connection will stop using Cloaked VPN until you turn it back on.' }]}\n            secondaryAction={{ label: 'Keep VPN on', onPress: NOOP }}\n            primaryAction={{ label: 'Turn off VPN', onPress: NOOP }}\n            testId='dialog-vpn'\n        />\n    ),\n};\n\nexport const PrimaryOnly: Story = {\n    render: () => (\n        <DialogStage\n            title='Recovery codes saved'\n            paragraphs={[{ copy: 'Keep them somewhere secure. Each recovery code can only be used once.' }]}\n            primaryAction={{ label: 'Done', onPress: NOOP }}\n            testId='dialog-recovery-codes'\n        />\n    ),\n};\n\nexport const LoadingDisabled: Story = {\n    render: () => (\n        <DialogStage\n            title='Updating notification settings'\n            paragraphs={[{ copy: 'Your delivery preferences are being saved. This usually takes a moment.' }]}\n            secondaryAction={{ label: 'Cancel', onPress: NOOP, disabled: true }}\n            primaryAction={{ label: 'Saving changes', onPress: NOOP, loading: true }}\n            testId='dialog-notifications'\n        />\n    ),\n};\n\nexport const DarkTheme: Story = {\n    ...Destructive,\n    globals: { theme: 'dark' },\n};\n"
  },
  "links": {
    "human": "/component-dialog",
    "json": "/data/components/dialog.json",
    "markdown": "/data/components/dialog.md",
    "storybook": "/storybook/?path=/story/cloaked-design-system-overlays-dialog--destructive"
  },
  "contract_status": "preview",
  "contract_kind": "source-derived",
  "approval": "required",
  "api": {
    "method": "typescript-type-checker",
    "typescript_version": "5.9.3",
    "public_export": "Dialog",
    "public_path": "Dialog",
    "import_path": "@cloakedinc/design-system",
    "root_kind": "component",
    "entrypoints": [
      {
        "name": "Dialog",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
          "line": 64
        },
        "props_type": "DialogProps",
        "props": [
          {
            "name": "isOpen",
            "type": "boolean",
            "declared_type": "boolean",
            "required": true,
            "description": "Presents the surface when true; closing remains mounted until the exit animation completes.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 45
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "children",
            "type": "[React.ReactElement<DialogTitleProps, string | React.JSXElementConstructor<any>>, React.ReactElement<DialogBodyProps, string | React.JSXElementConstructor<any>>]",
            "declared_type": "[React.ReactElement<DialogTitleProps>, React.ReactElement<DialogBodyProps>]",
            "required": true,
            "description": "The title and body slots, in that order.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 47
            }
          },
          {
            "name": "primaryAction",
            "type": "DialogPrimaryAction",
            "declared_type": "DialogPrimaryAction",
            "required": true,
            "description": "Required confirming or acknowledging action; it never receives initial focus.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 49
            }
          },
          {
            "name": "secondaryAction",
            "type": "DialogSecondaryAction | undefined",
            "declared_type": "DialogSecondaryAction",
            "required": false,
            "description": "Optional safe action; when enabled, it receives initial focus.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 51
            }
          },
          {
            "name": "error",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Transient failure from the last action attempt. Kept out of `aria-describedby`.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 53
            }
          },
          {
            "name": "testId",
            "type": "string",
            "declared_type": "string",
            "required": true,
            "description": "Root selector used to derive slot, action, and overlay test ids.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 55
            }
          },
          {
            "name": "portalTarget",
            "type": "HTMLElement | null | undefined",
            "declared_type": "HTMLElement | null",
            "required": false,
            "description": "Portal mount node. Defaults to `document.body`.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
              "line": 57
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      },
      {
        "name": "Dialog.Title",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/overlays/Dialog/DialogTitle.tsx",
          "line": 16
        },
        "props_type": "DialogTitleProps",
        "props": [
          {
            "name": "children",
            "type": "string",
            "declared_type": "string",
            "required": true,
            "description": "Doubles as the alertdialog's accessible name.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/DialogTitle.tsx",
              "line": 10
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      },
      {
        "name": "Dialog.Body",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/overlays/Dialog/DialogBody.tsx",
          "line": 20
        },
        "props_type": "DialogBodyProps",
        "props": [
          {
            "name": "children",
            "type": "React.ReactElement<DialogDescriptionProps, string | React.JSXElementConstructor<any>> | React.ReactElement<DialogDescriptionProps, string | React.JSXElementConstructor<any>>[]",
            "declared_type": "React.ReactElement<DialogDescriptionProps> | Array<React.ReactElement<DialogDescriptionProps>>",
            "required": true,
            "description": "One description per paragraph; the body owns the spacing between them.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/DialogBody.tsx",
              "line": 13
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      },
      {
        "name": "Dialog.Description",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/overlays/Dialog/DialogDescription.tsx",
          "line": 20
        },
        "props_type": "DialogDescriptionProps",
        "props": [
          {
            "name": "children",
            "type": "string",
            "declared_type": "string",
            "required": true,
            "description": "Plain copy for one paragraph. Multi-paragraph content is sibling descriptions, not markup.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/DialogDescription.tsx",
              "line": 9
            }
          },
          {
            "name": "color",
            "type": "\"primary\" | \"secondary\" | undefined",
            "declared_type": "'primary' | 'secondary'",
            "required": false,
            "description": "Drops a paragraph to secondary text. Hierarchy in a dialog comes from color and order, so\nthe paragraph the reader must not skim past stays primary and sits last, next to the actions.",
            "source": {
              "path": "packages/design-system/src/components/overlays/Dialog/DialogDescription.tsx",
              "line": 14
            },
            "values": [
              "primary",
              "secondary"
            ],
            "values_complete": true,
            "default": "'primary'",
            "default_kind": "source-expression"
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      }
    ],
    "type_sources": [
      {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 22,
        "name": "DialogPrimaryAction",
        "code": "export interface DialogPrimaryAction {\n    label: string;\n    onPress: () => void;\n    /** Use `danger` for irreversible actions. */\n    tone?: 'default' | 'danger';\n    loading?: boolean;\n    disabled?: boolean;\n}"
      },
      {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 34,
        "name": "DialogSecondaryAction",
        "code": "export interface DialogSecondaryAction {\n    label: string;\n    onPress: () => void;\n    disabled?: boolean;\n}"
      },
      {
        "path": "packages/design-system/src/components/overlays/Dialog/Dialog.tsx",
        "line": 43,
        "name": "DialogProps",
        "code": "export interface DialogProps {\n    /** Presents the surface when true; closing remains mounted until the exit animation completes. */\n    isOpen: boolean;\n    /** The title and body slots, in that order. */\n    children: [React.ReactElement<DialogTitleProps>, React.ReactElement<DialogBodyProps>];\n    /** Required confirming or acknowledging action; it never receives initial focus. */\n    primaryAction: DialogPrimaryAction;\n    /** Optional safe action; when enabled, it receives initial focus. */\n    secondaryAction?: DialogSecondaryAction;\n    /** Transient failure from the last action attempt. Kept out of `aria-describedby`. */\n    error?: string;\n    /** Root selector used to derive slot, action, and overlay test ids. */\n    testId: string;\n    /** Portal mount node. Defaults to `document.body`. */\n    portalTarget?: HTMLElement | null;\n}"
      },
      {
        "path": "packages/design-system/src/components/overlays/Dialog/DialogBody.tsx",
        "line": 11,
        "name": "DialogBodyProps",
        "code": "export interface DialogBodyProps {\n    /** One description per paragraph; the body owns the spacing between them. */\n    children: React.ReactElement<DialogDescriptionProps> | Array<React.ReactElement<DialogDescriptionProps>>;\n}"
      },
      {
        "path": "packages/design-system/src/components/overlays/Dialog/DialogDescription.tsx",
        "line": 7,
        "name": "DialogDescriptionProps",
        "code": "export interface DialogDescriptionProps {\n    /** Plain copy for one paragraph. Multi-paragraph content is sibling descriptions, not markup. */\n    children: string;\n    /**\n     * Drops a paragraph to secondary text. Hierarchy in a dialog comes from color and order, so\n     * the paragraph the reader must not skim past stays primary and sits last, next to the actions.\n     */\n    color?: 'primary' | 'secondary';\n}"
      },
      {
        "path": "packages/design-system/src/components/overlays/Dialog/DialogTitle.tsx",
        "line": 8,
        "name": "DialogTitleProps",
        "code": "export interface DialogTitleProps {\n    /** Doubles as the alertdialog's accessible name. */\n    children: string;\n}"
      }
    ],
    "defaults_policy": "Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source."
  },
  "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"
    }
  },
  "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": "approved",
    "imported_source_revision": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "note": "Inherited specification status is provenance, not approval of the current local implementation or extracted contract."
  }
}
