Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: parametrized StepIndicator strings #2707

Merged
merged 5 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,32 @@ Updates users on their progress through a multi-step process.
},
},
},
argTypes: {
stepText: {
control: 'text',
},
ofText: {
control: 'text',
},
},
args: {
stepText: 'Step',
ofText: 'of',
},
}

type StorybookArguments = {
stepText: string
ofText: string
}

export const defaultStepIndicator = (): React.ReactElement => (
<StepIndicator headingLevel="h4">
export const defaultStepIndicator = (
args: StorybookArguments
): React.ReactElement => (
<StepIndicator
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -30,8 +52,12 @@ export const defaultStepIndicator = (): React.ReactElement => (
</StepIndicator>
)

export const noLabels = (): React.ReactElement => (
<StepIndicator showLabels={false} headingLevel="h4">
export const noLabels = (args: StorybookArguments): React.ReactElement => (
<StepIndicator
showLabels={false}
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -40,8 +66,12 @@ export const noLabels = (): React.ReactElement => (
</StepIndicator>
)

export const centered = (): React.ReactElement => (
<StepIndicator centered headingLevel="h4">
export const centered = (args: StorybookArguments): React.ReactElement => (
<StepIndicator
centered
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -50,8 +80,12 @@ export const centered = (): React.ReactElement => (
</StepIndicator>
)

export const counters = (): React.ReactElement => (
<StepIndicator counters="default" headingLevel="h4">
export const counters = (args: StorybookArguments): React.ReactElement => (
<StepIndicator
counters="default"
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -60,8 +94,12 @@ export const counters = (): React.ReactElement => (
</StepIndicator>
)

export const smallCounters = (): React.ReactElement => (
<StepIndicator counters="small" headingLevel="h4">
export const smallCounters = (args: StorybookArguments): React.ReactElement => (
<StepIndicator
counters="small"
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -70,8 +108,13 @@ export const smallCounters = (): React.ReactElement => (
</StepIndicator>
)

export const differentHeadingLevel = (): React.ReactElement => (
<StepIndicator headingLevel="h2">
export const differentHeadingLevel = (
args: StorybookArguments
): React.ReactElement => (
<StepIndicator
headingLevel="h2"
ofText={args.ofText}
stepText={args.stepText}>
<StepIndicatorStep label="Personal information" status="complete" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend removing the passed in text in one of the tests so that we can ensure the fallback to english works correctly.

Copy link
Contributor Author

@werdnanoslen werdnanoslen Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { render } from '@testing-library/react'
import { render, within } from '@testing-library/react'
import { StepIndicatorStep } from '../StepIndicatorStep/StepIndicatorStep'
import { StepIndicator } from '../StepIndicator/StepIndicator'
import { HeadingLevel } from '../../../types/headingLevel'
Expand All @@ -14,22 +14,27 @@ describe('StepIndicator component', () => {
})

it('renders without errors', () => {
const { getByRole, queryByText, queryAllByText, queryByTestId } = render(
const { getByRole, queryByText, queryAllByText, getByTestId } = render(
<StepIndicator headingLevel="h4">
<StepIndicatorStep label={step1} status="complete" />
<StepIndicatorStep label={step2} status="current" />
<StepIndicatorStep label={step3} status="incomplete" />
</StepIndicator>
)

const stepIndicator = queryByTestId('step-indicator')
const stepIndicator = getByTestId('step-indicator')

expect(stepIndicator).toBeInTheDocument()
expect(stepIndicator).toHaveClass('usa-step-indicator')
expect(queryByText(step1)).toBeInTheDocument()
expect(queryAllByText(step2)).toHaveLength(2)
expect(queryByText(step3)).toBeInTheDocument()
expect(getByRole('list')).toHaveClass('usa-step-indicator__segments')
const stepSrOnly = within(stepIndicator).queryByText('Step')
expect(stepSrOnly).toHaveClass('usa-sr-only')
const totalSteps = queryByText(`of 3`)
expect(totalSteps).toBeInTheDocument()
expect(totalSteps).toHaveClass('usa-step-indicator__total-steps')
})

it('renders properly with no labels', () => {
Expand Down Expand Up @@ -163,4 +168,32 @@ describe('StepIndicator component', () => {
'usa-step-indicator__heading my-custom-className'
)
})

it("renders properly with translatable 'of' string", () => {
const ofText = 'de'
const { queryByText } = render(
<StepIndicator headingLevel="h4" ofText={ofText}>
<StepIndicatorStep label={step1} status="complete" />
<StepIndicatorStep label={step2} status="current" />
<StepIndicatorStep label={step3} status="incomplete" />
</StepIndicator>
)
const totalSteps = queryByText(`${ofText} 3`)
expect(totalSteps).toBeInTheDocument()
expect(totalSteps).toHaveClass('usa-step-indicator__total-steps')
})

it("renders properly with translatable 'step' string", () => {
const stepText = 'Paso'
const { getByTestId } = render(
<StepIndicator headingLevel="h4" stepText={stepText}>
<StepIndicatorStep label={step1} status="complete" />
<StepIndicatorStep label={step2} status="current" />
<StepIndicatorStep label={step3} status="incomplete" />
</StepIndicator>
)
const stepIndicator = getByTestId('step-indicator')
const stepSrOnly = within(stepIndicator).queryByText(stepText)
expect(stepSrOnly).toHaveClass('usa-sr-only')
})
})
10 changes: 8 additions & 2 deletions src/components/stepindicator/StepIndicator/StepIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type StepIndicatorProps = {
HTMLHeadingElement
>
headingLevel: HeadingLevel
stepText?: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are more of these, would it be better to do an object with multiple entries?

text: { step?: string, of?: string }

That way we can extend without adding loads more props?

Copy link
Contributor Author

@werdnanoslen werdnanoslen Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the only two strings on the top-level component, so would it still be beneficial to put it in such an object?

The other strings are on the StepIndicatorStep sub-component, which could use such a treatment, but I don't think we have that pattern on other components (yet) and wanted to keep this PR tight enough that we can unblock the project requirement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay no worries, that works. Lemme test.

ofText?: string
}
export const StepIndicator = (
props: StepIndicatorProps
Expand All @@ -30,6 +32,8 @@ export const StepIndicator = (
listProps,
headingProps,
headingLevel,
stepText = 'Step',
ofText = 'of',
} = props

const Heading = headingLevel
Expand Down Expand Up @@ -84,12 +88,14 @@ export const StepIndicator = (
<div className="usa-step-indicator__header">
<Heading className={headingClasses} {...remainingHeadingProps}>
<span className="usa-step-indicator__heading-counter">
<span className="usa-sr-only">Step</span>
<span className="usa-sr-only" data-testid="step-text">
{stepText}
</span>
<span className="usa-step-indicator__current-step">
{currentStepNumber}
</span>
&nbsp;
<span className="usa-step-indicator__total-steps">{`of ${totalNumberOfSteps}`}</span>
<span className="usa-step-indicator__total-steps">{`${ofText} ${totalNumberOfSteps}`}</span>
&nbsp;
</span>
<span className="usa-step-indicator__heading-text">
Expand Down
Loading