Skip to content

Commit

Permalink
fix: add a statusText prop to StepIndicator to allow for i18n for the…
Browse files Browse the repository at this point in the history
… sr-only element Closes #2857 (#2888)
  • Loading branch information
kimallen authored Apr 17, 2024
1 parent d8eb80a commit 855205e
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { StepIndicatorStep } from '../StepIndicatorStep/StepIndicatorStep'
import { StepIndicator } from '../StepIndicator/StepIndicator'
import { StepIndicator, StepStatusText } from '../StepIndicator/StepIndicator'

export default {
title: 'Components/Step Indicator',
Expand Down Expand Up @@ -35,6 +35,7 @@ Updates users on their progress through a multi-step process.
type StorybookArguments = {
stepText: string
ofText: string
statusText: StepStatusText
}

export const DefaultStepIndicator = (
Expand All @@ -43,7 +44,8 @@ export const DefaultStepIndicator = (
<StepIndicator
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -57,7 +59,8 @@ export const NoLabels = (args: StorybookArguments): React.ReactElement => (
showLabels={false}
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -71,7 +74,8 @@ export const Centered = (args: StorybookArguments): React.ReactElement => (
centered
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -85,7 +89,8 @@ export const Counters = (args: StorybookArguments): React.ReactElement => (
counters="default"
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -99,7 +104,8 @@ export const SmallCounters = (args: StorybookArguments): React.ReactElement => (
counters="small"
headingLevel="h4"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand All @@ -114,7 +120,8 @@ export const DifferentHeadingLevel = (
<StepIndicator
headingLevel="h2"
ofText={args.ofText}
stepText={args.stepText}>
stepText={args.stepText}
statusText={args.statusText}>
<StepIndicatorStep label="Personal information" status="complete" />
<StepIndicatorStep label="Household status" status="complete" />
<StepIndicatorStep label="Supporting documents" status="current" />
Expand Down
22 changes: 22 additions & 0 deletions src/components/stepindicator/StepIndicator/StepIndicator.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,26 @@ describe('StepIndicator component', () => {
const stepSrOnly = within(stepIndicator).queryByText(stepText)
expect(stepSrOnly).toHaveClass('usa-sr-only')
})
it('renders properly with translated statusText for screen reader', () => {
const statusText = { complete: 'completado', incomplete: 'no completado' }

const { getByTestId } = render(
<StepIndicator headingLevel="h4" statusText={statusText}>
<StepIndicatorStep label={step1} status="complete" />
<StepIndicatorStep label={step2} status="current" />
<StepIndicatorStep label={step3} status="incomplete" />
</StepIndicator>
)
const stepIndicator = getByTestId('step-indicator')

const completedStatusSrOnly = within(stepIndicator).queryByText(
statusText.complete
)
expect(completedStatusSrOnly).toHaveClass('usa-sr-only')

const incompleteStatusSrOnly = within(stepIndicator).queryByText(
statusText.incomplete
)
expect(incompleteStatusSrOnly).toHaveClass('usa-sr-only')
})
})
13 changes: 12 additions & 1 deletion src/components/stepindicator/StepIndicator/StepIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import classnames from 'classnames'
import { StepIndicatorStepProps } from '../StepIndicatorStep/StepIndicatorStep'
import { HeadingLevel } from '../../../types/headingLevel'

export type StepStatusText = {
complete: string
incomplete: string
}

type StepIndicatorProps = {
showLabels?: boolean
counters?: 'none' | 'default' | 'small'
Expand All @@ -18,6 +23,7 @@ type StepIndicatorProps = {
headingLevel: HeadingLevel
stepText?: string
ofText?: string
statusText?: StepStatusText
}
export const StepIndicator = (
props: StepIndicatorProps
Expand All @@ -34,6 +40,7 @@ export const StepIndicator = (
headingLevel,
stepText = 'Step',
ofText = 'of',
statusText = { complete: 'completed', incomplete: 'not completed' },
} = props

const Heading = headingLevel
Expand Down Expand Up @@ -76,14 +83,18 @@ export const StepIndicator = (
const currentStepLabel = children[parseInt(`${currentStepIndex}`)].props.label
const totalNumberOfSteps = children.length

const stepChildren = React.Children.map(children, (child) =>
React.cloneElement(child, { statusText: statusText })
)

return (
<div
className={divClasses}
data-testid="step-indicator"
aria-label="progress"
{...remainingDivProps}>
<ol className={listClasses} {...remainingListProps}>
{children}
{stepChildren}
</ol>
<div className="usa-step-indicator__header">
<Heading className={headingClasses} {...remainingHeadingProps}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,26 @@ describe('Step component', () => {
})

it('renders with incomplete status', () => {
const { getByRole, queryByText } = render(
const { getByRole, queryByText, queryByTestId } = render(
<StepIndicatorStep label="Test Step" status="incomplete" />
)
expect(queryByText('Test Step')).toBeInTheDocument()
expect(queryByText('not completed')).toHaveClass('usa-sr-only')
expect(queryByTestId('srStatusText')).toHaveClass('usa-sr-only')
expect(queryByTestId('srStatusText')).toHaveTextContent('not completed')
expect(getByRole('listitem')).toHaveClass('usa-step-indicator__segment')
})

it('renders incomplete status with alternative language in screen reader element', () => {
const { queryByTestId } = render(
<StepIndicatorStep
label="Test Step"
status="incomplete"
statusText={{ complete: 'completado', incomplete: 'no completado' }}
/>
)
expect(queryByTestId('srStatusText')).toHaveTextContent('no completado')
})

it('renders with current status', () => {
const { getByRole, queryByText } = render(
<StepIndicatorStep label="Test Step" status="current" />
Expand All @@ -31,13 +43,25 @@ describe('Step component', () => {
})

it('renders with complete status', () => {
const { getByRole, queryByText } = render(
const { getByRole, queryByText, queryByTestId } = render(
<StepIndicatorStep label="Test Step" status="complete" />
)
expect(queryByText('Test Step')).toBeInTheDocument()
expect(queryByText('completed')).toHaveClass('usa-sr-only')
expect(queryByTestId('srStatusText')).toHaveClass('usa-sr-only')
expect(queryByTestId('srStatusText')).toHaveTextContent('completed')
expect(getByRole('listitem')).toHaveClass(
'usa-step-indicator__segment usa-step-indicator__segment--complete'
)
})

it('renders complete status with alternative language in screen reader element', () => {
const { queryByTestId } = render(
<StepIndicatorStep
label="Test Step"
status="complete"
statusText={{ complete: 'completado', incomplete: 'no completado' }}
/>
)
expect(queryByTestId('srStatusText')).toHaveTextContent('completado')
})
})
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import classnames from 'classnames'
import React from 'react'

import { StepStatusText } from '../StepIndicator/StepIndicator'

export interface StepIndicatorStepProps {
label: string
status?: 'complete' | 'current' | 'incomplete'
statusText?: StepStatusText
className?: string
}

export const StepIndicatorStep = (
props: StepIndicatorStepProps & JSX.IntrinsicElements['li']
): React.ReactElement => {
const { label, status = 'incomplete', className, ...liProps } = props
const {
label,
status = 'incomplete',
statusText = { complete: 'completed', incomplete: 'not completed' },
className,
...liProps
} = props

const classes = classnames(
'usa-step-indicator__segment',
Expand All @@ -30,8 +39,10 @@ export const StepIndicatorStep = (
{label}
&nbsp;
{status !== 'current' && (
<span className="usa-sr-only">
{status === 'complete' ? 'completed' : 'not completed'}
<span data-testid="srStatusText" className="usa-sr-only">
{status === 'complete'
? statusText.complete
: statusText.incomplete}
</span>
)}
</span>
Expand Down

0 comments on commit 855205e

Please sign in to comment.