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: Add aria attributes to RangeInput #1560

Merged
merged 10 commits into from
Sep 20, 2021
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ lib/

# editor config
.vscode
.idea

# happo output directory
.out
19 changes: 14 additions & 5 deletions src/components/forms/RangeInput/RangeInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ describe('RangeInput component', () => {
expect(rangeElement).toBeInTheDocument()
expect(rangeElement).toHaveAttribute('id', 'range-slider-id')
expect(rangeElement).toHaveAttribute('name', 'rangeName')
expect(rangeElement).toHaveAttribute('aria-valuemin', '0')
expect(rangeElement).toHaveAttribute('aria-valuemax', '100')
expect(rangeElement).toHaveAttribute('aria-valuenow', '50')
expect(rangeElement).toHaveClass('usa-range')
expect(rangeElement).toHaveClass('additional-class')
})
Expand All @@ -26,16 +29,22 @@ describe('RangeInput component', () => {
<RangeInput
id="range-slider-id"
name="rangeName"
min={0}
min={-15}
max={60}
step={15}
defaultValue={45}
/>
)
expect(queryByTestId('range')).toHaveAttribute('min', '0')
expect(queryByTestId('range')).toHaveAttribute('max', '60')
expect(queryByTestId('range')).toHaveAttribute('step', '15')
expect(queryByTestId('range')).toHaveAttribute('value', '45')

const rangeElement = queryByTestId('range')

expect(rangeElement).toHaveAttribute('min', '-15')
expect(rangeElement).toHaveAttribute('max', '60')
expect(rangeElement).toHaveAttribute('aria-valuemin', '-15')
expect(rangeElement).toHaveAttribute('aria-valuemax', '60')
expect(rangeElement).toHaveAttribute('aria-valuenow', '45')
expect(rangeElement).toHaveAttribute('step', '15')
expect(rangeElement).toHaveAttribute('value', '45')
})

it('renders with step attribute set to value any', () => {
Expand Down
31 changes: 29 additions & 2 deletions src/components/forms/RangeInput/RangeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import classnames from 'classnames'
interface RangeInputProps {
id: string
name: string
min?: number
max?: number
inputRef?:
| string
| ((instance: HTMLInputElement | null) => void)
Expand All @@ -17,9 +19,30 @@ export const RangeInput = ({
inputRef,
...inputProps
}: RangeInputProps & JSX.IntrinsicElements['input']): React.ReactElement => {
// Range defaults to min = 0, max = 100, step = 1, and value = (max/2) if not specified.

const classes = classnames('usa-range', className)
// input range defaults to min = 0, max = 100, step = 1, and value = (max/2) if not specified.
const defaultMin = 0
const defaultMax = 100
const { min, max, defaultValue } = inputProps
const ariaMin = min || defaultMin
haworku marked this conversation as resolved.
Show resolved Hide resolved
const ariaMax = max || defaultMax
const calculatedDefaultValue =
defaultValue ||
(ariaMax < ariaMin ? ariaMin : ariaMin + ariaMax - ariaMax / 2)
const convertValueType = (
value: string | number | readonly string[]
): number | undefined => {
if (typeof value === 'number' || typeof value === 'string') {
return Number(value)
}
return undefined
}
const [ariaValue, setAriaValue] = React.useState<number | undefined>(
convertValueType(calculatedDefaultValue)
)
const onValueChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
setAriaValue(e.target.valueAsNumber)
haworku marked this conversation as resolved.
Show resolved Hide resolved
}

return (
<input
Expand All @@ -28,6 +51,10 @@ export const RangeInput = ({
ref={inputRef}
type="range"
{...inputProps}
aria-valuemin={ariaMin}
aria-valuemax={ariaMax}
aria-valuenow={ariaValue}
onChange={(e) => onValueChange(e)}
/>
)
}
Expand Down