From 52073e04e0694887ce123b3f3d6582eed1e2083d Mon Sep 17 00:00:00 2001 From: HCarrer Date: Mon, 29 Apr 2024 18:51:58 -0300 Subject: [PATCH 1/4] component implementation --- styleguide/src/Navigation/Stepper/index.tsx | 95 +++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 styleguide/src/Navigation/Stepper/index.tsx diff --git a/styleguide/src/Navigation/Stepper/index.tsx b/styleguide/src/Navigation/Stepper/index.tsx new file mode 100644 index 0000000..fe568d3 --- /dev/null +++ b/styleguide/src/Navigation/Stepper/index.tsx @@ -0,0 +1,95 @@ +import React from 'react' + +export const Stepper: React.FC = React.memo( + ({ + className = '', + currentStep = 0, + steps = [], + showText = false, + }) => { + const getColors = (step: number) => { + if(currentStep > step) return 'bg-primary border-primary' + if(currentStep == step) return 'bg-inverted-1 border-inverted-1' + return 'bg-base-4 border-base-4' + } + + return( +
+ {steps.map((item, index) => { + return ( +
+ {!showText && index > 0 && ( +
= item.step ? 'bg-primary' : 'bg-base-4'}`}/>) + } +
+ item.handleClick?.()} + className={`font-bold ${item.handleClick ? 'cursor-pointer' : ''}`} + > + {item.step} + +
+ {showText && ( + item.handleClick?.()} + className={`text-center my-auto text-sm ${showText ? '' : ''} + ${item.step < 2 ? 'cursor-pointer' : ''} + ${currentStep == item.step ? 'font-bold' : ''}`} + > + {item.text} + + )} + {!showText && index < steps.length - 1 && ( +
item.step ? 'bg-primary' : 'bg-base-4'}`}/>) + } +
+ ) + })} +
+ ) + } +) + +type StepType = { + step: number, + text?: string, + handleClick?: Function, + customClassName?: string +} + +export interface StepperProps { + /** + * Custom class name + * */ + className?: string + /** + * Current page step + * */ + currentStep: number + /** + * Array of steps containing the step number (1, 2, 3, ..., n), + * text with step's title (optional) and a handler for the + * step's click (optional) + * */ + steps: StepType[] + /** + * Shows step text instead of linking lines + * */ + showText?: boolean + /** + * Function to handle step click + * */ +} From f2d644a06bb04d7f126626627aa7ea6078af5f35 Mon Sep 17 00:00:00 2001 From: HCarrer Date: Mon, 29 Apr 2024 18:52:07 -0300 Subject: [PATCH 2/4] stepper stories --- .../Navigation/Stepper/Stepper.stories.tsx | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 styleguide/src/Navigation/Stepper/Stepper.stories.tsx diff --git a/styleguide/src/Navigation/Stepper/Stepper.stories.tsx b/styleguide/src/Navigation/Stepper/Stepper.stories.tsx new file mode 100644 index 0000000..6c31f86 --- /dev/null +++ b/styleguide/src/Navigation/Stepper/Stepper.stories.tsx @@ -0,0 +1,68 @@ +import React from 'react' +import { Story, Meta } from '@storybook/react' + +import { Stepper, StepperProps } from '.' + +export default { + title: 'Navigation/Stepper', + component: Stepper, + parameters: { + layout: 'padded', + } +} as Meta + +const Template: Story = args => + +export const Default = Template.bind({}) +Default.args = { + steps: [ + {step: 1, text: 'Step 1'}, + {step: 2, text: 'Step 2'}, + {step: 3, text: 'Step 3'} + ], + currentStep: 2 +} + +export const NoText = Template.bind({}) +NoText.args = { + steps: [ + {step: 1, text: 'Step 1'}, + {step: 2, text: 'Step 2'}, + {step: 3, text: 'Step 3'} + ], + currentStep: 2, + showText: false +} + +export const WithText = Template.bind({}) +WithText.args = { + steps: [ + {step: 1, text: 'Step 1'}, + {step: 2, text: 'Step 2'}, + {step: 3, text: 'Step 3'} + ], + currentStep: 2, + showText: true +} + +export const HandleClick = Template.bind({}) +HandleClick.args = { + steps: [ + {step: 1, text: 'Step 1', handleClick: () => alert(`Clicked on step 1!`)}, + {step: 2, text: 'Step 2', handleClick: () => alert(`Clicked on step 2!`)}, + {step: 3, text: 'Step 3', handleClick: () => alert(`Clicked on step 3!`)} + ], + currentStep: 2, + showText: false, +} + +export const CustomStepClassName = Template.bind({}) +CustomStepClassName.args = { + steps: [ + {step: 1, text: 'Step 1', customClassName: '!text-primary !bg-primary-light !border-primary'}, + {step: 2, text: 'Step 2', customClassName: '!text-warning !bg-warning-light !border-warning'}, + {step: 3, text: 'Step 3', customClassName: '!text-danger !bg-danger-light !border-danger'} + ], + currentStep: 2, + showText: false +} \ No newline at end of file From 311de4f07b98e7022fee6d83a8e3cdb232273b68 Mon Sep 17 00:00:00 2001 From: HCarrer Date: Mon, 29 Apr 2024 18:52:18 -0300 Subject: [PATCH 3/4] stepper stories tests --- .../src/Navigation/Stepper/Stepper.spec.tsx | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 styleguide/src/Navigation/Stepper/Stepper.spec.tsx diff --git a/styleguide/src/Navigation/Stepper/Stepper.spec.tsx b/styleguide/src/Navigation/Stepper/Stepper.spec.tsx new file mode 100644 index 0000000..bd07140 --- /dev/null +++ b/styleguide/src/Navigation/Stepper/Stepper.spec.tsx @@ -0,0 +1,68 @@ +import * as React from "react" +import { composeStories } from "@storybook/testing-react" +import { mount } from "@cypress/react" +import * as stories from "./Stepper.stories" + +const { Default, NoText, WithText, HandleClick, CustomStepClassName } = composeStories(stories) + +const specTitle = require('cypress-sonarqube-reporter/specTitle'); +describe(specTitle('Stepper tests'), () => { + + it('Default', () => { + mount() + cy.get('#stepsContainer').within(() => { + cy.get('#stepCircle1').should('have.class', 'bg-primary').contains('1') + cy.get('#stepCircle2').should('have.class', 'bg-inverted-1').contains('2') + cy.get('#stepCircle3').should('have.class', 'bg-base-4').contains('3') + }) + }) + + it('NoText', () => { + mount() + cy.get('#stepsContainer').within(() => { + cy.get('#stepCircle1').should('have.class', 'bg-primary').contains('1') + cy.get('#rightLinkStep1').should('have.class', 'absolute').and('have.class', '-right-5').and('have.class', 'bg-primary') + cy.get('#stepCircle2').should('have.class', 'bg-inverted-1').contains('2') + cy.get('#leftLinkStep2').should('have.class', 'absolute').and('have.class', '-left-5').and('have.class', 'bg-primary') + cy.get('#rightLinkStep2').should('have.class', 'absolute').and('have.class', '-right-5').and('have.class', 'bg-base-4') + cy.get('#stepCircle3').should('have.class', 'bg-base-4').contains('3') + cy.get('#leftLinkStep3').should('have.class', 'absolute').and('have.class', '-left-5').and('have.class', 'bg-base-4') + }) + }) + + it('WithText', () => { + mount() + cy.get('#stepsContainer').within(() => { + cy.get('#stepCircle1').should('have.class', 'bg-primary').contains('1') + cy.get('#step1 span').should('have.class', 'text-center').contains('Step 1') + cy.get('#rightLinkStep1').should('not.exist') + cy.get('#step2 span').should('have.class', 'text-center').contains('Step 2') + cy.get('#leftLinkStep2').should('not.exist') + cy.get('#rightLinkStep2').should('not.exist') + cy.get('#step3 span').should('have.class', 'text-center').contains('Step 3') + cy.get('#leftLinkStep3').should('not.exist') + }) + }) + + it('HandleClick', () => { + mount() + cy.get('#stepsContainer').within(() => { + cy.get('#stepCircle1').should('have.class', 'bg-primary').contains('1') + cy.get('#stepCircle1').should(() => {alert(`Clicked on step 1!`)}) + cy.get('#stepCircle2').should('have.class', 'bg-inverted-1').contains('2') + cy.get('#stepCircle2').should(() => {alert(`Clicked on step 2!`)}) + cy.get('#stepCircle3').should('have.class', 'bg-base-4').contains('3') + cy.get('#stepCircle3').should(() => {alert(`Clicked on step 3!`)}) + }) + }) + + it('CustomStepClassName', () => { + mount() + cy.get('#stepsContainer').within(() => { + cy.get('#stepCircle1').should('have.class', '!bg-primary-light').and('have.class', '!border-primary').and('have.class', '!text-primary').contains('1') + cy.get('#stepCircle2').should('have.class', '!bg-warning-light').and('have.class', '!border-warning').and('have.class', '!text-warning').contains('2') + cy.get('#stepCircle3').should('have.class', '!bg-danger-light').and('have.class', '!border-danger').and('have.class', '!text-danger').contains('3') + }) + }) + +}) From 22a8dfd57ff1e58c707e271f775766046729b42e Mon Sep 17 00:00:00 2001 From: HCarrer Date: Mon, 29 Apr 2024 19:00:52 -0300 Subject: [PATCH 4/4] file linting --- styleguide/src/Navigation/Stepper/index.tsx | 49 ++++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/styleguide/src/Navigation/Stepper/index.tsx b/styleguide/src/Navigation/Stepper/index.tsx index fe568d3..b16f242 100644 --- a/styleguide/src/Navigation/Stepper/index.tsx +++ b/styleguide/src/Navigation/Stepper/index.tsx @@ -1,19 +1,13 @@ import React from 'react' export const Stepper: React.FC = React.memo( - ({ - className = '', - currentStep = 0, - steps = [], - showText = false, - }) => { + ({ className = '', currentStep = 0, steps = [], showText = false }) => { const getColors = (step: number) => { - if(currentStep > step) return 'bg-primary border-primary' - if(currentStep == step) return 'bg-inverted-1 border-inverted-1' + if (currentStep > step) return 'bg-primary border-primary' + if (currentStep === step) return 'bg-inverted-1 border-inverted-1' return 'bg-base-4 border-base-4' } - - return( + return (
= React.memo( className="flex flex-row items-center gap-y-2.5 gap-x-3.5 z-10 relative" > {!showText && index > 0 && ( -
= item.step ? 'bg-primary' : 'bg-base-4'}`}/>) - } +
= item.step ? 'bg-primary' : 'bg-base-4' + }`} + /> + )}
item.handleClick?.()} - className={`font-bold ${item.handleClick ? 'cursor-pointer' : ''}`} + className={`font-bold ${ + item.handleClick ? 'cursor-pointer' : '' + }`} > {item.step} @@ -47,14 +47,19 @@ export const Stepper: React.FC = React.memo( onClick={() => item.handleClick?.()} className={`text-center my-auto text-sm ${showText ? '' : ''} ${item.step < 2 ? 'cursor-pointer' : ''} - ${currentStep == item.step ? 'font-bold' : ''}`} - > + ${currentStep === item.step ? 'font-bold' : ''}`} + > {item.text} )} {!showText && index < steps.length - 1 && ( -
item.step ? 'bg-primary' : 'bg-base-4'}`}/>) - } +
item.step ? 'bg-primary' : 'bg-base-4' + }`} + /> + )}
) })} @@ -64,9 +69,9 @@ export const Stepper: React.FC = React.memo( ) type StepType = { - step: number, - text?: string, - handleClick?: Function, + step: number + text?: string + handleClick?: Function customClassName?: string }