Implement create flow topnav and footer
This commit is contained in:
@@ -15,7 +15,8 @@ interface LogoProps {
|
|||||||
| "headerLg"
|
| "headerLg"
|
||||||
| "headerXl"
|
| "headerXl"
|
||||||
| "footer"
|
| "footer"
|
||||||
| "footerLg";
|
| "footerLg"
|
||||||
|
| "createFlow";
|
||||||
showText?: boolean;
|
showText?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +115,13 @@ const Logo = memo<LogoProps>(({ size = "default", showText = true }) => {
|
|||||||
lineHeight: "leading-[calc(27.05px*2.05)]",
|
lineHeight: "leading-[calc(27.05px*2.05)]",
|
||||||
iconSize: "w-[calc(27.05px*2.05)] h-[calc(27.05px*2.05)]",
|
iconSize: "w-[calc(27.05px*2.05)] h-[calc(27.05px*2.05)]",
|
||||||
},
|
},
|
||||||
|
createFlow: {
|
||||||
|
containerHeight: "h-[30px] md:h-[41px]",
|
||||||
|
gap: "gap-[6px] md:gap-[8.28px]",
|
||||||
|
textSize: "text-[16.48px] md:text-[21.97px]",
|
||||||
|
lineHeight: "leading-[20.28px] md:leading-[27.05px]",
|
||||||
|
iconSize: "w-[20.28px] h-[20.28px] md:w-[27.05px] md:h-[27.05px]",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const config =
|
const config =
|
||||||
@@ -137,8 +145,10 @@ const Logo = memo<LogoProps>(({ size = "default", showText = true }) => {
|
|||||||
? sizes.headerXl
|
? sizes.headerXl
|
||||||
: size === "footer"
|
: size === "footer"
|
||||||
? sizes.footer
|
? sizes.footer
|
||||||
: size === "footerLg"
|
: size === "footerLg"
|
||||||
? sizes.footerLg
|
? sizes.footerLg
|
||||||
|
: size === "createFlow"
|
||||||
|
? sizes.createFlow
|
||||||
: sizes.default;
|
: sizes.default;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { memo } from "react";
|
||||||
|
import { CreateFlowFooterView } from "./CreateFlowFooter.view";
|
||||||
|
import type { CreateFlowFooterProps } from "./CreateFlowFooter.types";
|
||||||
|
|
||||||
|
const CreateFlowFooterContainer = memo<CreateFlowFooterProps>(
|
||||||
|
({ secondButton, progressBar = true, className = "" }) => {
|
||||||
|
return (
|
||||||
|
<CreateFlowFooterView
|
||||||
|
secondButton={secondButton}
|
||||||
|
progressBar={progressBar}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
CreateFlowFooterContainer.displayName = "CreateFlowFooter";
|
||||||
|
|
||||||
|
export default CreateFlowFooterContainer;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Type definitions for CreateFlowFooter component
|
||||||
|
*
|
||||||
|
* Footer component for the create rule flow with progress bar and buttons.
|
||||||
|
*/
|
||||||
|
export interface CreateFlowFooterProps {
|
||||||
|
/**
|
||||||
|
* The second button (typically "Next" button) to display on the right side
|
||||||
|
*/
|
||||||
|
secondButton?: React.ReactNode;
|
||||||
|
/**
|
||||||
|
* Whether to show the progress bar
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
progressBar?: boolean;
|
||||||
|
/**
|
||||||
|
* Additional CSS classes
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import ProportionBar from "../../progress/ProportionBar";
|
||||||
|
import Button from "../../buttons/Button";
|
||||||
|
import type { CreateFlowFooterProps } from "./CreateFlowFooter.types";
|
||||||
|
|
||||||
|
export function CreateFlowFooterView({
|
||||||
|
secondButton,
|
||||||
|
progressBar = true,
|
||||||
|
className = "",
|
||||||
|
}: CreateFlowFooterProps) {
|
||||||
|
return (
|
||||||
|
<footer
|
||||||
|
className={`sticky bottom-0 z-50 bg-black w-full ${className}`}
|
||||||
|
role="contentinfo"
|
||||||
|
aria-label="Create Flow Footer"
|
||||||
|
>
|
||||||
|
{/* Progress Bar - Top */}
|
||||||
|
{progressBar && (
|
||||||
|
<div className="px-[var(--spacing-measures-spacing-500,20px)] md:px-[var(--spacing-measures-spacing-1200,48px)] pt-[var(--spacing-measures-spacing-300,12px)]">
|
||||||
|
<ProportionBar progress="1-0" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Buttons Container */}
|
||||||
|
<div className="flex items-center justify-between mx-auto max-w-[639px] md:max-w-[1920px] px-[var(--spacing-measures-spacing-500,20px)] md:px-[var(--spacing-measures-spacing-1200,48px)] py-[var(--spacing-measures-spacing-300,12px)] gap-[var(--spacing-measures-spacing-300,12px)]">
|
||||||
|
{/* Back Button - Left */}
|
||||||
|
<Button
|
||||||
|
buttonType="ghost"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
className="md:!text-[14px] md:!leading-[16px] !text-[12px] !leading-[14px] !px-[var(--spacing-measures-spacing-200,8px)] md:!px-[var(--spacing-measures-spacing-250,10px)] !py-[var(--spacing-measures-spacing-200,8px)] md:!py-[var(--spacing-measures-spacing-250,10px)]"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{/* Second Button - Right */}
|
||||||
|
{secondButton && (
|
||||||
|
<div className="flex-shrink-0">{secondButton}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from "./CreateFlowFooter.container";
|
||||||
|
export type { CreateFlowFooterProps } from "./CreateFlowFooter.types";
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { memo } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { CreateFlowTopNavView } from "./CreateFlowTopNav.view";
|
||||||
|
import type { CreateFlowTopNavProps } from "./CreateFlowTopNav.types";
|
||||||
|
|
||||||
|
const CreateFlowTopNavContainer = memo<CreateFlowTopNavProps>(
|
||||||
|
({
|
||||||
|
hasShare = false,
|
||||||
|
hasExport = false,
|
||||||
|
hasEdit = false,
|
||||||
|
loggedIn = false,
|
||||||
|
onShare,
|
||||||
|
onExport,
|
||||||
|
onEdit,
|
||||||
|
onExit,
|
||||||
|
className = "",
|
||||||
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleExit = () => {
|
||||||
|
if (onExit) {
|
||||||
|
onExit();
|
||||||
|
} else {
|
||||||
|
// Default behavior: navigate to home
|
||||||
|
router.push("/");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CreateFlowTopNavView
|
||||||
|
hasShare={hasShare}
|
||||||
|
hasExport={hasExport}
|
||||||
|
hasEdit={hasEdit}
|
||||||
|
loggedIn={loggedIn}
|
||||||
|
onShare={onShare}
|
||||||
|
onExport={onExport}
|
||||||
|
onEdit={onEdit}
|
||||||
|
onExit={handleExit}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
CreateFlowTopNavContainer.displayName = "CreateFlowTopNav";
|
||||||
|
|
||||||
|
export default CreateFlowTopNavContainer;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Type definitions for CreateFlowTopNav component
|
||||||
|
*
|
||||||
|
* Top navigation bar for the create rule flow.
|
||||||
|
* Includes logo and action buttons (Share, Export, Edit, Exit).
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface CreateFlowTopNavProps {
|
||||||
|
/**
|
||||||
|
* Whether to show the Share button
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
hasShare?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether to show the Export button
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
hasExport?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether to show the Edit button
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
hasEdit?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether the user is logged in
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
loggedIn?: boolean;
|
||||||
|
/**
|
||||||
|
* Callback when Share button is clicked
|
||||||
|
*/
|
||||||
|
onShare?: () => void;
|
||||||
|
/**
|
||||||
|
* Callback when Export button is clicked
|
||||||
|
*/
|
||||||
|
onExport?: () => void;
|
||||||
|
/**
|
||||||
|
* Callback when Edit button is clicked
|
||||||
|
*/
|
||||||
|
onEdit?: () => void;
|
||||||
|
/**
|
||||||
|
* Callback when Exit/Save & Exit button is clicked
|
||||||
|
*/
|
||||||
|
onExit?: () => void;
|
||||||
|
/**
|
||||||
|
* Additional CSS classes
|
||||||
|
*/
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import Logo from "../../icons/Logo";
|
||||||
|
import Button from "../../buttons/Button";
|
||||||
|
import type { CreateFlowTopNavProps } from "./CreateFlowTopNav.types";
|
||||||
|
|
||||||
|
export function CreateFlowTopNavView({
|
||||||
|
hasShare = false,
|
||||||
|
hasExport = false,
|
||||||
|
hasEdit = false,
|
||||||
|
loggedIn = false,
|
||||||
|
onShare,
|
||||||
|
onExport,
|
||||||
|
onEdit,
|
||||||
|
onExit,
|
||||||
|
className = "",
|
||||||
|
}: CreateFlowTopNavProps) {
|
||||||
|
const exitButtonText = loggedIn ? "Save & Exit" : "Exit";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header
|
||||||
|
className={`bg-black w-full border-b border-[var(--color-border-default-tertiary)] ${className}`}
|
||||||
|
role="banner"
|
||||||
|
aria-label="Create Rule Flow Navigation"
|
||||||
|
>
|
||||||
|
<nav
|
||||||
|
className="flex items-center justify-between mx-auto max-w-[639px] md:max-w-[1920px] px-[var(--spacing-measures-spacing-500,20px)] md:px-[48px] py-[var(--spacing-measures-spacing-300,12px)] md:py-[var(--spacing-measures-spacing-016,16px)]"
|
||||||
|
role="navigation"
|
||||||
|
aria-label="Create Flow Navigation"
|
||||||
|
>
|
||||||
|
{/* Logo - Left */}
|
||||||
|
<Logo size="createFlow" showText={true} />
|
||||||
|
|
||||||
|
{/* Button Group - Right */}
|
||||||
|
<div className="flex items-center gap-[var(--spacing-scale-012,12px)]">
|
||||||
|
{hasShare && (
|
||||||
|
<Button
|
||||||
|
buttonType="outline"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
onClick={onShare}
|
||||||
|
ariaLabel="Share"
|
||||||
|
className="md:!text-[12px] md:!leading-[14px] !text-[10px] !leading-[12px] !px-[var(--spacing-scale-006,6px)] md:!px-[var(--spacing-scale-008,8px)] !py-[6px] md:!py-[8px] !border md:!border-[1.5px]"
|
||||||
|
>
|
||||||
|
Share
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasExport && (
|
||||||
|
<Button
|
||||||
|
buttonType="outline"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
onClick={onExport}
|
||||||
|
ariaLabel="Export"
|
||||||
|
className="justify-center gap-[var(--spacing-scale-002,2px)] !pl-[var(--spacing-scale-012,12px)] !pr-[var(--spacing-scale-006,6px)] md:!pr-[var(--spacing-scale-006,6px)] !text-[10px] md:!text-[12px] !leading-[12px] md:!leading-[14px] !py-[6px] md:!py-[8px] !border md:!border-[1.5px]"
|
||||||
|
>
|
||||||
|
<span>Export</span>
|
||||||
|
<svg
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
className="shrink-0 md:w-[14px] md:h-[14px]"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasEdit && (
|
||||||
|
<Button
|
||||||
|
buttonType="outline"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
onClick={onEdit}
|
||||||
|
ariaLabel="Edit"
|
||||||
|
className="md:!text-[12px] md:!leading-[14px] !text-[10px] !leading-[12px] !px-[var(--spacing-scale-006,6px)] md:!px-[var(--spacing-scale-008,8px)] !py-[6px] md:!py-[8px] !border md:!border-[1.5px]"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
buttonType="outline"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
onClick={onExit}
|
||||||
|
ariaLabel={exitButtonText}
|
||||||
|
className="md:!text-[12px] md:!leading-[14px] !text-[10px] !leading-[12px] !px-[var(--spacing-scale-006,6px)] md:!px-[var(--spacing-scale-008,8px)] !py-[6px] md:!py-[8px] !border md:!border-[1.5px]"
|
||||||
|
>
|
||||||
|
{exitButtonText}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from "./CreateFlowTopNav.container";
|
||||||
|
export type { CreateFlowTopNavProps } from "./CreateFlowTopNav.types";
|
||||||
+20
-1
@@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { CreateFlowProvider } from "./context/CreateFlowContext";
|
import { CreateFlowProvider } from "./context/CreateFlowContext";
|
||||||
|
import CreateFlowTopNav from "../components/utility/CreateFlowTopNav";
|
||||||
|
import CreateFlowFooter from "../components/utility/CreateFlowFooter";
|
||||||
|
import Button from "../components/buttons/Button";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout for the Create Rule Flow
|
* Layout for the Create Rule Flow
|
||||||
*
|
*
|
||||||
* Provides a full-screen layout without the root layout's TopNav/Footer.
|
* Provides a full-screen layout without the root layout's TopNav/Footer.
|
||||||
* This layout wraps all create flow pages and provides the CreateFlowContext.
|
* This layout wraps all create flow pages and provides the CreateFlowContext.
|
||||||
|
* Includes the create flow-specific TopNav and Footer components.
|
||||||
*/
|
*/
|
||||||
export default function CreateFlowLayout({
|
export default function CreateFlowLayout({
|
||||||
children,
|
children,
|
||||||
@@ -17,7 +21,22 @@ export default function CreateFlowLayout({
|
|||||||
return (
|
return (
|
||||||
<CreateFlowProvider>
|
<CreateFlowProvider>
|
||||||
<div className="min-h-screen bg-black flex flex-col">
|
<div className="min-h-screen bg-black flex flex-col">
|
||||||
{children}
|
<CreateFlowTopNav />
|
||||||
|
<main className="flex-1 overflow-auto">
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
<CreateFlowFooter
|
||||||
|
secondButton={
|
||||||
|
<Button
|
||||||
|
buttonType="filled"
|
||||||
|
palette="default"
|
||||||
|
size="xsmall"
|
||||||
|
className="md:!text-[14px] md:!leading-[16px] !text-[12px] !leading-[14px] !px-[var(--spacing-measures-spacing-200,8px)] md:!px-[var(--spacing-measures-spacing-250,10px)] !py-[var(--spacing-measures-spacing-200,8px)] md:!py-[var(--spacing-measures-spacing-250,10px)]"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CreateFlowProvider>
|
</CreateFlowProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user