+
+/**
+ * This component is used in the `Footer` to track progress of the Workflows steps.
+ * It has no reverse variant and should only be used in the Worflow's `Footer` component.
+ */
+export const Playground: Story = {
+ parameters: {
+ docs: {
+ canvas: {
+ sourceState: "shown",
+ },
+ },
+ },
+}
+
+/** To ensure WCAG AA compliance, there are 3 visually destinct states.
+ * These are reflected in their accessible names for screen reader: "Completed", "Current" and "Not started"
+ */
+export const ProgressStates: Story = {
+ args: {
+ currentStepId: "questions-step",
+ },
+}
+
+/**
+ * You can use the `isComplete` follow a successful submission to render all steps as complete.
+ */
+export const AllStepsComplete: Story = {
+ args: {
+ currentStepId: "schedule-step",
+ isComplete: true,
+ },
+}
+
+export const FewerSteps: Story = {
+ args: {
+ currentStepId: "questions-step",
+ steps: [
+ { label: "Settings", id: "settings-step" },
+ { label: "Questions", id: "questions-step" },
+ { label: "Preview", id: "preview-step" },
+ ],
+ },
+}
+
+/**
+ * We have baked in a container query to ensure the component can be responsive.
+ * When a step reaches its minimum size (4.5rem), it will hide the display name to maximise realestate.
+ */
+export const EightSteps: Story = {
+ args: {
+ currentStepId: "questions-step",
+ steps: [
+ ...meta.args.steps,
+ { label: "Plan", id: "plan-step" },
+ { label: "Provision", id: "provision-step" },
+ { label: "Procure", id: "procure-step" },
+ ],
+ },
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.mdx b/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.mdx
new file mode 100644
index 00000000000..cbcd52fc70f
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.mdx
@@ -0,0 +1,165 @@
+import { ArgTypes, Canvas, Meta } from "@storybook/blocks"
+import { Installation, ResourceLinks } from "~storybook/components"
+import * as Workflow from "./Workflow.stories"
+import * as WorkflowFooter from "./WorkflowFooter.stories"
+import * as WorkflowHeader from "./WorkflowHeader.stories"
+
+
+
+# Workflow
+
+
+
+
+
+## Overview
+
+This is a page template component containing the header, footer, and main landmarks that compose a Workflow page. Its purpose is to guide a customer through a multi-step form to create a Workflow.
+
+The Worflow is intended as a page wrapper and sets a minimum height of `100vh` with a sticky `Header` component. The `Children` will be wrapped in an unstyled main landmark to provide flexibility for inner content layouts.
+
+To ensure at readability at 400% zoom (See WCAG's [Reflow criteria](https://www.w3.org/WAI/WCAG21/Understanding/reflow.html)) this component will collapse to a vertical layout on smaller screen sizes and remove `sticky` positioning to maximise screen real estate. You can see an example in [the responsive workflow story](/story/pages-workflow-components-workflow--responsive-workflow).
+
+
+
+## Header actions
+
+The `headerActions` prop takes array of JSX elements that will render in the top right of the `Header` component.
+
+While the number of JSX elements is not limited, is important to consider the real estate in the `Header` and how larger strings or components may be rendered on smaller screen sizes.
+
+ ,
+
+ ]}
+ {...otherProps}
+ >
+
+ `}}
+/>
+
+
+## Handling a Workflow exit
+
+A common pattern identified is a Workflow Exit button. An implementation of this component should be passed to the `headerActions` an array to handle a user leaving a Workflow. We've provided an example below that combines a Kaizen `Button` with the `ConfirmationModal` component.
+
+(false)
+ ...
+ return (
+ <>
+ setShowModal(true)}
+ />
+ {
+ setShowModal(false)
+ }}
+ >
+
+ {exitDescription}
+
+
+ >
+ )`
+ }}
+/>
+
+## Tracking progress
+
+The Footer tracks the progress of the form by using finding the index of the `currentStepId` within the `steps` array.
+
+
+
+ `}}
+/>
+
+The Footer is agnostic to the JSX elements that are used in the `previousAction` and `nextAction`. While we recommend using the Kaizen Button, a button-like component can be used in its place to satisfy project-specific requirements.
+
+
+To hide, disable or change the appearance of the Footer buttons you can leverage the props available for the `@kaizen/button` or pass in undefined to not render the component.
+
+ }
+ previousAction={ }
+ {...otherProps}
+ >
+
+ `}}
+/>
+
+In Instances where users are returning to a completed workflow you can pass the `isComplete` prop to set the indicators to their "complete" status. This will also be reflected in their Aria title.
+
+
+
+ `}}
+/>
+
+## Composable Worflow
+
+While we do not advise this path, a composable Workflow may be created if required. Refer to the component's stories on how to consume each subcomponent.
+
+
+
+
+## Worflow API at a glance
+
+
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.stories.tsx b/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.stories.tsx
new file mode 100644
index 00000000000..aafde8941e6
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/Workflow.stories.tsx
@@ -0,0 +1,178 @@
+import React from "react"
+import { Meta, StoryObj } from "@storybook/react"
+import { Heading } from "~components/Heading"
+import { CloseIcon, VisibleIcon } from "~components/Icon"
+import { Text } from "~components/Text"
+import { TextField } from "~components/TextField"
+import { Button } from "~components/__actions__/v2"
+import { Tag } from "~components/__future__"
+import { Workflow } from "../"
+import { WorkflowControls } from "./controls"
+
+const MockContent = (): JSX.Element => (
+
+
+
+ Name and schedule the self-reflection cycle
+
+
+
+
+)
+
+const meta = {
+ title: "Layout/Workflow/Workflow (v3)",
+ component: Workflow,
+ argTypes: WorkflowControls,
+ args: {
+ workflowName: "Create a self-reflection cycle",
+ currentStepId: "settings-step",
+ steps: [
+ { label: "Settings", id: "settings-step" },
+ { label: "Questions", id: "questions-step" },
+ { label: "Preview", id: "preview-step" },
+ { label: "Employees", id: "employees-step" },
+ { label: "Schedule", id: "schedule-step" },
+ ],
+ isComplete: false,
+ statusTag: Draft ,
+ previousAction: ,
+ nextAction: ,
+ headerActions: [
+ }
+ secondary
+ iconPosition="end"
+ />,
+ ],
+ children: ,
+ },
+} satisfies Meta
+
+export default meta
+
+type Story = StoryObj
+
+export const Playground: Story = {
+ parameters: {
+ docs: {
+ canvas: {
+ sourceState: "shown",
+ },
+ },
+ chromatic: { disable: false },
+ },
+}
+
+export const MultipleActions: Story = {
+ args: {
+ headerActions: [
+ }
+ secondary
+ iconPosition="start"
+ />,
+ }
+ secondary
+ iconPosition="end"
+ onClick={(): void => alert("mock example of a save action")}
+ />,
+ ],
+ },
+}
+
+export const FinalStep: Story = {
+ args: { currentStepId: "schedule-step" },
+}
+
+export const CompletedWorkflow: Story = {
+ args: { isComplete: true },
+ parameters: { chromatic: { disable: false } },
+}
+
+export const ComposableWorkflow: Story = {
+ render: ({
+ steps,
+ isComplete,
+ workflowName,
+ currentStepId,
+ statusTag,
+ headerActions,
+ previousAction,
+ nextAction,
+ ...restProps
+ }) => (
+
+ step.id === currentStepId)!.label}
+ statusTag={statusTag}
+ headerActions={headerActions}
+ />
+
+ Content
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta error
+ labore dolorum debitis eaque laboriosam qui quidem itaque
+ necessitatibus obcaecati aut earum consectetur excepturi accusamus
+ nulla libero maxime, quibusdam vero?
+
+
+
+
+ ),
+ parameters: { chromatic: { disable: false } },
+}
+
+export const ResponsiveWorkflow: Story = {
+ parameters: {
+ docs: {
+ canvas: {
+ sourceState: "hidden",
+ },
+ },
+ viewport: {
+ viewports: {
+ vieportZoomed: {
+ name: "Simulate 400% zoom",
+ styles: {
+ width: "500px",
+ height: "800px",
+ },
+ type: "mobile",
+ },
+ },
+ defaultViewport: "vieportZoomed",
+ },
+ chromatic: {
+ disable: false,
+ viewports: [500, 1200],
+ },
+ },
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.mdx b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.mdx
new file mode 100644
index 00000000000..b4b31f4f8fc
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.mdx
@@ -0,0 +1,38 @@
+import { Canvas, Controls, DocsStory, Meta } from "@storybook/blocks"
+import { Installation, ResourceLinks } from "~storybook/components"
+import * as WorkflowFooterStories from "./WorkflowFooter.stories"
+
+
+
+# Footer
+
+
+
+
+
+## Overview
+
+
+
+
+## API
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.stories.tsx b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.stories.tsx
new file mode 100644
index 00000000000..921cf1fd1a8
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowFooter.stories.tsx
@@ -0,0 +1,95 @@
+import React from "react"
+import { Meta, StoryObj } from "@storybook/react"
+import { Button } from "~components/__actions__/v2"
+import { Workflow } from "../"
+import { WorkflowControls } from "./controls"
+
+const meta = {
+ title: "Layout/Workflow/Workflow (v3)/Components/Footer",
+ component: Workflow.Footer,
+ argTypes: {
+ ...WorkflowControls.nextAction,
+ ...WorkflowControls.previousAction,
+ ...WorkflowControls.currentStepId,
+ },
+ args: {
+ currentStepId: "preview-step",
+ steps: [
+ { label: "Settings", id: "settings-step" },
+ { label: "Questions", id: "questions-step" },
+ { label: "Preview", id: "preview-step" },
+ { label: "Employees", id: "employees-step" },
+ { label: "Schedule", id: "schedule-step" },
+ ],
+ isComplete: false,
+ previousAction: ,
+ nextAction: ,
+ },
+} satisfies Meta
+
+export default meta
+
+type Story = StoryObj
+
+export const Playground: Story = {
+ parameters: {
+ docs: {
+ canvas: {
+ sourceState: "shown",
+ },
+ },
+ },
+}
+
+/** Next and previous button are passed in by the consumer to allow for page routing method to be determined by the user
*/
+export const FirstStep: Story = {
+ args: { currentStepId: "settings-step" },
+}
+
+export const NextStepDisabled: Story = {
+ args: { nextAction: },
+}
+
+export const LastStep: Story = {
+ args: {
+ currentStepId: "schedule-step",
+ nextAction: (
+
+ ),
+ },
+}
+
+export const AllStepsComplete: Story = {
+ args: {
+ currentStepId: "schedule-step",
+ isComplete: true,
+ },
+}
+
+export const FewerSteps: Story = {
+ args: {
+ currentStepId: "questions-step",
+ steps: [
+ { label: "Settings", id: "settings-step" },
+ { label: "Questions", id: "questions-step" },
+ { label: "Preview", id: "preview-step" },
+ ],
+ },
+}
+
+export const EightSteps: Story = {
+ args: {
+ currentStepId: "questions-step",
+ steps: [
+ ...meta.args.steps,
+ { label: "Plan", id: "plan-step" },
+ { label: "Provision", id: "provision-step" },
+ { label: "Procure", id: "procure-step" },
+ ],
+ },
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.mdx b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.mdx
new file mode 100644
index 00000000000..5eb2ea571bd
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.mdx
@@ -0,0 +1,28 @@
+import { Canvas, Controls, DocsStory, Meta } from "@storybook/blocks"
+import { Installation, ResourceLinks } from "~storybook/components"
+import * as WorkflowHeaderStories from "./WorkflowHeader.stories"
+
+
+
+# Header
+
+
+
+
+
+## Overview
+
+
+
+
+## API
+
+
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.stories.tsx b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.stories.tsx
new file mode 100644
index 00000000000..c0c6867f09f
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/WorkflowHeader.stories.tsx
@@ -0,0 +1,68 @@
+import React from "react"
+import { Meta, StoryObj } from "@storybook/react"
+import { CloseIcon, VisibleIcon } from "~components/Icon"
+import { Button } from "~components/__actions__/v2"
+import { Tag } from "~components/__future__"
+import { Workflow } from "../"
+import { WorkflowControls } from "./controls"
+
+const meta = {
+ title: "Layout/Workflow/Workflow (v3)/Components/Header",
+ component: Workflow.Header,
+ argTypes: {
+ ...WorkflowControls.headerActions,
+ },
+ args: {
+ workflowName: "Create a self-reflection cycle",
+ stepName: "Settings",
+ statusTag: Draft ,
+ headerActions: [
+ }
+ secondary
+ iconPosition="end"
+ onClick={(): void => alert("mock example of a save action")}
+ />,
+ ],
+ },
+} satisfies Meta
+
+export default meta
+
+type Story = StoryObj
+
+export const Playground: Story = {
+ parameters: {
+ docs: {
+ canvas: {
+ sourceState: "shown",
+ },
+ },
+ },
+}
+
+/** `headerActions` gives consumers the ability to add multiple `JSX Element`'s to top of the Workflow Header. We assume these will be Button or Button-like components
+ * There is no limit to the number of actions you can pass in, but please consider the limited realesate with labels.
*/
+export const MultipleActions: Story = {
+ args: {
+ headerActions: [
+ }
+ secondary
+ iconPosition="start"
+ />,
+ }
+ secondary
+ iconPosition="end"
+ onClick={(): void => alert("mock example of a save action")}
+ />,
+ ],
+ },
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/controls/controls.tsx b/packages/components/src/__layout__/Workflow/v3/_docs/controls/controls.tsx
new file mode 100644
index 00000000000..e1654e7f5a3
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/controls/controls.tsx
@@ -0,0 +1,93 @@
+import React from "react"
+import { ArgTypes } from "@storybook/react"
+import { CloseIcon, VisibleIcon } from "~components/Icon"
+import { Button } from "~components/__actions__/v2"
+
+export const WorkflowControls: Partial = {
+ headerActions: {
+ control: {
+ type: "radio",
+ },
+ options: ["Single action", "Multiple actions", "No actions"],
+ mapping: {
+ "Single action": [
+ }
+ secondary
+ iconPosition="end"
+ />,
+ ],
+ "Multiple actions": [
+ }
+ secondary
+ iconPosition="end"
+ />,
+ }
+ secondary
+ iconPosition="start"
+ />,
+ ],
+ "No actions": [],
+ },
+ },
+ nextAction: {
+ control: {
+ type: "radio",
+ },
+ options: ["Next active", "Next disabled", "Next submit", "No next action"],
+ mapping: {
+ "Next active": ,
+ "Next disabled": ,
+ "Next submit": (
+
+ ),
+ "No next action": undefined,
+ },
+ },
+ previousAction: {
+ control: {
+ type: "radio",
+ },
+ options: [
+ "Previous active",
+ "Previous disabled",
+ "Previous submit",
+ "No Previous action",
+ ],
+ mapping: {
+ "Previous active": ,
+ "Previous disabled": ,
+ "Previous submit": (
+
+ ),
+ "No Previous action": undefined,
+ },
+ },
+ currentStepId: {
+ control: {
+ type: "select",
+ },
+ options: [
+ "settings-step",
+ "questions-step",
+ "preview-step",
+ "employees-step",
+ "schedule-step",
+ ],
+ mapping: {
+ "settings-step": "settings-step",
+ "questions-step": "questions-step",
+ "preview-step": "preview-step",
+ "employees-step": "employees-step",
+ "schedule-step": "schedule-step",
+ },
+ },
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/_docs/controls/index.tsx b/packages/components/src/__layout__/Workflow/v3/_docs/controls/index.tsx
new file mode 100644
index 00000000000..496b46abcf6
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/_docs/controls/index.tsx
@@ -0,0 +1 @@
+export * from "./controls"
diff --git a/packages/components/src/Workflow/index.ts b/packages/components/src/__layout__/Workflow/v3/index.ts
similarity index 100%
rename from packages/components/src/Workflow/index.ts
rename to packages/components/src/__layout__/Workflow/v3/index.ts
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/Footer.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/Footer.tsx
new file mode 100644
index 00000000000..2c2f37195be
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/Footer.tsx
@@ -0,0 +1,38 @@
+import React from "react"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import {
+ FooterRoot,
+ FooterAction,
+ ProgressStepper,
+ ProgressStepperProps,
+ FooterRootProps,
+} from "./components"
+
+export type FooterProps = {
+ /** An action to return to a previous step */
+ previousAction?: JSX.Element
+ /** An action to progress to the next step or submit the form */
+ nextAction?: JSX.Element
+} & ProgressStepperProps &
+ OverrideClassName>
+
+export const Footer = ({
+ steps,
+ currentStepId,
+ isComplete,
+ previousAction,
+ nextAction,
+ ...restProps
+}: FooterProps): JSX.Element => (
+
+
+
+
+
+)
+
+Footer.displayName = "Workflow.Footer"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.module.css
new file mode 100644
index 00000000000..c831d29804b
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.module.css
@@ -0,0 +1,15 @@
+.footerAction {
+ display: flex;
+ flex-grow: 1;
+ flex-basis: auto;
+}
+
+.footerActionPrevious {
+ grid-area: "prev";
+ justify-content: start;
+}
+
+.footerActionNext {
+ grid-area: "next";
+ justify-content: end;
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.tsx
new file mode 100644
index 00000000000..a99c43f5e75
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/FooterActions.tsx
@@ -0,0 +1,28 @@
+import React, { HTMLAttributes } from "react"
+import classnames from "classnames"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./FooterActions.module.css"
+
+export type FooterActionsProps = {
+ actionType?: "Previous" | "Next"
+ action?: JSX.Element
+} & OverrideClassName, "children">>
+
+/** A simple wrapper for a Footer previous or next action */
+export const FooterAction = ({
+ actionType = "Previous",
+ action,
+ ...restProps
+}: FooterActionsProps): JSX.Element => (
+
+ {action}
+
+)
+
+FooterAction.displayName = "Workflow.FooterActions"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/index.ts
new file mode 100644
index 00000000000..9c7a165d2cc
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/FooterActions/index.ts
@@ -0,0 +1 @@
+export * from "./FooterActions"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.module.css
new file mode 100644
index 00000000000..2f5dcb2f186
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.module.css
@@ -0,0 +1,110 @@
+.stepsContainer {
+ --progress-stepper-indicator-size: 1.25rem;
+
+ width: 100%;
+ grid-area: stepper;
+}
+
+.stepList {
+ display: none;
+ justify-content: center;
+ align-items: flex-end;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+
+ @media (width >= 768px) {
+ display: flex;
+ }
+}
+
+.step {
+ display: flex;
+ flex-grow: 1;
+ flex-basis: 100%;
+ justify-content: center;
+ max-width: var(--spacing-96);
+ overflow-wrap: break-word;
+ position: relative;
+ container: step / inline-size;
+}
+
+.stepContent {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+}
+
+.stepIndicator {
+ width: var(--progress-stepper-indicator-size);
+ height: var(--progress-stepper-indicator-size);
+ position: relative;
+}
+
+.stepName {
+ display: none;
+ text-align: center;
+ margin-bottom: var(--spacing-12);
+ font-weight: var(--typography-paragraph-bold-font-weight);
+ color: var(--color-gray-600);
+}
+
+.stepName.isCurrent {
+ color: var(--color-purple-800);
+}
+
+.stepIcon {
+ color: var(--color-purple-800);
+ position: absolute;
+ width: var(--progress-stepper-indicator-size);
+ height: var(--progress-stepper-indicator-size);
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+}
+
+.stepIcon.isCompleted {
+ color: var(--color-green-500);
+}
+
+.stepDivider {
+ height: 0;
+ display: flex;
+ position: absolute;
+ flex-grow: 1;
+ min-width: calc(100% - var(--spacing-24));
+ border: solid var(--spacing-1) var(--color-gray-300);
+ margin: 0;
+ border-radius: var(--border-solid-border-radius);
+ left: 100%;
+
+ /* sets fron the bottom to the centre of the dot */
+ top: calc(100% - calc(var(--progress-stepper-indicator-size) / 2));
+ transform: translateX(-50%);
+
+ [dir="rtl"] & {
+ left: unset;
+ right: 100%;
+ transform: translateX(50%);
+ }
+}
+
+.stepperDescription {
+ display: flex;
+ justify-content: center;
+
+ @media (width >= 768px) {
+ /* sr hidden styles */
+ position: absolute;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ }
+}
+
+/* Some defensive CSS for many steps on desktop screens */
+@container step (width >= 4.5rem) {
+ .stepName {
+ display: inline;
+ }
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.spec.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.spec.tsx
new file mode 100644
index 00000000000..2be118e09b0
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.spec.tsx
@@ -0,0 +1,45 @@
+import React from "react"
+import { render, screen } from "@testing-library/react"
+import { ProgressStepper, ProgressStepperProps } from "./"
+
+const defaultArgs = {
+ steps: [
+ { label: "Settings", id: "settings-step" },
+ { label: "Questions", id: "questions-step" },
+ { label: "Preview", id: "preview-step" },
+ { label: "Employees", id: "employees-step" },
+ { label: "Schedule", id: "schedule-step" },
+ ],
+} satisfies Pick
+
+describe(" ", () => {
+ it("renders the correct number of steps", () => {
+ render( )
+ expect(screen.getAllByRole("listitem").length).toBe(5)
+ })
+ it("tracks the correct position of the active step", () => {
+ render( )
+ screen.getByText("Current: Settings")
+ expect(
+ screen.getByText(`Step 1 of ${defaultArgs.steps.length}`)
+ ).toBeInTheDocument()
+ })
+ it("renders the correct number of completed steps with an accessible name", () => {
+ render( )
+ expect(screen.getAllByText("Completed:", { exact: false }).length).toBe(2)
+ })
+ it("renders the correct number of steps not started with an accessible name", () => {
+ render( )
+ expect(screen.getAllByText("Not started:", { exact: false }).length).toBe(2)
+ })
+ it("renders all steps as complete if the provided the `isComplete` prop", () => {
+ render(
+
+ )
+ expect(screen.getAllByText("Completed:", { exact: false }).length).toBe(5)
+ })
+})
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.tsx
new file mode 100644
index 00000000000..5d9e4427705
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/ProgressStepper.tsx
@@ -0,0 +1,154 @@
+import React from "react"
+import classnames from "classnames"
+import {
+ IndicatorActiveIcon,
+ IndicatorInactiveIcon,
+ SuccessIcon,
+} from "~components/Icon"
+import { Text } from "~components/Text"
+import { VisuallyHidden } from "~components/VisuallyHidden"
+import styles from "./ProgressStepper.module.css"
+
+export type Step = {
+ id: string
+ label: string
+}
+
+export type Steps = [Step, ...Step[]]
+
+export type ProgressStepperProps = {
+ /** The id reference to within a Step object */
+ currentStepId: Step["id"]
+ /** A non-empty array of Steps */
+ steps: Steps
+ isComplete?: boolean
+}
+
+const getStepStatus = (
+ isComplete: boolean,
+ isCurrentStep: boolean,
+ step: Step,
+ index: number
+): {
+ icon: JSX.Element
+ accessibleName: string
+} => {
+ if (isComplete) {
+ return {
+ icon: (
+
+ ),
+ accessibleName: `Completed: ${step.label}`,
+ }
+ }
+ if (isCurrentStep) {
+ return {
+ icon: (
+
+ ),
+ accessibleName: `Current: ${step.label}`,
+ }
+ }
+ return {
+ icon: (
+
+ ),
+ accessibleName: `Not started: ${step.label}`,
+ }
+}
+
+export const ProgressStepper = ({
+ currentStepId,
+ steps,
+ isComplete = false,
+ ...restprops
+}: ProgressStepperProps): JSX.Element => {
+ const currentStepIndex = steps.findIndex(
+ stepItem => stepItem.id === currentStepId
+ )
+
+ return (
+
+
+ {steps.map((step, index: number) => {
+ const isCurrentStep = currentStepIndex === index
+ const isCompletedStep = index < currentStepIndex || isComplete
+ const { accessibleName, icon: Icon } = getStepStatus(
+ isCompletedStep,
+ isCurrentStep,
+ step,
+ index
+ )
+ return (
+
+
+
+ {/* will need to be translated */}
+ {accessibleName}
+
+
+ {step.label}
+
+
+
+ {Icon}
+
+
+ {index < steps.length - 1 && (
+
+ )}
+
+
+ )
+ })}
+
+
+ Step {currentStepIndex + 1} of {steps.length}
+
+
+ )
+}
+
+ProgressStepper.displayName = "Workflow.ProgressStepper"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/index.ts
new file mode 100644
index 00000000000..439d643ed15
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/ProgressStepper/index.ts
@@ -0,0 +1 @@
+export * from "./ProgressStepper"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/FooterRoot.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/FooterRoot.module.css
new file mode 100644
index 00000000000..ec38b345a02
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/FooterRoot.module.css
@@ -0,0 +1,20 @@
+.footerRoot {
+ display: grid;
+ grid-template-areas: "prev stepper next";
+ grid-template-columns: 1fr 2fr 1fr;
+ flex-grow: 1;
+ justify-content: center;
+ align-items: center;
+ padding: var(--spacing-24) var(--spacing-12);
+ background: var(--color-white);
+ gap: var(--spacing-16);
+ border-top: 2px solid rgba(var(--color-gray-600-rgb), 0.1);
+
+ @media (width >= 768px) {
+ grid-template-columns: 1fr 5fr 1fr;
+ padding: var(--spacing-24) var(--spacing-32);
+ position: sticky;
+ bottom: 0;
+ z-index: 1;
+ }
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/Root.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/Root.tsx
new file mode 100644
index 00000000000..1f7105ea9a9
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/Root.tsx
@@ -0,0 +1,23 @@
+import React, { HTMLAttributes } from "react"
+import classnames from "classnames"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./FooterRoot.module.css"
+
+export type FooterRootProps = OverrideClassName<
+ HTMLAttributes
+>
+
+export const FooterRoot = ({
+ children,
+ classNameOverride,
+ ...restProps
+}: FooterRootProps): JSX.Element => (
+
+)
+
+FooterRoot.displayName = "Workflow.FooterRoot"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/index.ts
new file mode 100644
index 00000000000..aee034e3871
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/Root/index.ts
@@ -0,0 +1 @@
+export * from "./Root"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/index.ts
new file mode 100644
index 00000000000..f379a3338d7
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/components/index.ts
@@ -0,0 +1,3 @@
+export * from "./Root"
+export * from "./ProgressStepper"
+export * from "./FooterActions"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/index.ts
new file mode 100644
index 00000000000..5bbffa1ee5e
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Footer/index.ts
@@ -0,0 +1,2 @@
+export * from "./Footer"
+export * from "./components"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/Header.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/Header.tsx
new file mode 100644
index 00000000000..3153df85133
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/Header.tsx
@@ -0,0 +1,31 @@
+import React from "react"
+import {
+ HeaderRoot,
+ Branding,
+ Titles,
+ Actions,
+ WorkflowActionsProps,
+ WorkflowTitlesProps,
+} from "./components"
+
+export type HeaderProps = WorkflowTitlesProps & WorkflowActionsProps
+
+export const Header = ({
+ workflowName,
+ stepName,
+ statusTag,
+ headerActions,
+ ...restProps
+}: HeaderProps): JSX.Element => (
+
+
+
+
+
+)
+
+Header.displayName = "Workflow.Header"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.module.css
new file mode 100644
index 00000000000..b274b395260
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.module.css
@@ -0,0 +1,15 @@
+.actions {
+ grid-area: actions;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ justify-content: center;
+ align-items: center;
+
+ @media (width >= 768px) {
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: flex-end;
+ margin-top: calc(-1 * var(--spacing-12));
+ }
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.tsx
new file mode 100644
index 00000000000..06e15486dc9
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/Actions.tsx
@@ -0,0 +1,24 @@
+import React, { HTMLAttributes } from "react"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Actions.module.css"
+
+export type WorkflowActionsProps = {
+ /**
+ * Header actions will render in order of the array.
+ */
+ headerActions?: JSX.Element[]
+} & OverrideClassName, "children">>
+
+/** A wrapper for an exit trigger (and other) actions of the Header Workflow */
+export const Actions = ({
+ headerActions,
+ ...restProps
+}: WorkflowActionsProps): JSX.Element => (
+
+ {headerActions?.map((action, index) => (
+
+ ))}
+
+)
+
+Actions.displayName = "Workflow.Actions"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/index.ts
new file mode 100644
index 00000000000..32a0903d4a8
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Actions/index.ts
@@ -0,0 +1 @@
+export * from "./Actions"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.module.css
new file mode 100644
index 00000000000..aef8c2293b5
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.module.css
@@ -0,0 +1,15 @@
+.branding {
+ justify-content: center;
+ grid-area: branding;
+ display: flex;
+ flex-grow: 1;
+ padding-top: var(--spacing-4);
+
+ @media (width >= 768px) {
+ justify-content: unset;
+ }
+}
+
+.logo {
+ flex-basis: 7.5rem;
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.tsx
new file mode 100644
index 00000000000..24ff1e22fea
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/Branding.tsx
@@ -0,0 +1,20 @@
+import React, { HTMLAttributes } from "react"
+import { Brand, BrandProps } from "~components/Brand"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Branding.module.css"
+
+export type WorflowBrandingProps = {
+ variant?: BrandProps["variant"]
+ alt: string
+} & OverrideClassName>
+
+export const Branding = ({
+ variant = "logo-horizontal",
+ alt,
+}: WorflowBrandingProps): JSX.Element => (
+
+
+
+)
+
+Branding.displayName = "Workflow.Branding"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/index.ts
new file mode 100644
index 00000000000..6c0671616d5
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Branding/index.ts
@@ -0,0 +1 @@
+export * from "./Branding"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.module.css
new file mode 100644
index 00000000000..efce1ce0673
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.module.css
@@ -0,0 +1,20 @@
+.root {
+ display: grid;
+ background-color: var(--color-white);
+ grid-template: "branding" min-content "titles" max-content "actions" min-content / 1fr;
+ flex-grow: 1;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ padding: var(--spacing-24);
+ gap: var(--spacing-16);
+ border-bottom: 2px solid rgb(var(--color-gray-600-rgb), 0.1);
+
+ @media (width >= 768px) {
+ align-items: start;
+ grid-template: "branding titles actions" min-content / 1fr max-content 1fr;
+ position: sticky;
+ top: 0;
+ z-index: 1;
+ }
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.tsx
new file mode 100644
index 00000000000..bd693465098
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/Root.tsx
@@ -0,0 +1,20 @@
+import React, { HTMLAttributes } from "react"
+import classnames from "classnames"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Root.module.css"
+
+export type HeaderRootProps = OverrideClassName<
+ HTMLAttributes
+>
+
+export const HeaderRoot = ({
+ children,
+ classNameOverride,
+ ...restProps
+}: HeaderRootProps): JSX.Element => (
+
+)
+
+HeaderRoot.displayName = "Workflow.HeaderRoot"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/index.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/index.tsx
new file mode 100644
index 00000000000..aee034e3871
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Root/index.tsx
@@ -0,0 +1 @@
+export * from "./Root"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.module.css
new file mode 100644
index 00000000000..994e37f5cfa
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.module.css
@@ -0,0 +1,21 @@
+.titles {
+ grid-area: titles;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ flex-grow: 1;
+}
+
+.pageTitle {
+ display: flex;
+ flex-direction: column;
+}
+
+.prefix {
+ margin-bottom: var(--spacing-4);
+}
+
+.statusTag {
+ margin-top: var(--spacing-8);
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.tsx
new file mode 100644
index 00000000000..59b48c38c37
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/Titles.tsx
@@ -0,0 +1,44 @@
+import React, { HTMLAttributes, ReactNode } from "react"
+import { Heading } from "~components/Heading"
+import { VisuallyHidden } from "~components/VisuallyHidden"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Titles.module.css"
+
+export type WorkflowTitlesProps = {
+ workflowName: string
+ stepName: string
+ statusTag?: ReactNode
+} & OverrideClassName>
+
+export const Titles = ({
+ workflowName,
+ stepName,
+ statusTag,
+ ...restProps
+}: WorkflowTitlesProps): JSX.Element => (
+
+
+
+ {workflowName}
+ :
+
+ {stepName}
+
+ {statusTag && (
+ // status may need to be update by a fetch
+
{statusTag}
+ )}
+
+)
+
+Titles.displayName = "Workflow.Titles"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/index.ts
new file mode 100644
index 00000000000..93a7f43ed19
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/Titles/index.ts
@@ -0,0 +1 @@
+export * from "./Titles"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/index.ts
new file mode 100644
index 00000000000..cac0f7231b6
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/components/index.ts
@@ -0,0 +1,4 @@
+export * from "./Titles"
+export * from "./Actions"
+export * from "./Branding"
+export * from "./Root"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/index.ts
new file mode 100644
index 00000000000..46c5e0e973c
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Header/index.ts
@@ -0,0 +1,2 @@
+export * from "./Header"
+export * from "./components"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.module.css
new file mode 100644
index 00000000000..68f297a744d
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.module.css
@@ -0,0 +1,4 @@
+.main {
+ /* This is set so children will sit beneath the header and footer when sticky */
+ z-index: 0;
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.tsx
new file mode 100644
index 00000000000..618bfd7edd9
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/Main.tsx
@@ -0,0 +1,22 @@
+import React, { HTMLAttributes, ReactNode } from "react"
+import classnames from "classnames"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Main.module.css"
+
+export type WorkflowMainProps = OverrideClassName<
+ HTMLAttributes
+> & {
+ children: ReactNode
+}
+
+export const Main = ({
+ children,
+ classNameOverride,
+ ...restProps
+}: WorkflowMainProps): JSX.Element => (
+
+ {children}
+
+)
+
+Main.displayName = "Workflow.Main"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/index.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/index.tsx
new file mode 100644
index 00000000000..3c0d2743028
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Main/index.tsx
@@ -0,0 +1 @@
+export * from "./Main"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.module.css b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.module.css
new file mode 100644
index 00000000000..93553ac28e4
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.module.css
@@ -0,0 +1,7 @@
+.wrapper {
+ display: grid;
+ grid-template-rows: min-content 1fr min-content;
+ position: relative;
+ min-height: 100vh;
+ background: var(--color-gray-100);
+}
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.tsx b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.tsx
new file mode 100644
index 00000000000..cbed6d1ad8a
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/Wrapper.tsx
@@ -0,0 +1,22 @@
+import React, { HTMLAttributes, ReactNode } from "react"
+import classnames from "classnames"
+import { OverrideClassName } from "~components/types/OverrideClassName"
+import styles from "./Wrapper.module.css"
+
+export type WorkflowWrapperProps = OverrideClassName<
+ HTMLAttributes
+> & {
+ children: ReactNode
+}
+
+export const Wrapper = ({
+ children,
+ classNameOverride,
+ ...restProps
+}: WorkflowWrapperProps): JSX.Element => (
+
+ {children}
+
+)
+
+Wrapper.displayName = "Workflow.Wrapper"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/index.ts
new file mode 100644
index 00000000000..de73e491dd8
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/Wrapper/index.ts
@@ -0,0 +1 @@
+export * from "./Wrapper"
diff --git a/packages/components/src/__layout__/Workflow/v3/subcomponents/index.ts b/packages/components/src/__layout__/Workflow/v3/subcomponents/index.ts
new file mode 100644
index 00000000000..b652662c049
--- /dev/null
+++ b/packages/components/src/__layout__/Workflow/v3/subcomponents/index.ts
@@ -0,0 +1,4 @@
+export * from "./Footer"
+export * from "./Header"
+export * from "./Main"
+export * from "./Wrapper"
diff --git a/packages/components/src/__layout__/v1.ts b/packages/components/src/__layout__/v1.ts
new file mode 100644
index 00000000000..df726afd7ef
--- /dev/null
+++ b/packages/components/src/__layout__/v1.ts
@@ -0,0 +1 @@
+export * from "./Workflow/v1"
diff --git a/packages/components/src/__layout__/v2.ts b/packages/components/src/__layout__/v2.ts
new file mode 100644
index 00000000000..eb67aa773a6
--- /dev/null
+++ b/packages/components/src/__layout__/v2.ts
@@ -0,0 +1 @@
+export * from "./Workflow/v2"
diff --git a/packages/components/src/__layout__/v3.ts b/packages/components/src/__layout__/v3.ts
new file mode 100644
index 00000000000..1fb6cca756a
--- /dev/null
+++ b/packages/components/src/__layout__/v3.ts
@@ -0,0 +1 @@
+export * from "./Workflow/v3"
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index ca1d8135b1f..95ad718095e 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -57,7 +57,7 @@ export * from "./ToggleSwitch"
export * from "./utils"
export * from "./VisuallyHidden"
export * from "./Well"
-export * from "./Workflow"
+export * from "./__layout__/Workflow/v1"
export * from "./__overlays__/Tooltip/v1"
export * from "./__actions__/Menu/v1"
export * from "./__actions__/Button/v1"
diff --git a/packages/components/v1/layout/package.json b/packages/components/v1/layout/package.json
new file mode 100644
index 00000000000..a7b33c0c287
--- /dev/null
+++ b/packages/components/v1/layout/package.json
@@ -0,0 +1,5 @@
+{
+ "main": "../../dist/cjs/layoutV1.cjs",
+ "module": "../../dist/esm/layoutV1.mjs",
+ "types": "../../dist/types/__layout__/v1.d.ts"
+}
diff --git a/packages/components/v2/layout/package.json b/packages/components/v2/layout/package.json
new file mode 100644
index 00000000000..320370f1250
--- /dev/null
+++ b/packages/components/v2/layout/package.json
@@ -0,0 +1,5 @@
+{
+ "main": "../../dist/cjs/layoutV2.cjs",
+ "module": "../../dist/esm/layoutV2.mjs",
+ "types": "../../dist/types/__layout__/v2.d.ts"
+}
diff --git a/packages/components/v3/layout/package.json b/packages/components/v3/layout/package.json
new file mode 100644
index 00000000000..85f7c4b8c7f
--- /dev/null
+++ b/packages/components/v3/layout/package.json
@@ -0,0 +1,5 @@
+{
+ "main": "../../dist/cjs/layoutV3.cjs",
+ "module": "../../dist/esm/layoutV3.mjs",
+ "types": "../../dist/types/__layout__/v3.d.ts"
+}