{
  "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": "vstack",
  "name": "VStack",
  "category": "Layout",
  "contract_status": "preview",
  "contract_kind": "source-derived",
  "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."
  },
  "approval": "required",
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-layout-vstack--playground",
        "name": "Playground",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "Playground",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--playground&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--tight-gap",
        "name": "Tight Gap",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "TightGap",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--tight-gap&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--align-matrix",
        "name": "Align Matrix",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "AlignMatrix",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--align-matrix&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--justify-matrix",
        "name": "Justify Matrix",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "JustifyMatrix",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--justify-matrix&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--centered-panel",
        "name": "Centered Panel",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "CenteredPanel",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--centered-panel&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--scroll-column",
        "name": "Scroll Column",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "ScrollColumn",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--scroll-column&viewMode=story"
      },
      {
        "id": "cloaked-design-system-layout-vstack--with-individual-padding",
        "name": "With Individual Padding",
        "title": "Cloaked Design System/Layout/VStack",
        "exportName": "WithIndividualPadding",
        "source_path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
        "source_digest": "5fe07e58bf180451285685a5ade5a24ce9cf0bd626024bb2679b01b9511e53e5",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-layout-vstack--with-individual-padding&viewMode=story"
      }
    ],
    "name": "VStack",
    "id": "vstack",
    "category": "Layout"
  },
  "stories_source": {
    "path": "packages/design-system/src/components/layout/VStack/VStack.stories.tsx",
    "code": "import React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { VStack } from './VStack';\nimport { HStack } from '../HStack/HStack';\nimport { Card } from '../../cards/Card/Card';\nimport { Text } from '../../primitives/Text/Text';\nimport {\n    SPACE_OPTIONS,\n    STACK_ALIGN_OPTIONS,\n    STACK_JUSTIFY_OPTIONS,\n    selectArgType,\n} from '../../../storybook/controlOptions';\n\nconst Box = ({ label }: { label: string }) => (\n    <Card radius='sm'>\n        <Card.Body padding='compact'>\n            <Text variant='body-small'>{label}</Text>\n        </Card.Body>\n    </Card>\n);\n\nconst meta: Meta<typeof VStack> = {\n    title: 'Cloaked Design System/Layout/VStack',\n    component: VStack,\n    parameters: {\n        a11y: { test: 'error' },\n        docs: {\n            description: {\n                component:\n                    'Vertical flex column with a token-scale `gap` — the default replacement for hand-rolled ' +\n                    '`display:flex; flex-direction:column` wrappers. `align` is the cross (horizontal) axis and ' +\n                    '`justify` the main (vertical) axis, so `justify=\"between\"` pushes the first and last child ' +\n                    'to the top and bottom edges. Use `HStack` for a row, `Grid` for equal-width tiles, and ' +\n                    '`Screen`/`Background` for full-screen scaffolding.',\n            },\n        },\n    },\n    args: {\n        gap: 12,\n        children: [<Box key='a' label='One' />, <Box key='b' label='Two' />, <Box key='c' label='Three' />],\n    },\n    argTypes: {\n        gap: { ...selectArgType(SPACE_OPTIONS), description: 'Space between children, in `--cds-space-*` steps.' },\n        align: {\n            ...selectArgType(STACK_ALIGN_OPTIONS),\n            description: 'Cross-axis (horizontal) alignment of children (`align-items`).',\n        },\n        justify: {\n            ...selectArgType(STACK_JUSTIFY_OPTIONS),\n            description: 'Main-axis (vertical) distribution of children (`justify-content`).',\n        },\n        wrap: { description: 'Allow children to wrap onto multiple columns when they overflow.' },\n        scroll: { description: 'Turn the column into a vertical overflow region with a hidden scrollbar.' },\n        padding: { ...selectArgType(SPACE_OPTIONS), description: 'Uniform inner padding, in `--cds-space-*` steps.' },\n        paddingX: {\n            ...selectArgType(SPACE_OPTIONS),\n            description: 'Horizontal padding override, in `--cds-space-*` steps.',\n        },\n        paddingY: {\n            ...selectArgType(SPACE_OPTIONS),\n            description: 'Vertical padding override, in `--cds-space-*` steps.',\n        },\n        paddingTop: { ...selectArgType(SPACE_OPTIONS), description: 'Top padding override, in `--cds-space-*` steps.' },\n        paddingRight: {\n            ...selectArgType(SPACE_OPTIONS),\n            description: 'Right padding override, in `--cds-space-*` steps.',\n        },\n        paddingBottom: {\n            ...selectArgType(SPACE_OPTIONS),\n            description: 'Bottom padding override, in `--cds-space-*` steps.',\n        },\n        paddingLeft: {\n            ...selectArgType(SPACE_OPTIONS),\n            description: 'Left padding override, in `--cds-space-*` steps.',\n        },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof VStack>;\n\nexport const Playground: Story = {};\n\nexport const TightGap: Story = {\n    parameters: {\n        docs: { description: { story: 'A small `gap` for dense rows such as stacked key/value pairs.' } },\n    },\n    args: {\n        gap: 4,\n        children: [<Box key='a' label='Row 1' />, <Box key='b' label='Row 2' />],\n    },\n};\n\nexport const AlignMatrix: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story:\n                    'Every `align` value against a fixed-width column. `stretch` fills the width; `start`/`center`/' +\n                    '`end` sit the content-width boxes left/center/right.',\n            },\n        },\n    },\n    render: () => (\n        <HStack gap={16} align='start' wrap>\n            {STACK_ALIGN_OPTIONS.map(align => (\n                <VStack key={align} gap={8}>\n                    <Text variant='body-small' color='secondary'>\n                        align {align}\n                    </Text>\n                    <Card surface='highlight' radius='lg'>\n                        <VStack gap={8} align={align} padding={12} style={{ width: 'var(--cds-size-160)' }}>\n                            <Box label='Short' />\n                            <Box label='A wider row' />\n                        </VStack>\n                    </Card>\n                </VStack>\n            ))}\n        </HStack>\n    ),\n};\n\nexport const JustifyMatrix: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story:\n                    'Every `justify` value inside a fixed-height column. `between`/`around`/`evenly` spread the ' +\n                    'rows vertically; `start`/`center`/`end` cluster them.',\n            },\n        },\n    },\n    render: () => (\n        <HStack gap={16} align='start' wrap>\n            {STACK_JUSTIFY_OPTIONS.map(justify => (\n                <VStack key={justify} gap={8}>\n                    <Text variant='body-small' color='secondary'>\n                        justify {justify}\n                    </Text>\n                    <Card surface='highlight' radius='lg'>\n                        <VStack gap={8} justify={justify} padding={12} style={{ height: 'var(--cds-size-240)' }}>\n                            <Box label='One' />\n                            <Box label='Two' />\n                        </VStack>\n                    </Card>\n                </VStack>\n            ))}\n        </HStack>\n    ),\n};\n\nexport const CenteredPanel: Story = {\n    parameters: {\n        docs: { description: { story: 'Centered on both axes with padding — the empty-state / onboarding pattern.' } },\n    },\n    args: {\n        gap: 16,\n        align: 'center',\n        justify: 'center',\n        padding: 24,\n        children: [\n            <Text key='title' variant='h3'>\n                Centered stack\n            </Text>,\n            <Text key='body' variant='body-small' color='secondary'>\n                Useful for empty states and onboarding moments.\n            </Text>,\n            <Box key='action' label='Primary action' />,\n        ],\n    },\n    decorators: [Story => <div style={{ height: 'var(--cds-size-240)' }}>{Story()}</div>],\n};\n\nexport const ScrollColumn: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: '`scroll` makes the column a vertical overflow region once content exceeds its height.',\n            },\n        },\n    },\n    args: {\n        gap: 12,\n        scroll: true,\n        padding: 16,\n        children: ['One', 'Two', 'Three', 'Four', 'Five', 'Six'].map(label => <Box key={label} label={label} />),\n    },\n    decorators: [Story => <div style={{ height: 'var(--cds-size-240)' }}>{Story()}</div>],\n};\n\nexport const WithIndividualPadding: Story = {\n    parameters: {\n        docs: { description: { story: 'Per-edge padding overrides layered on top of a uniform column.' } },\n    },\n    args: {\n        gap: 12,\n        paddingX: 24,\n        paddingTop: 40,\n        paddingBottom: 16,\n        children: [<Box key='one' label='Custom top padding' />, <Box key='two' label='Token-aligned sides' />],\n    },\n};\n"
  },
  "specification": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "VStack",
      "status": "preview",
      "version": "1.0.0",
      "summary": "A vertical flex column with a token-scale gap, cross-axis alignment, main-axis distribution, wrap, and scroll options."
    },
    "parts": [
      {
        "id": "root",
        "label": "Root",
        "description": "Flex column container. Structural: it lays out children and paints no surface of its own.",
        "required": true
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "column": {
          "label": "Column",
          "description": "The single vertical flex layout."
        }
      },
      "sizes": {},
      "alignments": {
        "start": {
          "label": "Start"
        },
        "center": {
          "label": "Center"
        },
        "end": {
          "label": "End"
        },
        "stretch": {
          "label": "Stretch"
        },
        "baseline": {
          "label": "Baseline"
        }
      },
      "justifications": {
        "start": {
          "label": "Start"
        },
        "center": {
          "label": "Center"
        },
        "end": {
          "label": "End"
        },
        "between": {
          "label": "Between"
        },
        "around": {
          "label": "Around"
        },
        "evenly": {
          "label": "Evenly"
        }
      }
    },
    "variants": [
      {
        "id": "column",
        "label": "Column",
        "description": "Vertical flex container.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [],
    "measurements": [
      {
        "id": "stack-gap",
        "label": "Column gap",
        "kind": "example-only",
        "token": "--cds-space-12",
        "value": 12,
        "unit": "px",
        "appliesTo": [
          "root"
        ],
        "notes": "Representative value: gap is author-configurable and accepts any step on the spacing scale. 12 is the value rendered and verified by the Playground story."
      }
    ],
    "layout": {
      "alignment": "align sets the cross (horizontal) axis; justify sets the main (vertical) axis.",
      "flow": "Children flow top to bottom and may wrap or scroll on overflow.",
      "notes": [
        "Use HStack for a row, Grid for equal-width tiles, and Screen/Background for full-screen scaffolding."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Inherited",
          "description": "VStack sets no type; children own their text. Ramp noted for parity.",
          "token": "--cds-type-body-size"
        }
      ],
      "colors": [
        {
          "label": "Transparent",
          "description": "VStack paints no background; the surface behind shows through.",
          "token": "--cds-bg-page"
        }
      ]
    },
    "states": [
      {
        "id": "default",
        "label": "Default",
        "description": "Static column that flexes to its children."
      },
      {
        "id": "wrap",
        "label": "Wrapped",
        "description": "Children wrap onto additional columns on overflow."
      },
      {
        "id": "scroll",
        "label": "Scroll",
        "description": "The column becomes a vertical overflow region with a hidden scrollbar."
      }
    ],
    "behavior": [
      {
        "label": "Token gap",
        "description": "gap uses the spacing scale; avoid hand-rolled flex wrappers."
      },
      {
        "label": "Padding",
        "description": "Padding props map to the spacing scale per edge."
      }
    ],
    "accessibility": [
      {
        "label": "Presentational",
        "description": "VStack is a layout container and adds no roles; order follows DOM order."
      },
      {
        "label": "Focus order",
        "description": "Reordering visually via justify does not change tab order."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Wrap vs scroll",
        "description": "Choose wrap to reflow onto new columns or scroll to keep a single overflow region."
      },
      {
        "label": "Distribution",
        "description": "between, around, and evenly pin content to the top and bottom edges of a sized column."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "None",
          "description": "VStack does not animate layout changes on its own."
        }
      ],
      "haptics": [
        {
          "label": "None",
          "description": "A layout container requests no haptics."
        }
      ]
    },
    "platformDifferences": []
  },
  "specification_source": "packages/design-system/src/components/layout/VStack/VStack.spec.json",
  "guidance": {
    "summary": "A vertical flex column with a token-scale gap, cross-axis alignment, main-axis distribution, wrap, and scroll options.",
    "guidance": [
      {
        "heading": "Overview",
        "body": "Vertical flex column with a token-scale `gap` — the default replacement for hand-rolled\n`display:flex; flex-direction:column` wrappers. It is the most-reached-for layout primitive."
      },
      {
        "heading": "When to use",
        "body": "Reach for `VStack` any time you stack elements top to bottom with consistent spacing — form\nfields, list rows, card contents, whole screen bodies. `align` is the cross (horizontal) axis\nand `justify` the main (vertical) axis, so `justify=\"between\"` pushes the first and last child\nto the top and bottom edges.\n\n-   Laying out a **row** left to right? Use `HStack`.\n-   Placing items in **equal-width tiles** across a fixed column count? Use `Grid`.\n-   Scaffolding a **whole route** (surface, safe-area insets, sticky header/footer)? Wrap the page\n    in `Screen` and use `VStack` for the content inside it.\n-   Need a **surface behind a centered panel** without route chrome? Use `Background`."
      }
    ],
    "usage": [],
    "examples": [],
    "source": "packages/design-system/src/components/layout/VStack/VStack.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."
  },
  "links": {
    "human": "/component-vstack",
    "json": "/data/visual/components/vstack.json",
    "storybook": "/storybook/?path=/story/cloaked-design-system-layout-vstack--playground"
  }
}
