feat: Améliore a11y de Progress et Questions

ajout-redux-focus
Benjamin Arias 2022-09-12 15:07:24 +02:00
parent 68045d2e02
commit ead7930261
7 changed files with 45 additions and 17 deletions

View File

@ -27,14 +27,14 @@ export function Questions({
}: {
customEndMessages?: ConversationProps['customEndMessages']
}) {
const progress = useSimulationProgress()
const { numberCurrentStep, numberSteps } = useSimulationProgress()
return (
<>
<Progress progress={progress} />
<Progress progress={numberCurrentStep} maxValue={numberSteps} />
<QuestionsContainer>
<div className="print-hidden">
{progress < 1 && (
{numberCurrentStep < numberSteps && (
<Notice>
<Trans i18nKey="simulateurs.précision.défaut">
Améliorez votre simulation en répondant aux questions :

View File

@ -40,6 +40,7 @@ export function SimulationGoals({
publique={publique}
role="group"
aria-labelledby="simulator-legend"
aria-live="polite"
>
<ThemeProvider theme={(theme) => ({ ...theme, darkMode: true })}>
<div className="sr-only" id="simulator-legend">

View File

@ -10,6 +10,7 @@ export default function TextInput({
description,
title,
missing,
autoFocus,
}: InputProps & { value: Evaluation<string> }) {
const debouncedOnChange = useCallback(debounce(1000, onChange), [])
@ -17,6 +18,8 @@ export default function TextInput({
<TextField
type="text"
label={title}
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={autoFocus}
onChange={(value) => {
debouncedOnChange(`'${value}'`)
}}

View File

@ -3,28 +3,40 @@ import styled from 'styled-components'
type ProgressProps = {
progress: number
minValue?: number
maxValue?: number
step?: number
}
export default function Progress({ progress }: ProgressProps) {
export default function Progress({
progress,
minValue = 0,
maxValue = 1,
step = 1,
}: ProgressProps) {
const propsBar = {
showValueLabel: false,
label: 'Précision de votre simulation',
minValue: 0,
maxValue: 1,
label: 'Précisions concernant votre simulation',
minValue,
maxValue,
value: progress,
}
const a11yPrefixLabel = `Étape ${progress + step} sur ${String(maxValue)}, `
const { progressBarProps, labelProps } = useProgressBar(propsBar)
return (
<>
<span {...labelProps} className="sr-only">
{propsBar.label}
<div aria-live="polite">
<span {...labelProps} className="sr-only" aria-hidden>
{`${a11yPrefixLabel} ${propsBar.label}`}
</span>
<ProgressContainer {...progressBarProps}>
<ProgressBar style={{ width: `${progress * 100}%` }} />
<ProgressBar
style={{ width: `${(progress * 100) / (maxValue || 1)}%` }}
/>
</ProgressContainer>
</>
</div>
)
}

View File

@ -173,9 +173,18 @@ export const useNextQuestions = function (): Array<DottedName> {
return nextQuestions
}
export function useSimulationProgress(): number {
export function useSimulationProgress(): {
progressRatio: number
numberCurrentStep: number
numberSteps: number
} {
const numberQuestionAnswered = useSelector(answeredQuestionsSelector).length
const numberQuestionLeft = useNextQuestions().length
return numberQuestionAnswered / (numberQuestionAnswered + numberQuestionLeft)
return {
progressRatio:
numberQuestionAnswered / (numberQuestionAnswered + numberQuestionLeft),
numberCurrentStep: numberQuestionAnswered,
numberSteps: numberQuestionAnswered + numberQuestionLeft,
}
}

View File

@ -16,7 +16,7 @@ import { SimpleField } from '../_components/Fields'
import { DéclarationRevenu } from './_components/DéclarationRevenu'
export default function Cotisations() {
const progress = useSimulationProgress()
const { numberCurrentStep, numberSteps } = useSimulationProgress()
const engine = useEngine()
return (
@ -100,7 +100,10 @@ export default function Cotisations() {
margin: 0 -1.5rem;
`}
>
<Progress progress={progress} />
<Progress
progress={numberCurrentStep}
maxValue={numberSteps}
/>
</div>
</div>
</Message>

View File

@ -88,7 +88,7 @@ function useSteps() {
const step1Progress = useProgress(Step1Objectifs)
const step2Progress = useProgress(Step2Objectifs)
const step3Progress = useProgress(useStep3Objectifs())
const step4Progress = useSimulationProgress()
const { progressRatio: step4Progress } = useSimulationProgress()
const casExcluStep1 = useEngine().evaluate('DRI . cas exclus ')
.nodeValue as boolean
const casExcluStep2 = useEngine().evaluate('DRI . imposition cas exclus')