Skip to content

Commit 6527c94

Browse files
OlgaLarinaOlgaLarina
and
OlgaLarina
authored
resolve #9849 A11Y: Paneldynamic progressbar (#9857)
Co-authored-by: OlgaLarina <[email protected]>
1 parent d04a521 commit 6527c94

22 files changed

+100
-16
lines changed

accessibilityTests/navigation.spec.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { frameworks, initSurvey, url } from "./helper";
1+
import { checkA11y, injectAxe } from "axe-playwright";
2+
import { axeOptions, frameworks, initSurvey, url } from "./helper";
23
import { test, expect } from "@playwright/test";
34
const title = "navigation";
45

@@ -70,12 +71,14 @@ frameworks.forEach((framework) => {
7071
test.describe(`${framework} a11y:${title}`, () => {
7172
test.beforeEach(async ({ page }) => {
7273
await page.goto(`${url}${framework}`);
73-
await initSurvey(page, framework, json);
74+
await injectAxe(page);
7475
});
7576
test("progress bar", async ({ page }) => {
77+
await initSurvey(page, framework, json);
7678
await expect(page.locator("[role='progressbar']")).toHaveAttribute(
7779
"aria-label"
7880
);
81+
await checkA11y(page, ".sd-progress-buttons", { axeOptions });
7982
});
8083
});
8184
});
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Page, test } from "@playwright/test";
2+
import { frameworks, url, initSurvey, axeOptions } from "./helper";
3+
import { injectAxe, checkA11y } from "axe-playwright";
4+
5+
const title = "Paneldynamic";
6+
7+
frameworks.forEach((framework) => {
8+
test.describe(`${framework} a11y:${title}`, () => {
9+
test.beforeEach(async ({ page }) => {
10+
await page.goto(`${url}${framework}`);
11+
await injectAxe(page);
12+
});
13+
test("axe check paneldynamic", async ({ page }) => {
14+
await initSurvey(page, framework, {
15+
"pages": [
16+
{
17+
"name": "page1",
18+
"elements": [
19+
{
20+
"type": "paneldynamic",
21+
"name": "relatives26",
22+
"title": "Panel Dynamic",
23+
"templateElements": [
24+
{
25+
"type": "dropdown",
26+
"name": "relativeType27",
27+
"title": "Relative",
28+
"choices": ["father", "mother", "brother", "sister", "son", "daughter"]
29+
},
30+
{
31+
"type": "radiogroup",
32+
"name": "isalive28",
33+
"startWithNewLine": false,
34+
"title": "Alive?",
35+
"choices": ["Yes", "No"],
36+
"colCount": 0
37+
}
38+
],
39+
"templateTitle": "Information about: {panel.relativeType}",
40+
"panelCount": 2,
41+
"addPanelText": "Add a blood relative",
42+
"removePanelText": "Remove the relative",
43+
"renderMode": "progressTop",
44+
"displayMode": "carousel"
45+
},
46+
]
47+
}
48+
],
49+
"questionErrorLocation": "bottom"
50+
});
51+
await checkA11y(page, ".sd-question", { axeOptions });
52+
});
53+
});
54+
});

packages/survey-angular-ui/src/components/progress/buttons/progress.component.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
<div [class]="model.getRootCss(container)" [style.maxWidth]="model.progressWidth" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
1+
<div [class]="model.getRootCss(container)" [style.maxWidth]="model.progressWidth"
2+
role="progressbar" aria-valuemin="0" aria-valuemax="100" [attr.aria-label]="model.progressBarAriaLabel"
3+
>
24
<div *ngIf="canShowHeader" [class]="survey.css.progressButtonsHeader">
35
<div [class]="survey.css.progressButtonsPageTitle" [title]="model.headerText">{{ model.headerText }}</div>
46
</div>

packages/survey-angular-ui/src/components/progress/default/progress.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<ng-template #template>
22
<div [class]="model.getProgressCssClasses(container)">
33
<div [class]="model.css.progressBar" [style.width]="model.progressValue + '%'"
4-
role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
4+
role="progressbar" aria-valuemin="0" aria-valuemax="100" [attr.aria-label]="model.progressBarAriaLabel">
55
<span [class]="getProgressTextInBarCss(model.css)">
66
{{ model.progressText }}
77
</span>

packages/survey-angular-ui/src/questions/paneldynamic.component.html

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
</div>
55
<sv-ng-placeholder-paneldynamic [question]="model"></sv-ng-placeholder-paneldynamic>
66
<div [class]="model.cssClasses.progress" *ngIf="model.isProgressTopShowing && model.isRangeShowing">
7-
<div [class]="model.cssClasses.progressBar" [style]="{ width: model.progress }" role="progressbar"></div>
7+
<div [class]="model.cssClasses.progressBar" [style]="{ width: model.progress }"
8+
role="progressbar" [attr.aria-label]="model.progressBarAriaLabel"
9+
></div>
810
</div>
911
<div [class]="model.cssClasses.panelsContainer">
1012
<ng-container *ngFor="let panel of model.renderedPanels; index as index; trackBy: trackPanelBy">
@@ -27,7 +29,9 @@
2729
<div [class]="model.cssClasses.footer" *ngIf="!!model.cssClasses.footer">
2830
<hr [class]="model.cssClasses.separator" />
2931
<div [class]="model.cssClasses.progress" *ngIf="model.isRangeShowing && model.isProgressBottomShowing">
30-
<div [class]="model.cssClasses.progressBar" [style]="{ width: model.progress }" role="progressbar"></div>
32+
<div [class]="model.cssClasses.progressBar" [style]="{ width: model.progress }"
33+
role="progressbar" [attr.aria-label]="model.progressBarAriaLabel"
34+
></div>
3135
</div>
3236
<div *ngIf="model.footerToolbar.visibleActions.length" [class]="model.cssClasses.footerButtonsContainer">
3337
<sv-ng-action-bar [model]="model.footerToolbar"></sv-ng-action-bar>

packages/survey-core/src/localization/english.ts

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export var englishStrings = {
118118
cancel: "Cancel",
119119
createCustomItem: "Create \"{0}\" item...",
120120
toc: "Table of contents",
121+
progressbar: "Progress bar",
121122
};
122123

123124
// Uncomment the lines below if you create a custom dictionary.

packages/survey-core/src/progress-buttons.ts

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Base, EventBase } from "./base";
22
import { surveyCss } from "./defaultCss/defaultCss";
33
import { PageModel } from "./page";
44
import { SurveyModel } from "./survey";
5+
import { getLocaleString } from "./surveyStrings";
56
import { CssClassBuilder } from "./utils/cssClassBuilder";
67

78
export class ProgressButtons extends Base {
@@ -130,6 +131,9 @@ export class ProgressButtons extends Base {
130131
public get progressText(): string {
131132
return this.getPropertyValue("progressText", undefined, () => this.survey.getProgressText());
132133
}
134+
public get progressBarAriaLabel(): string {
135+
return getLocaleString("progressbar", this.survey.getLocale());
136+
}
133137
public resetProgressText(): void {
134138
this.resetPropertyValue("progressText");
135139
}

packages/survey-core/src/question_paneldynamic.ts

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { AdaptiveActionContainer } from "./actions/adaptive-container";
3333
import { ITheme } from "./themes";
3434
import { AnimationGroup, AnimationProperty, AnimationTab, IAnimationConsumer, IAnimationGroupConsumer } from "./utils/animation";
3535
import { QuestionSingleInputSummary, QuestionSingleInputSummaryItem } from "./questionSingleInputSummary";
36+
import { getLocaleString } from "./surveyStrings";
3637

3738
export interface IQuestionPanelDynamicData {
3839
getItemIndex(item: ISurveyData): number;
@@ -2570,6 +2571,9 @@ export class QuestionPanelDynamicModel extends Question
25702571
public get progress(): string {
25712572
return ((this.currentIndex + 1) / this.visiblePanelCount) * 100 + "%";
25722573
}
2574+
public get progressBarAriaLabel(): string {
2575+
return getLocaleString("progressbar", this.getLocale());
2576+
}
25732577
public getRootCss(): string {
25742578
return new CssClassBuilder().append(super.getRootCss()).append(this.cssClasses.empty, this.getShowNoEntriesPlaceholder()).toString();
25752579
}

packages/survey-core/src/survey.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { CalculatedValue } from "./calculatedValue";
3030
import { PageModel } from "./page";
3131
import { TextPreProcessor, TextPreProcessorValue } from "./textPreProcessor";
3232
import { ProcessValue } from "./conditionProcessValue";
33-
import { surveyLocalization } from "./surveyStrings";
33+
import { getLocaleString, surveyLocalization } from "./surveyStrings";
3434
import { CustomError } from "./error";
3535
import { LocalizableString } from "./localizablestring";
3636
// import { StylesManager } from "./stylesmanager";
@@ -5296,6 +5296,9 @@ export class SurveyModel extends SurveyElementCore
52965296
var pages = this.isDesignMode ? this.pages : this.visiblePages;
52975297
return SurveyElement.getProgressInfoByElements(pages, false);
52985298
}
5299+
public get progressBarAriaLabel(): string {
5300+
return getLocaleString("progressbar", this.getLocale());
5301+
}
52995302
/**
53005303
* Returns text displayed by the progress bar (for instance, "Page 2 of 3" or "Answered 3/8 questions"). Handle the [`onGetProgressText`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onGetProgressText) event to change this text.
53015304
* @see progressValue

packages/survey-react-ui/src/progress.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export class SurveyProgress extends SurveyNavigationBase {
1616
protected get progressText(): string {
1717
return this.survey.progressText;
1818
}
19+
protected get progressBarAriaLabel(): string {
20+
return this.survey.progressBarAriaLabel;
21+
}
1922
render(): React.JSX.Element {
2023
var progressStyle = {
2124
width: this.progress + "%",
@@ -28,7 +31,7 @@ export class SurveyProgress extends SurveyNavigationBase {
2831
role="progressbar"
2932
aria-valuemin={0}
3033
aria-valuemax={100}
31-
aria-label="progress"
34+
aria-label={this.progressBarAriaLabel}
3235
>
3336
<span
3437
className={SurveyProgressModel.getProgressTextInBarCss(this.css)}

packages/survey-react-ui/src/progressButtons.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export class SurveyProgressButtons extends SurveyNavigationBase implements IProg
3030
}
3131
render(): React.JSX.Element {
3232
return (
33-
<div className={this.model.getRootCss(this.props.container)} style={{ "maxWidth": this.model.progressWidth }} role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-label="progress">
33+
<div className={this.model.getRootCss(this.props.container)} style={{ "maxWidth": this.model.progressWidth }}
34+
role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-label={this.model.progressBarAriaLabel}
35+
>
3436
{this.state.canShowHeader ? <div className={this.css.progressButtonsHeader}>
3537
<div className={this.css.progressButtonsPageTitle} title={this.model.headerText}>{this.model.headerText}</div>
3638
</div> : null}

packages/survey-react-ui/src/reactquestion_paneldynamic.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class SurveyQuestionPanelDynamic extends SurveyQuestionElementBase {
7878
className={this.question.cssClasses.progressBar}
7979
style={{ width: this.question.progress }}
8080
role="progressbar"
81+
aria-label={this.question.progressBarAriaLabel}
8182
/>
8283
</div>
8384
);

packages/survey-vue3-ui/src/PanelDynamic.vue

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
:class="question.cssClasses.progressBar"
2121
:style="{ width: question.progress }"
2222
role="progressbar"
23+
:aria-label="question.progressBarAriaLabel"
2324
></div>
2425
</div>
2526
<div :class="question.cssClasses.panelsContainer">

packages/survey-vue3-ui/src/PanelDynamicProgress.vue

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
:class="question.cssClasses.progressBar"
1515
:style="{ width: question.progress }"
1616
role="progressbar"
17+
:aria-label="question.progressBarAriaLabel"
1718
></div>
1819
</div>
1920
<SvComponent

packages/survey-vue3-ui/src/PanelDynamicProgressV2.vue

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
:class="question.cssClasses.progressBar"
1010
:style="{ width: question.progress }"
1111
role="progressbar"
12+
:aria-label="question.progressBarAriaLabel"
1213
></div>
1314
</div>
1415
<div

packages/survey-vue3-ui/src/components/progress/Progress.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
role="progressbar"
77
aria-valuemin="0"
88
aria-valuemax="100"
9-
aria-label="progress"
9+
:aria-label="survey.progressBarAriaLabel"
1010
>
1111
<span :class="getProgressTextInBarCss(survey.css)">{{
1212
survey.progressText

packages/survey-vue3-ui/src/components/progress/ProgressButtons.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
role="progressbar"
66
aria-valuemin="0"
77
aria-valuemax="100"
8-
aria-label="progress"
8+
:aria-label="model.progressBarAriaLabel"
99
>
1010
<div v-if="canShowHeader" :class="survey.css.progressButtonsHeader">
1111
<div

tests/markup/snapshots/paneldynamic-progress-bottom-legacy-navigation.snap.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<div class="sd-paneldynamic__footer">
77
<hr class="sd-paneldynamic__separator">
88
<div class="sd-progress">
9-
<div class="sd-progress__bar" role="progressbar" style="width:50%;">
9+
<div aria-label="Progress bar" class="sd-progress__bar" role="progressbar" style="width:50%;">
1010
</div>
1111
</div>
1212
<div class="sd-paneldynamic__buttons-container">

tests/markup/snapshots/paneldynamic-progress-bottom.snap.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<div class="sd-paneldynamic__footer">
77
<hr class="sd-paneldynamic__separator">
88
<div class="sd-progress">
9-
<div class="sd-progress__bar" role="progressbar" style="width:50%;">
9+
<div aria-label="Progress bar" class="sd-progress__bar" role="progressbar" style="width:50%;">
1010
</div>
1111
</div>
1212
<div class="sd-paneldynamic__buttons-container">

tests/markup/snapshots/paneldynamic-progress-top-legacy-navigation.snap.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="sd-paneldynamic">
22
<div class="sd-progress">
3-
<div class="sd-progress__bar" role="progressbar" style="width:50%;">
3+
<div aria-label="Progress bar" class="sd-progress__bar" role="progressbar" style="width:50%;">
44
</div>
55
</div>
66
<div class="sd-paneldynamic__panels-container">

tests/markup/snapshots/paneldynamic-progress-top.snap.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="sd-paneldynamic">
22
<div class="sd-progress">
3-
<div class="sd-progress__bar" role="progressbar" style="width:50%;">
3+
<div aria-label="Progress bar" class="sd-progress__bar" role="progressbar" style="width:50%;">
44
</div>
55
</div>
66
<div class="sd-paneldynamic__panels-container">

visualRegressionTests/tests/defaultV2/responsiveness.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ frameworks.forEach(framework => {
5353
"description": "Enter 8 characters minimum.",
5454
"inputType": "password",
5555
"isRequired": true,
56-
"autocomplete": "password",
56+
"autocomplete": "current-password",
5757
"validators": [{
5858
"type": "text",
5959
"minLength": 8,

0 commit comments

Comments
 (0)