From 2941d05a8f1599b10f8fc1658dab84346f632a0b Mon Sep 17 00:00:00 2001 From: Savut Sang Date: Fri, 9 Feb 2024 14:31:45 -0500 Subject: [PATCH 1/9] feat(ProgressTracker): non linear and clickable --- packages/react/src/components/icon/icon.tsx | 2 + .../progress-tracker.test.tsx | 52 +-- .../progress-tracker.test.tsx.snap | 339 ++++++++++-------- .../progress-tracker/progress-tracker.tsx | 232 +++++++----- .../react/src/icons/alert-filled-round.svg | 6 + packages/react/src/utils/range.ts | 2 +- packages/storybook/stories/icon-library.mdx | 3 + .../stories/progress-tracker.stories.tsx | 72 +++- 8 files changed, 436 insertions(+), 272 deletions(-) create mode 100644 packages/react/src/icons/alert-filled-round.svg diff --git a/packages/react/src/components/icon/icon.tsx b/packages/react/src/components/icon/icon.tsx index 37642ec4c9..b61cf7884c 100644 --- a/packages/react/src/components/icon/icon.tsx +++ b/packages/react/src/components/icon/icon.tsx @@ -55,10 +55,12 @@ import WarningFilled from '../../icons/warning-filled.svg'; import Equisoft from '../../logos/logo-equisoft-ico.svg'; import CaretDown from '../../icons/caret-down.svg'; import CaretRight from '../../icons/caret-right.svg'; +import AlertFilledRound from '../../icons/alert-filled-round.svg'; const iconMapping = { alertCircle: AlertCircle, alertFilled: AlertFilled, + alertFilledRound: AlertFilledRound, alertTriangle: AlertTriangle, alertOctagon: AlertOctagon, arrowDown: ArrowDown, diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx index 1e00184212..00b122f59f 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx @@ -2,9 +2,9 @@ import { shallow } from 'enzyme'; import { findByTestId, getByTestId } from '../../test-utils/enzyme-selectors'; import { renderWithProviders } from '../../test-utils/renderer'; import { range } from '../../utils/range'; -import { Progress, ProgressTracker } from './progress-tracker'; +import { ProgressTracker, ProgressTrackerStep } from './progress-tracker'; -function generateSteps(count: number): ProgressTracker[] { +function generateSteps(count: number): ProgressTrackerStep[] { return range(1, count).map((i) => ({ label: `Step ${i}` })); } @@ -12,86 +12,92 @@ describe('Progress Component', () => { it('should render all steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const allSteps = findByTestId(stepsWrapper, 'progress-step-', '^'); + const allSteps = findByTestId(stepsWrapper, 'progress-tracker-step-', '^'); expect(allSteps.length).toBe(3); }); it('should render all steps labels', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const allStepsLabels = findByTestId(stepsWrapper, 'progress-step-', '^').map((w) => w.text()); + const allStepsLabels = findByTestId(stepsWrapper, 'progress-tracker-step-', '^') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); expect(allStepsLabels).toEqual(expect.arrayContaining(['Step 1', 'Step 2', 'Step 3'])); }); - it('should have past steps', () => { + it('should have completed steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const pastSteps = findByTestId(stepsWrapper, 'progress-step-past').map((w) => w.text()); - expect(pastSteps).toEqual(expect.arrayContaining(['Step 1', 'Step 2'])); + const completedSteps = findByTestId(stepsWrapper, 'progress-tracker-step-completed') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); + expect(completedSteps).toEqual(expect.arrayContaining(['Step 1', 'Step 2'])); }); it('should have current step', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const currentStep = findByTestId(stepsWrapper, 'progress-step-current').map((w) => w.text()); + const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 2'])); }); it('should fallback to first step if value is less than 1', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const currentStep = findByTestId(stepsWrapper, 'progress-step-current').map((w) => w.text()); + const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 1'])); }); it('should fallback to last step if value is higher than number of steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const currentStep = findByTestId(stepsWrapper, 'progress-step-current').map((w) => w.text()); + const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 3'])); }); - it('should have future steps', () => { + it('should have incomplete steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); + const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const currentStep = findByTestId(stepsWrapper, 'progress-step-future').map((w) => w.text()); - expect(currentStep).toEqual(expect.arrayContaining(['Step 2', 'Step 3'])); + const incompleteStep = findByTestId(stepsWrapper, 'progress-tracker-step-incomplete') + .map((w) => findByTestId(w, 'progress-tracker-label').text()); + expect(incompleteStep).toEqual(expect.arrayContaining(['Step 2', 'Step 3'])); }); describe('Snapshots', () => { it('with labels', () => { const steps = generateSteps(3); - const wrapper = renderWithProviders(); + const wrapper = renderWithProviders(); expect(wrapper).toMatchSnapshot(); }); it('without labels', () => { - const steps: ProgressTracker[] = [{}, {}, {}]; + const steps: ProgressTrackerStep[] = [{}, {}, {}]; - const wrapper = renderWithProviders(); + const wrapper = renderWithProviders(); expect(wrapper).toMatchSnapshot(); }); diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap index a5b2ebffe4..864a23c888 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap @@ -1,38 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Progress Component Snapshots with labels 1`] = ` +.c6 { + border: 0; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + .c0 { position: relative; + padding: var(--spacing-2x) 0; width: 100%; } .c1 { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-color: #DBDEE1; - border: none; - bottom: 1.5rem; - color: #004E78; - height: 4px; - left: 16.666666666666668%; - position: absolute; - width: 66.66666666666666%; -} - -.c1[value]::-moz-progress-bar { - background-color: #004E78; -} - -.c1[value]::-webkit-progress-bar { - background-color: #DBDEE1; -} - -.c1[value]::-webkit-progress-value { - background-color: #004E78; -} - -.c2 { + -webkit-align-items: start; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: start; counter-reset: step; display: grid; grid-auto-columns: unset; @@ -42,7 +33,18 @@ exports[`Progress Component Snapshots with labels 1`] = ` padding: 0; } -.c3 { +.c5 { + font-size: 0.875rem; + font-weight: var(--font-normal); + -webkit-letter-spacing: 0.0125rem; + -moz-letter-spacing: 0.0125rem; + -ms-letter-spacing: 0.0125rem; + letter-spacing: 0.0125rem; + line-height: 1.25rem; + margin-top: var(--spacing-half); +} + +.c2 { color: #004E78; display: -webkit-box; display: -webkit-flex; @@ -51,7 +53,7 @@ exports[`Progress Component Snapshots with labels 1`] = ` -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; - font-weight: var(--font-bold); + font-weight: var(--font-normal); -webkit-box-pack: end; -webkit-justify-content: flex-end; -ms-flex-pack: end; @@ -60,146 +62,175 @@ exports[`Progress Component Snapshots with labels 1`] = ` text-align: center; } -.c3::after { +.c2::before { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; background-color: #FFFFFF; - border: 0.25rem solid; + border: 0.125rem solid; border-radius: 50%; box-sizing: border-box; + color: #1b1c1e; content: counter(step); counter-increment: step; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - height: var(--size-2x); + font-size: 0.75rem; + height: var(--size-1halfx); -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - line-height: 2rem; - margin: 0 auto 0.625rem; + margin: 0 auto 0.25rem; text-align: center; - width: var(--size-2x); + width: var(--size-1halfx); } -.c3 > span { - color: #000000; - font-size: 0.75rem; - font-weight: var(--font-normal); - -webkit-letter-spacing: 0.0125rem; - -moz-letter-spacing: 0.0125rem; - -ms-letter-spacing: 0.0125rem; - letter-spacing: 0.0125rem; - line-height: 1.25rem; - margin-bottom: var(--spacing-1x); +.c2::after { + content: ''; + position: absolute; + width: 100%; + height: 0.25rem; + background-color: #DBDEE1; + top: 0.625rem; + left: calc(-50% - 0.5rem); + z-index: -1; +} + +.c2:first-child::after { + content: none; +} + +.c2 a { + -webkit-text-decoration: none; + text-decoration: none; } -.c4::after { +.c3::before { background-color: #004E78; border-color: #004E78; color: #FFFFFF; + font-weight: var(--font-bold); } -.c4 > span { - color: #60666E; +.c3::after { + background-color: #004E78; } -.c5 { - color: #004E78; +.c3 .c4 { + color: #006296; } -.c5::after { +.c7::before { border-color: #004E78; + border-width: 0.25rem; + font-weight: var(--font-bold); + height: var(--size-2x); + width: var(--size-2x); + margin: -0.25rem auto 0; + color: #003A5A; } -.c5 span { - color: #004E78; +.c7::after { + background-color: #004E78; +} + +.c7 .c4 { + color: #003A5A; font-weight: var(--font-bold); } -.c6::after { - border-color: #DBDEE1; +.c8::before { + border-color: #B7BBC2; + color: #1B1C1E; +} + +.c8 .c4 { color: #60666E; } -
-
  1. - + Step 1 + + completed +
  2. - + Step 2
  3. - + Step 3 + + not completed +
-
+ `; exports[`Progress Component Snapshots without labels 1`] = ` +.c4 { + border: 0; + -webkit-clip: rect(0,0,0,0); + clip: rect(0,0,0,0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + .c0 { position: relative; + padding: var(--spacing-2x) 0; width: 100%; } .c1 { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-color: #DBDEE1; - border: none; - bottom: 1.5rem; - color: #004E78; - height: 4px; - left: 16.666666666666668%; - position: absolute; - width: 66.66666666666666%; -} - -.c1[value]::-moz-progress-bar { - background-color: #004E78; -} - -.c1[value]::-webkit-progress-bar { - background-color: #DBDEE1; -} - -.c1[value]::-webkit-progress-value { - background-color: #004E78; -} - -.c2 { + -webkit-align-items: start; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: start; counter-reset: step; display: grid; grid-auto-columns: unset; @@ -209,7 +240,7 @@ exports[`Progress Component Snapshots without labels 1`] = ` padding: 0; } -.c3 { +.c2 { color: #004E78; display: -webkit-box; display: -webkit-flex; @@ -218,7 +249,7 @@ exports[`Progress Component Snapshots without labels 1`] = ` -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; - font-weight: var(--font-bold); + font-weight: var(--font-normal); -webkit-box-pack: end; -webkit-justify-content: flex-end; -ms-flex-pack: end; @@ -227,103 +258,115 @@ exports[`Progress Component Snapshots without labels 1`] = ` text-align: center; } -.c3::after { +.c2::before { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; background-color: #FFFFFF; - border: 0.25rem solid; + border: 0.125rem solid; border-radius: 50%; box-sizing: border-box; + color: #1b1c1e; content: counter(step); counter-increment: step; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; - height: var(--size-2x); + font-size: 0.75rem; + height: var(--size-1halfx); -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; - line-height: 2rem; - margin: 0 auto 0.625rem; + margin: 0 auto 0.25rem; text-align: center; - width: var(--size-2x); + width: var(--size-1halfx); } -.c3 > span { - color: #000000; - font-size: 0.75rem; - font-weight: var(--font-normal); - -webkit-letter-spacing: 0.0125rem; - -moz-letter-spacing: 0.0125rem; - -ms-letter-spacing: 0.0125rem; - letter-spacing: 0.0125rem; - line-height: 1.25rem; - margin-bottom: var(--spacing-1x); +.c2::after { + content: ''; + position: absolute; + width: 100%; + height: 0.25rem; + background-color: #DBDEE1; + top: 0.625rem; + left: calc(-50% - 0.5rem); + z-index: -1; +} + +.c2:first-child::after { + content: none; } -.c4::after { +.c2 a { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c3::before { background-color: #004E78; border-color: #004E78; color: #FFFFFF; + font-weight: var(--font-bold); } -.c4 > span { - color: #60666E; -} - -.c5 { - color: #004E78; +.c3::after { + background-color: #004E78; } -.c5::after { +.c5::before { border-color: #004E78; + border-width: 0.25rem; + font-weight: var(--font-bold); + height: var(--size-2x); + width: var(--size-2x); + margin: -0.25rem auto 0; + color: #003A5A; } -.c5 span { - color: #004E78; - font-weight: var(--font-bold); +.c5::after { + background-color: #004E78; } -.c6::after { - border-color: #DBDEE1; - color: #60666E; +.c6::before { + border-color: #B7BBC2; + color: #1B1C1E; } -
-
  1. - + + completed +
  2. - -
  3. + class="c2 c5" + data-testid="progress-tracker-step-current" + />
  4. - + + not completed +
-
+ `; diff --git a/packages/react/src/components/progress-tracker/progress-tracker.tsx b/packages/react/src/components/progress-tracker/progress-tracker.tsx index 8bfd651ddb..6b2ac72d86 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.tsx @@ -1,43 +1,17 @@ import { ReactElement, VoidFunctionComponent } from 'react'; import styled from 'styled-components'; -import { clamp, toInt } from '../../utils/math'; +import { Icon } from '../icon/icon'; +import { ScreenReaderOnlyText } from '../screen-reader-only-text/ScreenReaderOnlyText'; +import { clamp } from '../../utils/math'; -const Container = styled.div` +const Container = styled.section` + padding: var(--spacing-2x) 0; position: relative; width: 100%; `; -function getHalfStepLength(props: JSX.IntrinsicElements['progress']): number { - return 50 / (toInt(props.max, 1) + 1); -} - -const StyledProgress = styled.progress` - appearance: none; - background-color: ${(props) => props.theme.greys.grey}; - border: none; - bottom: 1.5rem; - color: ${(props) => props.theme.main['primary-3']}; - height: 4px; - left: ${getHalfStepLength}%; - position: absolute; - width: ${(props) => `${100 - (2 * getHalfStepLength(props))}%`}; - - &[value] { - &::-moz-progress-bar { - background-color: ${(props) => props.theme.main['primary-3']}; - } - - &::-webkit-progress-bar { - background-color: ${(props) => props.theme.greys.grey}; - } - - &::-webkit-progress-value { - background-color: ${(props) => props.theme.main['primary-3']}; - } - } -`; - const Steps = styled.ol` + align-items: start; counter-reset: step; display: grid; grid-auto-columns: unset; @@ -47,115 +21,201 @@ const Steps = styled.ol` padding: 0; `; -const Step = styled.li` - color: ${(props) => props.theme.main['primary-3']}; +const Label = styled.span` + font-size: 0.875rem; + font-weight: var(--font-normal); + letter-spacing: 0.0125rem; + line-height: 1.25rem; + margin-top: var(--spacing-half); +`; + +const Step = styled.li<{ $linear: boolean }>` + color: ${({ theme }) => theme.main['primary-3']}; display: flex; flex-direction: column; - font-weight: var(--font-bold); + font-weight: var(--font-normal); justify-content: flex-end; position: relative; text-align: center; - ::after { + &::before { align-items: center; - background-color: ${(props) => props.theme.greys.white}; - border: 0.25rem solid; + background-color: ${({ theme }) => theme.greys.white}; + border: 0.125rem solid; border-radius: 50%; box-sizing: border-box; + color: #1b1c1e; content: counter(step); counter-increment: step; display: flex; - height: var(--size-2x); + font-size: 0.75rem; + height: var(--size-1halfx); justify-content: center; - line-height: 2rem; - margin: 0 auto 0.625rem; + margin: 0 auto 0.25rem; text-align: center; - width: var(--size-2x); + width: var(--size-1halfx); } - > span { - color: ${(props) => props.theme.greys.black}; - font-size: 0.75rem; - font-weight: var(--font-normal); - letter-spacing: 0.0125rem; - line-height: 1.25rem; - margin-bottom: var(--spacing-1x); + &::after { + background-color: ${({ theme }) => theme.greys.grey}; + content: ''; + height: 0.25rem; + left: calc(-50% - 0.5rem); + position: absolute; + top: 0.625rem; + width: 100%; + z-index: -1; + } + + &:first-child::after { + content: none; + } + + a { + margin-top: calc(var(--size-2x) * -1); + padding-top: var(--size-2x); + text-decoration: none; } `; -const PastStep = styled(Step)` - ::after { - background-color: ${(props) => props.theme.main['primary-3']}; - border-color: ${(props) => props.theme.main['primary-3']}; - color: ${(props) => props.theme.greys.white}; +const CompletedStep = styled(Step)` + &::before { + background-color: ${({ theme }) => theme.main['primary-3']}; + border-color: ${({ theme }) => theme.main['primary-3']}; + color: ${({ theme }) => theme.greys.white}; + font-weight: var(--font-bold); + } + + &::after { + background-color: ${({ $linear, theme }) => $linear && theme.main['primary-3']}; } - > span { - color: ${(props) => props.theme.greys['dark-grey']}; + ${Label} { + color: ${({ theme }) => theme.main['primary-1.1']}; } `; -const CurrentStep = styled(Step).attrs({ 'aria-current': 'step' })` - color: ${(props) => props.theme.main['primary-3']}; +const CurrentStep = styled(Step)` + &::before { + border-color: ${({ theme }) => theme.main['primary-3']}; + border-width: 0.25rem; + color: ${({ theme }) => theme.main['primary-1.3']}; + font-weight: var(--font-bold); + height: var(--size-2x); + margin: -0.25rem auto 0; + width: var(--size-2x); + } - ::after { - border-color: ${(props) => props.theme.main['primary-3']}; + &::after { + background-color: ${({ $linear, theme }) => $linear && theme.main['primary-3']}; } - span { - color: ${(props) => props.theme.main['primary-3']}; + ${Label} { + color: ${({ theme }) => theme.main['primary-1.3']}; font-weight: var(--font-bold); } `; -const FutureStep = styled(Step)` - ::after { - border-color: ${(props) => props.theme.greys.grey}; - color: ${(props) => props.theme.greys['dark-grey']}; +const IncompleteIcon = styled(Icon)` + left: calc(50% + 0.25rem); + position: absolute; + top: -0.5rem; +`; + +const IncompleteStep = styled(Step)` + &::before { + border-color: ${({ theme }) => theme.greys['mid-grey']}; + color: ${({ theme }) => theme.greys['neutral-90']}; + } + + ${Label} { + color: ${({ theme }) => theme.greys['dark-grey']}; } `; -export interface ProgressTracker { +export interface ProgressTrackerStep { + href?: string; label?: string; + nonLinearState?: 'incomplete' | 'completed' | 'default'; + onClick?: (stepNumber: number) => void; } -interface ProgressProps { +interface ProgressTrackerProps { + ariaLabel?: string; className?: string; - steps: ProgressTracker[]; + linear?: boolean; + steps: ProgressTrackerStep[]; value: number; } -function renderStep(step: ProgressTracker, stepIndex: number, value: number): ReactElement { - let StepComponent; - let dataTestId: string; +function renderStep(step: ProgressTrackerStep, stepNumber: number, value: number, linear: boolean): ReactElement { + let StepComponent: typeof Step; + let dataTestId: string | undefined; + let screenReaderText: string | undefined; + const isLink = step.href || step.onClick; + const showIncompleteIcon = !linear && step.nonLinearState === 'incomplete'; - if (stepIndex < value) { - dataTestId = 'progress-step-past'; - StepComponent = PastStep; - } else if (stepIndex === value) { - dataTestId = 'progress-step-current'; + if (stepNumber === value) { + dataTestId = 'progress-tracker-step-current'; StepComponent = CurrentStep; + } else if ((linear && stepNumber < value) || (!linear && step.nonLinearState === 'completed')) { + dataTestId = 'progress-tracker-step-completed'; + screenReaderText = 'completed'; + StepComponent = CompletedStep; } else { - dataTestId = 'progress-step-future'; - StepComponent = FutureStep; + dataTestId = 'progress-tracker-step-incomplete'; + screenReaderText = 'not completed'; + StepComponent = IncompleteStep; } + const content = ( + <> + {showIncompleteIcon && } + {step.label && } + {screenReaderText && } + + ); + + const linkClickHandler = (event: React.MouseEvent): void => { + if (!step.href) { + event.preventDefault(); + } + step.onClick!(stepNumber); + }; + return ( - - {step.label} + + {isLink ? ( + + {content} + + ) : ( + content + )} ); } -export const Progress:VoidFunctionComponent = ({ className, steps, value }) => { +export const ProgressTracker: VoidFunctionComponent = ({ + ariaLabel, + linear = true, + className, + steps, + value, +}) => { const max = steps.length; - const zeroBasedValue = clamp(value, 1, max) - 1; + const clampValue = clamp(value, 1, max); + const hasAnyLink = steps.some((step) => step.href || step.onClick); return ( - - + - {steps.map((step, stepIndex: number) => renderStep(step, stepIndex, zeroBasedValue))} + {steps.map((step, stepNumber) => renderStep(step, stepNumber + 1, clampValue, linear))} ); diff --git a/packages/react/src/icons/alert-filled-round.svg b/packages/react/src/icons/alert-filled-round.svg new file mode 100644 index 0000000000..de78da301a --- /dev/null +++ b/packages/react/src/icons/alert-filled-round.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/react/src/utils/range.ts b/packages/react/src/utils/range.ts index d30553979e..5245b70e9e 100644 --- a/packages/react/src/utils/range.ts +++ b/packages/react/src/utils/range.ts @@ -1,3 +1,3 @@ export function range(start: number, end: number): number[] { - return new Array(end - start + 1).fill(undefined).map((_, i) => i + start); + return [...Array(end - start + 1).keys()].map((x) => x + start); } diff --git a/packages/storybook/stories/icon-library.mdx b/packages/storybook/stories/icon-library.mdx index c6e6625e30..46f334f5dd 100644 --- a/packages/storybook/stories/icon-library.mdx +++ b/packages/storybook/stories/icon-library.mdx @@ -9,6 +9,9 @@ import { ArgTypes, Canvas, IconGallery, IconItem, Meta, Title } from '@storybook + + + diff --git a/packages/storybook/stories/progress-tracker.stories.tsx b/packages/storybook/stories/progress-tracker.stories.tsx index 7fa7ff94c5..3667ea2266 100644 --- a/packages/storybook/stories/progress-tracker.stories.tsx +++ b/packages/storybook/stories/progress-tracker.stories.tsx @@ -1,39 +1,83 @@ -import { Progress, ProgressTracker } from '@equisoft/design-elements-react'; +import { ProgressTracker, ProgressTrackerStep } from '@equisoft/design-elements-react'; import { StoryFn as Story } from '@storybook/react'; +import { useState } from 'react'; +import { rawCodeParameters } from './utils/parameters'; export default { title: 'Components/Data/Progress Tracker', - component: Progress, + component: ProgressTracker, + parameters: rawCodeParameters, + }; -function createEmptySteps(count: number): ProgressTracker[] { - const steps: ProgressTracker[] = []; +function createEmptySteps(count: number): ProgressTrackerStep[] { + const steps: ProgressTrackerStep[] = []; for (let i = 1; i <= count; i++) { steps.push({}); } return steps; } -function createSteps(count: number): ProgressTracker[] { - const steps: ProgressTracker[] = []; +function createSteps(count: number): ProgressTrackerStep[] { + const steps: ProgressTrackerStep[] = []; for (let i = 1; i <= count; i++) { steps.push({ label: `Step ${i}` }); } return steps; } -export const Beginning: Story = () => ( - +export const Normal: Story = () => ( + ); -export const Middle: Story = () => ( - +export const Steps: Story = () => ( + <> + + + + ); -export const End: Story = () => ( - +export const WithLabels: Story = () => ( + ); -export const WithLabels: Story = () => ( - +export const AriaLabel: Story = () => ( + ); + +export const OnclickEvent: Story = () => { + const [currentStep, setCurrentStep] = useState(1); + + const steps: ProgressTrackerStep[] = [ + { label: 'Step 1', onClick: (stepNumber) => setCurrentStep(stepNumber) }, + { label: 'Step 2', onClick: (stepNumber) => setCurrentStep(stepNumber) }, + { label: 'Step 3', onClick: (stepNumber) => setCurrentStep(stepNumber) }, + ]; + return ; +}; + +export const HrefLinks: Story = () => { + const steps: ProgressTrackerStep[] = [ + { label: 'Step 1', href: 'https://equisoft.com' }, + { label: 'Step 2', href: 'https://equisoft.com' }, + { label: 'Step 3', href: 'https://equisoft.com' }, + ]; + return ; +}; + +export const NonLinear: Story = () => { + const [currentStep, setCurrentStep] = useState(3); + + const steps: ProgressTrackerStep[] = [ + { label: 'Step 1', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'completed' }, + { label: 'Step 2', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'incomplete' }, + { label: 'Step 3', onClick: (stepNumber) => setCurrentStep(stepNumber) }, + { label: 'Step 4', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'default' }, + ]; + return ; +}; From 09fe0c10015a30f10b08ea460517867f50556f6c Mon Sep 17 00:00:00 2001 From: Savut Sang Date: Fri, 9 Feb 2024 14:49:01 -0500 Subject: [PATCH 2/9] fix: snapshots --- .../progress-tracker.test.tsx.snap | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap index 864a23c888..522b2662d7 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap @@ -14,8 +14,8 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c0 { - position: relative; padding: var(--spacing-2x) 0; + position: relative; width: 100%; } @@ -90,13 +90,13 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c2::after { + background-color: #DBDEE1; content: ''; - position: absolute; - width: 100%; height: 0.25rem; - background-color: #DBDEE1; - top: 0.625rem; left: calc(-50% - 0.5rem); + position: absolute; + top: 0.625rem; + width: 100%; z-index: -1; } @@ -105,6 +105,8 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c2 a { + margin-top: calc(var(--size-2x) * -1); + padding-top: var(--size-2x); -webkit-text-decoration: none; text-decoration: none; } @@ -127,11 +129,11 @@ exports[`Progress Component Snapshots with labels 1`] = ` .c7::before { border-color: #004E78; border-width: 0.25rem; + color: #003A5A; font-weight: var(--font-bold); height: var(--size-2x); - width: var(--size-2x); margin: -0.25rem auto 0; - color: #003A5A; + width: var(--size-2x); } .c7::after { @@ -221,8 +223,8 @@ exports[`Progress Component Snapshots without labels 1`] = ` } .c0 { - position: relative; padding: var(--spacing-2x) 0; + position: relative; width: 100%; } @@ -286,13 +288,13 @@ exports[`Progress Component Snapshots without labels 1`] = ` } .c2::after { + background-color: #DBDEE1; content: ''; - position: absolute; - width: 100%; height: 0.25rem; - background-color: #DBDEE1; - top: 0.625rem; left: calc(-50% - 0.5rem); + position: absolute; + top: 0.625rem; + width: 100%; z-index: -1; } @@ -301,6 +303,8 @@ exports[`Progress Component Snapshots without labels 1`] = ` } .c2 a { + margin-top: calc(var(--size-2x) * -1); + padding-top: var(--size-2x); -webkit-text-decoration: none; text-decoration: none; } @@ -319,11 +323,11 @@ exports[`Progress Component Snapshots without labels 1`] = ` .c5::before { border-color: #004E78; border-width: 0.25rem; + color: #003A5A; font-weight: var(--font-bold); height: var(--size-2x); - width: var(--size-2x); margin: -0.25rem auto 0; - color: #003A5A; + width: var(--size-2x); } .c5::after { From 7a447e7b7a2b2e96baeea178198b5c6fadfbc07e Mon Sep 17 00:00:00 2001 From: Savut Sang Date: Thu, 15 Feb 2024 09:53:51 -0500 Subject: [PATCH 3/9] fix: various pr comments --- packages/react/src/components/icon/icon.tsx | 2 - .../progress-tracker.test.tsx | 6 +- .../progress-tracker.test.tsx.snap | 18 +--- .../progress-tracker/progress-tracker.tsx | 88 ++++++++++++------- packages/react/src/i18n/translations.ts | 8 ++ .../react/src/icons/alert-filled-round.svg | 6 -- packages/storybook/stories/icon-library.mdx | 3 - .../stories/progress-tracker.stories.tsx | 6 +- 8 files changed, 73 insertions(+), 64 deletions(-) delete mode 100644 packages/react/src/icons/alert-filled-round.svg diff --git a/packages/react/src/components/icon/icon.tsx b/packages/react/src/components/icon/icon.tsx index b61cf7884c..37642ec4c9 100644 --- a/packages/react/src/components/icon/icon.tsx +++ b/packages/react/src/components/icon/icon.tsx @@ -55,12 +55,10 @@ import WarningFilled from '../../icons/warning-filled.svg'; import Equisoft from '../../logos/logo-equisoft-ico.svg'; import CaretDown from '../../icons/caret-down.svg'; import CaretRight from '../../icons/caret-right.svg'; -import AlertFilledRound from '../../icons/alert-filled-round.svg'; const iconMapping = { alertCircle: AlertCircle, alertFilled: AlertFilled, - alertFilledRound: AlertFilledRound, alertTriangle: AlertTriangle, alertOctagon: AlertOctagon, arrowDown: ArrowDown, diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx index 00b122f59f..581462add2 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx @@ -74,15 +74,15 @@ describe('Progress Component', () => { expect(currentStep).toEqual(expect.arrayContaining(['Step 3'])); }); - it('should have incomplete steps', () => { + it('should have uncompleted steps', () => { const steps = generateSteps(3); const wrapper = shallow(); const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - const incompleteStep = findByTestId(stepsWrapper, 'progress-tracker-step-incomplete') + const uncompletedStep = findByTestId(stepsWrapper, 'progress-tracker-step-uncompleted') .map((w) => findByTestId(w, 'progress-tracker-label').text()); - expect(incompleteStep).toEqual(expect.arrayContaining(['Step 2', 'Step 3'])); + expect(uncompletedStep).toEqual(expect.arrayContaining(['Step 2', 'Step 3'])); }); describe('Snapshots', () => { diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap index 522b2662d7..7be0b225b3 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap @@ -104,13 +104,6 @@ exports[`Progress Component Snapshots with labels 1`] = ` content: none; } -.c2 a { - margin-top: calc(var(--size-2x) * -1); - padding-top: var(--size-2x); - -webkit-text-decoration: none; - text-decoration: none; -} - .c3::before { background-color: #004E78; border-color: #004E78; @@ -191,7 +184,7 @@ exports[`Progress Component Snapshots with labels 1`] = `
  • ` +const StepLink = styled.a` + display: inline-block; + margin-top: calc(var(--size-2x) * -1); + padding-top: var(--size-2x); + text-decoration: none; +`; + +const StyledStep = styled.li<{ $linear: boolean }>` + align-items: center; color: ${({ theme }) => theme.main['primary-3']}; display: flex; flex-direction: column; @@ -70,15 +79,9 @@ const Step = styled.li<{ $linear: boolean }>` &:first-child::after { content: none; } - - a { - margin-top: calc(var(--size-2x) * -1); - padding-top: var(--size-2x); - text-decoration: none; - } `; -const CompletedStep = styled(Step)` +const CompletedStep = styled(StyledStep)` &::before { background-color: ${({ theme }) => theme.main['primary-3']}; border-color: ${({ theme }) => theme.main['primary-3']}; @@ -95,7 +98,7 @@ const CompletedStep = styled(Step)` } `; -const CurrentStep = styled(Step)` +const CurrentStep = styled(StyledStep)` &::before { border-color: ${({ theme }) => theme.main['primary-3']}; border-width: 0.25rem; @@ -116,13 +119,7 @@ const CurrentStep = styled(Step)` } `; -const IncompleteIcon = styled(Icon)` - left: calc(50% + 0.25rem); - position: absolute; - top: -0.5rem; -`; - -const IncompleteStep = styled(Step)` +const UncompletedStep = styled(StyledStep)` &::before { border-color: ${({ theme }) => theme.greys['mid-grey']}; color: ${({ theme }) => theme.greys['neutral-90']}; @@ -133,10 +130,19 @@ const IncompleteStep = styled(Step)` } `; +const UncompletedIcon = styled(Icon)` + left: calc(50% + 0.25rem); + position: absolute; + top: -0.5rem; + + fill: ${({ theme }) => theme.notifications['alert-2.1']}; + color: ${({ theme }) => theme.greys.white}; +`; + export interface ProgressTrackerStep { href?: string; label?: string; - nonLinearState?: 'incomplete' | 'completed' | 'default'; + completion?: 'uncompleted' | 'completed'; onClick?: (stepNumber: number) => void; } @@ -148,29 +154,40 @@ interface ProgressTrackerProps { value: number; } -function renderStep(step: ProgressTrackerStep, stepNumber: number, value: number, linear: boolean): ReactElement { - let StepComponent: typeof Step; +interface StepProps { + step: ProgressTrackerStep, + stepNumber: number, + value: number, + linear: boolean +} + +const Step: VoidFunctionComponent = ({ + step, stepNumber, value, linear, +}): ReactElement => { + const { t } = useTranslation('progress-tracker'); + + let StepComponent: typeof StyledStep; let dataTestId: string | undefined; let screenReaderText: string | undefined; const isLink = step.href || step.onClick; - const showIncompleteIcon = !linear && step.nonLinearState === 'incomplete'; + const showUncompletedIcon = !linear && step.completion === 'uncompleted'; if (stepNumber === value) { dataTestId = 'progress-tracker-step-current'; StepComponent = CurrentStep; - } else if ((linear && stepNumber < value) || (!linear && step.nonLinearState === 'completed')) { + } else if ((linear && stepNumber < value) || (!linear && step.completion === 'completed')) { dataTestId = 'progress-tracker-step-completed'; - screenReaderText = 'completed'; + screenReaderText = t('completedAriaLabel'); StepComponent = CompletedStep; } else { - dataTestId = 'progress-tracker-step-incomplete'; - screenReaderText = 'not completed'; - StepComponent = IncompleteStep; + dataTestId = 'progress-tracker-step-uncompleted'; + screenReaderText = t('uncompletedAriaLabel'); + StepComponent = UncompletedStep; } const content = ( <> - {showIncompleteIcon && } + {showUncompletedIcon && } {step.label && } {screenReaderText && } @@ -180,7 +197,7 @@ function renderStep(step: ProgressTrackerStep, stepNumber: number, value: number if (!step.href) { event.preventDefault(); } - step.onClick!(stepNumber); + step.onClick?.(stepNumber); }; return ( @@ -191,15 +208,15 @@ function renderStep(step: ProgressTrackerStep, stepNumber: number, value: number $linear={linear} > {isLink ? ( - + {content} - + ) : ( content )} ); -} +}; export const ProgressTracker: VoidFunctionComponent = ({ ariaLabel, @@ -215,7 +232,16 @@ export const ProgressTracker: VoidFunctionComponent = ({ return ( - {steps.map((step, stepNumber) => renderStep(step, stepNumber + 1, clampValue, linear))} + {steps.map((step, index) => ( + + ))} ); diff --git a/packages/react/src/i18n/translations.ts b/packages/react/src/i18n/translations.ts index f57994402d..cb5315be32 100644 --- a/packages/react/src/i18n/translations.ts +++ b/packages/react/src/i18n/translations.ts @@ -80,6 +80,10 @@ export const Translations = { 'show-password': 'Show password in plain text.', 'hide-password': 'Hide password.', }, + 'progress-tracker': { + completedAriaLabel: 'completed', + uncompletedAriaLabel: 'not completed', + }, 'search-input': { label: 'Search', }, @@ -204,6 +208,10 @@ export const Translations = { 'show-password': 'Montrer le mot de passe.', 'hide-password': 'Cacher le mot de passe.', }, + 'progress-tracker': { + completedAriaLabel: 'complété', + uncompletedAriaLabel: 'non complété', + }, 'search-input': { label: 'Rechercher', }, diff --git a/packages/react/src/icons/alert-filled-round.svg b/packages/react/src/icons/alert-filled-round.svg deleted file mode 100644 index de78da301a..0000000000 --- a/packages/react/src/icons/alert-filled-round.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/storybook/stories/icon-library.mdx b/packages/storybook/stories/icon-library.mdx index 46f334f5dd..c6e6625e30 100644 --- a/packages/storybook/stories/icon-library.mdx +++ b/packages/storybook/stories/icon-library.mdx @@ -9,9 +9,6 @@ import { ArgTypes, Canvas, IconGallery, IconItem, Meta, Title } from '@storybook - - - diff --git a/packages/storybook/stories/progress-tracker.stories.tsx b/packages/storybook/stories/progress-tracker.stories.tsx index 3667ea2266..bc14aab949 100644 --- a/packages/storybook/stories/progress-tracker.stories.tsx +++ b/packages/storybook/stories/progress-tracker.stories.tsx @@ -74,10 +74,10 @@ export const NonLinear: Story = () => { const [currentStep, setCurrentStep] = useState(3); const steps: ProgressTrackerStep[] = [ - { label: 'Step 1', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'completed' }, - { label: 'Step 2', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'incomplete' }, + { label: 'Step 1', onClick: (stepNumber) => setCurrentStep(stepNumber), completion: 'completed' }, + { label: 'Step 2', onClick: (stepNumber) => setCurrentStep(stepNumber), completion: 'uncompleted' }, { label: 'Step 3', onClick: (stepNumber) => setCurrentStep(stepNumber) }, - { label: 'Step 4', onClick: (stepNumber) => setCurrentStep(stepNumber), nonLinearState: 'default' }, + { label: 'Step 4', onClick: (stepNumber) => setCurrentStep(stepNumber) }, ]; return ; }; From f2c808d8c390a89e32143b51cbb2cc9c76bb75be Mon Sep 17 00:00:00 2001 From: Savut Sang Date: Thu, 15 Feb 2024 13:20:32 -0500 Subject: [PATCH 4/9] fix: linting and tests --- .../progress-tracker.test.tsx | 57 +++++++------------ .../progress-tracker.test.tsx.snap | 8 +++ .../progress-tracker/progress-tracker.tsx | 5 +- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx index 581462add2..da312735a8 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx @@ -1,6 +1,5 @@ -import { shallow } from 'enzyme'; import { findByTestId, getByTestId } from '../../test-utils/enzyme-selectors'; -import { renderWithProviders } from '../../test-utils/renderer'; +import { mountWithTheme, renderWithProviders } from '../../test-utils/renderer'; import { range } from '../../utils/range'; import { ProgressTracker, ProgressTrackerStep } from './progress-tracker'; @@ -12,76 +11,62 @@ describe('Progress Component', () => { it('should render all steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const allSteps = findByTestId(stepsWrapper, 'progress-tracker-step-', '^'); + const wrapper = mountWithTheme(); + const allSteps = wrapper.find('li[data-testid^="progress-tracker-step-"]'); expect(allSteps.length).toBe(3); }); it('should render all steps labels', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const allStepsLabels = findByTestId(stepsWrapper, 'progress-tracker-step-', '^') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const allStepsLabels = findByTestId(wrapper, 'progress-tracker-step-', '^') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(allStepsLabels).toEqual(expect.arrayContaining(['Step 1', 'Step 2', 'Step 3'])); }); it('should have completed steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const completedSteps = findByTestId(stepsWrapper, 'progress-tracker-step-completed') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const completedSteps = findByTestId(wrapper, 'progress-tracker-step-completed') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(completedSteps).toEqual(expect.arrayContaining(['Step 1', 'Step 2'])); }); it('should have current step', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const currentStep = findByTestId(wrapper, 'progress-tracker-step-current') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 2'])); }); it('should fallback to first step if value is less than 1', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const currentStep = findByTestId(wrapper, 'progress-tracker-step-current') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 1'])); }); it('should fallback to last step if value is higher than number of steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const currentStep = findByTestId(stepsWrapper, 'progress-tracker-step-current') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const currentStep = findByTestId(wrapper, 'progress-tracker-step-current') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(currentStep).toEqual(expect.arrayContaining(['Step 3'])); }); it('should have uncompleted steps', () => { const steps = generateSteps(3); - const wrapper = shallow(); - const stepsWrapper = getByTestId(wrapper, 'progress-tracker'); - - const uncompletedStep = findByTestId(stepsWrapper, 'progress-tracker-step-uncompleted') - .map((w) => findByTestId(w, 'progress-tracker-label').text()); + const wrapper = mountWithTheme(); + const uncompletedStep = findByTestId(wrapper, 'progress-tracker-step-uncompleted') + .map((w) => getByTestId(w, 'progress-tracker-label').text()); expect(uncompletedStep).toEqual(expect.arrayContaining(['Step 2', 'Step 3'])); }); diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap index 7be0b225b3..4ebbbe8d59 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap @@ -45,6 +45,10 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c2 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; color: #004E78; display: -webkit-box; display: -webkit-flex; @@ -236,6 +240,10 @@ exports[`Progress Component Snapshots without labels 1`] = ` } .c2 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; color: #004E78; display: -webkit-box; display: -webkit-flex; diff --git a/packages/react/src/components/progress-tracker/progress-tracker.tsx b/packages/react/src/components/progress-tracker/progress-tracker.tsx index c50fa8d5d2..79ca217b2c 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.tsx @@ -131,12 +131,11 @@ const UncompletedStep = styled(StyledStep)` `; const UncompletedIcon = styled(Icon)` + color: ${({ theme }) => theme.greys.white}; + fill: ${({ theme }) => theme.notifications['alert-2.1']}; left: calc(50% + 0.25rem); position: absolute; top: -0.5rem; - - fill: ${({ theme }) => theme.notifications['alert-2.1']}; - color: ${({ theme }) => theme.greys.white}; `; export interface ProgressTrackerStep { From 7a42ab90f8290203f2a828d39d125be33de4f5f0 Mon Sep 17 00:00:00 2001 From: Savut Sang Date: Fri, 16 Feb 2024 12:32:39 -0500 Subject: [PATCH 5/9] fix: console.warn, colors, label required --- .../progress-tracker.test.tsx | 21 ++-- .../progress-tracker.test.tsx.snap | 105 ++++++++++++++---- .../progress-tracker/progress-tracker.tsx | 22 ++-- .../stories/progress-tracker.stories.tsx | 26 ++--- 4 files changed, 115 insertions(+), 59 deletions(-) diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx index da312735a8..b855186d73 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx @@ -8,12 +8,8 @@ function generateSteps(count: number): ProgressTrackerStep[] { } describe('Progress Component', () => { - it('should render all steps', () => { - const steps = generateSteps(3); - - const wrapper = mountWithTheme(); - const allSteps = wrapper.find('li[data-testid^="progress-tracker-step-"]'); - expect(allSteps.length).toBe(3); + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => { }); }); it('should render all steps labels', () => { @@ -71,7 +67,7 @@ describe('Progress Component', () => { }); describe('Snapshots', () => { - it('with labels', () => { + it('linear', () => { const steps = generateSteps(3); const wrapper = renderWithProviders(); @@ -79,10 +75,15 @@ describe('Progress Component', () => { expect(wrapper).toMatchSnapshot(); }); - it('without labels', () => { - const steps: ProgressTrackerStep[] = [{}, {}, {}]; + it('non linear', () => { + const steps: ProgressTrackerStep[] = [ + { label: 'Step 1', completion: 'completed' }, + { label: 'Step 2', completion: 'uncompleted' }, + { label: 'Step 3' }, + { label: 'Step 4' }, + ]; - const wrapper = renderWithProviders(); + const wrapper = renderWithProviders(); expect(wrapper).toMatchSnapshot(); }); diff --git a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap index 4ebbbe8d59..9d295e6544 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap +++ b/packages/react/src/components/progress-tracker/progress-tracker.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Progress Component Snapshots with labels 1`] = ` +exports[`Progress Component Snapshots linear 1`] = ` .c6 { border: 0; -webkit-clip: rect(0,0,0,0); @@ -109,14 +109,14 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c3::before { - background-color: #004E78; - border-color: #004E78; + background-color: #006296; + border-color: #006296; color: #FFFFFF; - font-weight: var(--font-bold); + font-weight: var(--font-semi-bold); } .c3::after { - background-color: #004E78; + background-color: #006296; } .c3 .c4 { @@ -124,7 +124,7 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c7::before { - border-color: #004E78; + border-color: #006296; border-width: 0.25rem; color: #003A5A; font-weight: var(--font-bold); @@ -134,7 +134,7 @@ exports[`Progress Component Snapshots with labels 1`] = ` } .c7::after { - background-color: #004E78; + background-color: #006296; } .c7 .c4 { @@ -206,8 +206,8 @@ exports[`Progress Component Snapshots with labels 1`] = ` `; -exports[`Progress Component Snapshots without labels 1`] = ` -.c4 { +exports[`Progress Component Snapshots non linear 1`] = ` +.c6 { border: 0; -webkit-clip: rect(0,0,0,0); clip: rect(0,0,0,0); @@ -239,6 +239,17 @@ exports[`Progress Component Snapshots without labels 1`] = ` padding: 0; } +.c5 { + font-size: 0.875rem; + font-weight: var(--font-normal); + -webkit-letter-spacing: 0.0125rem; + -moz-letter-spacing: 0.0125rem; + -ms-letter-spacing: 0.0125rem; + letter-spacing: 0.0125rem; + line-height: 1.25rem; + margin-top: var(--spacing-half); +} + .c2 { -webkit-align-items: center; -webkit-box-align: center; @@ -304,18 +315,22 @@ exports[`Progress Component Snapshots without labels 1`] = ` } .c3::before { - background-color: #004E78; - border-color: #004E78; + background-color: #006296; + border-color: #006296; color: #FFFFFF; - font-weight: var(--font-bold); + font-weight: var(--font-semi-bold); } .c3::after { - background-color: #004E78; + background-color: #006296; +} + +.c3 .c4 { + color: #006296; } -.c5::before { - border-color: #004E78; +.c7::before { + border-color: #006296; border-width: 0.25rem; color: #003A5A; font-weight: var(--font-bold); @@ -324,15 +339,24 @@ exports[`Progress Component Snapshots without labels 1`] = ` width: var(--size-2x); } -.c5::after { - background-color: #004E78; +.c7::after { + background-color: #006296; } -.c6::before { +.c7 .c4 { + color: #003A5A; + font-weight: var(--font-bold); +} + +.c8::before { border-color: #B7BBC2; color: #1B1C1E; } +.c8 .c4 { + color: #60666E; +} +
    @@ -345,22 +369,57 @@ exports[`Progress Component Snapshots without labels 1`] = ` data-testid="progress-tracker-step-completed" > + Step 1 + + + completed + +
  • +
  • + + Step 2 + + completed
  • + > + + Step 3 + +
  • + Step 4 + + not completed diff --git a/packages/react/src/components/progress-tracker/progress-tracker.tsx b/packages/react/src/components/progress-tracker/progress-tracker.tsx index 79ca217b2c..bea670e9b6 100644 --- a/packages/react/src/components/progress-tracker/progress-tracker.tsx +++ b/packages/react/src/components/progress-tracker/progress-tracker.tsx @@ -83,14 +83,14 @@ const StyledStep = styled.li<{ $linear: boolean }>` const CompletedStep = styled(StyledStep)` &::before { - background-color: ${({ theme }) => theme.main['primary-3']}; - border-color: ${({ theme }) => theme.main['primary-3']}; + background-color: ${({ theme }) => theme.main['primary-1.1']}; + border-color: ${({ theme }) => theme.main['primary-1.1']}; color: ${({ theme }) => theme.greys.white}; - font-weight: var(--font-bold); + font-weight: var(--font-semi-bold); } &::after { - background-color: ${({ $linear, theme }) => $linear && theme.main['primary-3']}; + background-color: ${({ $linear, theme }) => $linear && theme.main['primary-1.1']}; } ${Label} { @@ -100,7 +100,7 @@ const CompletedStep = styled(StyledStep)` const CurrentStep = styled(StyledStep)` &::before { - border-color: ${({ theme }) => theme.main['primary-3']}; + border-color: ${({ theme }) => theme.main['primary-1.1']}; border-width: 0.25rem; color: ${({ theme }) => theme.main['primary-1.3']}; font-weight: var(--font-bold); @@ -110,7 +110,7 @@ const CurrentStep = styled(StyledStep)` } &::after { - background-color: ${({ $linear, theme }) => $linear && theme.main['primary-3']}; + background-color: ${({ $linear, theme }) => $linear && theme.main['primary-1.1']}; } ${Label} { @@ -140,8 +140,8 @@ const UncompletedIcon = styled(Icon)` export interface ProgressTrackerStep { href?: string; - label?: string; - completion?: 'uncompleted' | 'completed'; + label: string; + completion?: 'completed' | 'uncompleted'; onClick?: (stepNumber: number) => void; } @@ -186,7 +186,7 @@ const Step: VoidFunctionComponent = ({ const content = ( <> - {showUncompletedIcon && } + {showUncompletedIcon &&
  • + - completed + not completed