Skip to content

Commit

Permalink
Merge 6bb59e3 into fff7f65
Browse files Browse the repository at this point in the history
  • Loading branch information
TylerJDev authored Aug 29, 2024
2 parents fff7f65 + 6bb59e3 commit dc2a901
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 26 deletions.
76 changes: 56 additions & 20 deletions packages/react/src/ProgressBar/ProgressBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const shimmer = keyframes`
to { mask-position: 0%; }
`

export const Item = styled.span<ProgressProp & SxProp>`
const ProgressItem = styled.span<ProgressProp & SxProp>`
width: ${props => (props.progress ? `${props.progress}%` : 0)};
background-color: ${get('colors.success.emphasis')};
Expand All @@ -31,8 +31,6 @@ export const Item = styled.span<ProgressProp & SxProp>`
${sx};
`

Item.displayName = 'ProgressBar.Item'

const sizeMap = {
small: '5px',
large: '10px',
Expand All @@ -57,36 +55,74 @@ const ProgressContainer = styled.span<StyledProgressContainerProps>`
${sx};
`

export type ProgressBarProps = React.HTMLAttributes<HTMLSpanElement> & {bg?: string} & StyledProgressContainerProps &
ProgressProp
export type ProgressBarItems = React.HTMLAttributes<HTMLSpanElement> & {'aria-label'?: string} & ProgressProp & SxProp

export const ProgressBar = forwardRef<HTMLSpanElement, ProgressBarProps>(
(
{animated, progress, bg = 'success.emphasis', barSize = 'default', children, ...rest}: ProgressBarProps,
forwardRef,
) => {
if (children && progress) {
throw new Error('You should pass `progress` or children, not both.')
export const Item = forwardRef<HTMLSpanElement, ProgressBarItems>(
({progress, 'aria-label': ariaLabel, ...rest}, forwardRef) => {
const progressAsNumber = typeof progress === 'string' ? parseInt(progress, 10) : progress

const ariaAttributes = {
'aria-valuenow': progressAsNumber && progressAsNumber >= 0 ? Math.round(progressAsNumber) : undefined,
'aria-valuemin': 0,
'aria-valuemax': 100,
}

warning(
children &&
ariaAttributes['aria-valuenow'] === undefined &&
typeof (rest as React.AriaAttributes)['aria-valuenow'] === 'undefined' &&
typeof (rest as React.AriaAttributes)['aria-valuetext'] === 'undefined',
'Expected `aria-valuenow` or `aria-valuetext` to be provided to <ProgressBar>. Provide one of these values so screen reader users can determine the current progress. This warning will become an error in the next major release.',
)

const progressAsNumber = typeof progress === 'string' ? parseInt(progress, 10) : progress
return (
<ProgressItem
role="progressbar"
aria-label={ariaLabel}
ref={forwardRef}
progress={progress}
{...ariaAttributes}
{...rest}
/>
)
},
)

const ariaAttributes = {
'aria-valuenow': progressAsNumber ? Math.round(progressAsNumber) : undefined,
'aria-valuemin': 0,
'aria-valuemax': 100,
Item.displayName = 'ProgressBar.Item'

export type ProgressBarProps = React.HTMLAttributes<HTMLSpanElement> & {bg?: string} & StyledProgressContainerProps &
ProgressProp

export const ProgressBar = forwardRef<HTMLSpanElement, ProgressBarProps>(
(
{
animated,
progress,
bg = 'success.emphasis',
barSize = 'default',
children,
'aria-label': ariaLabel,
'aria-valuenow': ariaValueNow,
'aria-valuetext': ariaValueText,
...rest
}: ProgressBarProps,
forwardRef,
) => {
if (children && progress) {
throw new Error('You should pass `progress` or children, not both.')
}

return (
<ProgressContainer ref={forwardRef} role="progressbar" barSize={barSize} {...ariaAttributes} {...rest}>
{children ?? <Item data-animated={animated} progress={progress} sx={{backgroundColor: bg}} />}
<ProgressContainer ref={forwardRef} barSize={barSize} {...rest}>
{children ?? (
<Item
data-animated={animated}
progress={progress}
aria-label={ariaLabel}
aria-valuenow={ariaValueNow}
aria-valuetext={ariaValueText}
sx={{backgroundColor: bg}}
/>
)}
</ProgressContainer>
)
},
Expand Down
37 changes: 36 additions & 1 deletion packages/react/src/__tests__/ProgressBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {render as HTMLRender} from '@testing-library/react'
import axe from 'axe-core'

describe('ProgressBar', () => {
behavesAsComponent({Component: ProgressBar})
behavesAsComponent({Component: ProgressBar, toRender: () => <ProgressBar aria-valuenow={10} progress={0} />})

checkExports('ProgressBar', {
default: undefined,
Expand Down Expand Up @@ -50,4 +50,39 @@ describe('ProgressBar', () => {
it('respects the "progress" prop', () => {
expect(render(<ProgressBar progress={80} aria-label="Upload test.png" />)).toMatchSnapshot()
})

it('passed the `aria-label` down to the progress bar', () => {
const {getByRole, getByLabelText} = HTMLRender(<ProgressBar progress={80} aria-label="Upload test.png" />)
expect(getByRole('progressbar')).toHaveAttribute('aria-label', 'Upload test.png')
expect(getByLabelText('Upload test.png')).toBeInTheDocument()
})

it('passed the `aria-valuenow` down to the progress bar', () => {
const {getByRole} = HTMLRender(<ProgressBar progress={80} aria-valuenow={80} />)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '80')
})

it('passed the `aria-valuetext` down to the progress bar', () => {
const {getByRole} = HTMLRender(<ProgressBar aria-valuetext="80 percent" />)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuetext', '80 percent')
})

it('does not pass the `aria-label` down to the progress bar if there are multiple items', () => {
const {getByRole} = HTMLRender(
<ProgressBar aria-label="Upload test.png">
<ProgressBar.Item progress={80} />
</ProgressBar>,
)
expect(getByRole('progressbar')).not.toHaveAttribute('aria-label')
})

it('passes aria attributes to the progress bar item', () => {
const {getByRole} = HTMLRender(
<ProgressBar>
<ProgressBar.Item progress={50} aria-label="Progress" ria-valuenow="50"></ProgressBar.Item>
</ProgressBar>,
)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '50')
expect(getByRole('progressbar')).toHaveAttribute('aria-label', 'Progress')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,14 @@ exports[`ProgressBar respects the "progress" prop 1`] = `
}
<span
aria-label="Upload test.png"
aria-valuemax={100}
aria-valuemin={0}
aria-valuenow={80}
className="c0"
role="progressbar"
>
<span
aria-label="Upload test.png"
aria-valuemax={100}
aria-valuemin={0}
className="c1"
role="progressbar"
/>
</span>
`;

0 comments on commit dc2a901

Please sign in to comment.