diff --git a/src/layout/Stepper/Step.tsx b/src/layout/Stepper/Step.tsx new file mode 100644 index 00000000..5a738d39 --- /dev/null +++ b/src/layout/Stepper/Step.tsx @@ -0,0 +1,17 @@ +import React, { FC, PropsWithChildren } from 'react'; + +export interface StepProps extends PropsWithChildren { + /** + * Optional Text of the marker + */ + markerLabel?: string; + + /** + * CSS Classname to applied to the step + */ + className?: string; +} + +export const Step: FC = ({ children, className }) => ( +
{children}
+); diff --git a/src/layout/Stepper/Stepper.story.tsx b/src/layout/Stepper/Stepper.story.tsx new file mode 100644 index 00000000..8cdacee9 --- /dev/null +++ b/src/layout/Stepper/Stepper.story.tsx @@ -0,0 +1,231 @@ +import { Stepper } from './Stepper'; +import { Step } from './Step'; + +export default { + title: 'Components/Layout/Stepper', + component: Stepper +}; + +export const Markers = () => ( + + +
+ + 03/01/2024, 8:00 AM + + + Austin{' '} + + created ticket + + +
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + Backlog + to In + Progress + +
+ This looks fine, might've missed it but maybe we can add a link to the + website where we also have the video of how to use the plug in? + Otherwise this is a nice addition. +
+
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + In Progress + to Done + +
+
+
+); + +export const Numbered = () => ( + + +
+ + 03/01/2024, 8:00 AM + + + Austin{' '} + + created ticket + + +
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + Backlog + to In + Progress + +
+ This looks fine, might've missed it but maybe we can add a link to the + website where we also have the video of how to use the plug in? + Otherwise this is a nice addition. +
+
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + In Progress + to Done + +
+
+
+); + +export const Labels = () => ( + + +
+ + 03/01/2024, 8:00 AM + + + Austin{' '} + + created ticket + + +
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + Backlog + to In + Progress + +
+ This looks fine, might've missed it but maybe we can add a link to the + website where we also have the video of how to use the plug in? + Otherwise this is a nice addition. +
+
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + In Progress + to Done + +
+
+
+); + +export const Mixed = () => ( + + +
+ + 03/01/2024, 8:00 AM + + + Austin{' '} + + created ticket + + +
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + Backlog + to In + Progress + +
+ This looks fine, might've missed it but maybe we can add a link to the + website where we also have the video of how to use the plug in? + Otherwise this is a nice addition. +
+
+
+ +
+ + 03/01/2024, 8:00 AM + + + Austin + + {' '} + changed statues from{' '} + + In Progress + to Done + +
+
+
+); diff --git a/src/layout/Stepper/Stepper.tsx b/src/layout/Stepper/Stepper.tsx new file mode 100644 index 00000000..a509a95b --- /dev/null +++ b/src/layout/Stepper/Stepper.tsx @@ -0,0 +1,92 @@ +import { StepperTheme } from '@/layout'; +import { cn, useComponentTheme } from '@/utils'; +import React, { Children, FC, Fragment, PropsWithChildren } from 'react'; + +import { Step, StepProps } from './Step'; + +export interface StepperProps extends PropsWithChildren { + /** + * Currently active step + */ + activeStep?: number; + + /** + * Theme for the Stepper. + */ + theme?: StepperTheme; + + /** + * Show number for every step + */ + numbered?: boolean; +} + +export const Stepper: FC = ({ + activeStep = 0, + children, + numbered = false, + theme: customTheme +}) => { + const theme: StepperTheme = useComponentTheme('stepper', customTheme); + + const childrenStepProps = Children.toArray(children) + .filter((child: any) => child.type?.name === Step.name) + .map((child: any) => child.props); + + const totalSteps = childrenStepProps.length - 1; + + return ( +
+ {childrenStepProps.map((props: StepProps, index) => ( + +
+
+ {/* Numbered marker */} + {numbered && ( +
+ {index + 1} +
+ )} + {/* Labeled marker */} + {!numbered && props.markerLabel && ( +
+
+ {props.markerLabel} +
+ )} + {/* Dot marker */} + {!numbered && !props.markerLabel && ( +
+ )} +
+
+ + + ))} +
+ ); +}; diff --git a/src/layout/Stepper/StepperTheme.tsx b/src/layout/Stepper/StepperTheme.tsx new file mode 100644 index 00000000..c6602404 --- /dev/null +++ b/src/layout/Stepper/StepperTheme.tsx @@ -0,0 +1,38 @@ +export interface StepperTheme { + base: string; + step: { + base: string; + marker: { + container: string; + base: string; + active: string; + label: { + base: string; + active: string; + }; + }; + active: string; + content: string; + }; +} + +export const stepperTheme: StepperTheme = { + base: 'grid grid-cols-[min-content_1fr] gap-x-3', + step: { + base: 'border-l border-solid border-panel-accent translate-x-1/2', + marker: { + base: 'rounded-full w-[9px] h-[9px] bg-surface', + container: + 'w-max pt-1 pb-0.5 backdrop-blur-md -translate-x-[calc(50%+0.5px)]', + active: 'bg-info', + label: { + base: 'flex flex-row items-center gap-1 border border-solid border-surface px-3 py-1 rounded-[20px]', + active: 'border-info bg-info-background' + } + }, + active: 'border-primary', + content: 'pb-6' + } +}; + +export const legacyStepperTheme: StepperTheme = stepperTheme; diff --git a/src/layout/Stepper/index.ts b/src/layout/Stepper/index.ts new file mode 100644 index 00000000..74f1addd --- /dev/null +++ b/src/layout/Stepper/index.ts @@ -0,0 +1,2 @@ +export * from './Stepper'; +export * from './StepperTheme'; diff --git a/src/layout/index.ts b/src/layout/index.ts index 5f9f2ec7..59f0a852 100644 --- a/src/layout/index.ts +++ b/src/layout/index.ts @@ -9,3 +9,4 @@ export * from './Tree'; export * from './VerticalSpacer'; export * from './Tabs'; export * from './Breadcrumbs'; +export * from './Stepper'; diff --git a/src/utils/Theme/themes/theme.ts b/src/utils/Theme/themes/theme.ts index 9aed6b56..f840e331 100644 --- a/src/utils/Theme/themes/theme.ts +++ b/src/utils/Theme/themes/theme.ts @@ -115,7 +115,10 @@ import { legacyJsonTreeTheme, breadcrumbsTheme, BreadcrumbsTheme, - legacyBreadcrumbTheme + legacyBreadcrumbTheme, + StepperTheme, + stepperTheme, + legacyStepperTheme } from '@/layout'; import { @@ -186,6 +189,7 @@ export interface ReablocksTheme { pager: PagerTheme; tabs: TabsTheme; breadcrumbs: BreadcrumbsTheme; + stepper: StepperTheme; }; } @@ -232,7 +236,8 @@ export const theme: ReablocksTheme = { pager: pagerTheme, tabs: tabsTheme, jsonTree: jsonTreeTheme, - breadcrumbs: breadcrumbsTheme + breadcrumbs: breadcrumbsTheme, + stepper: stepperTheme } }; @@ -279,6 +284,7 @@ export const legacyThemeVars: ReablocksTheme = { pager: legacyPagerTheme, tabs: legacyTabsTheme, jsonTree: legacyJsonTreeTheme, - breadcrumbs: legacyBreadcrumbTheme + breadcrumbs: legacyBreadcrumbTheme, + stepper: legacyStepperTheme } };