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

Resolved #7810 - Progress Bar Issues #7909

Merged
merged 9 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
"editor.tabSize": 2,
"editor.formatOnSave": true,
"eslint.format.enable": true,
"jest.outputConfig": {
"revealOn": "run",
"revealWithFocus": "test-results",
"clearOnRun": "none"
},
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"test:vue:single": "karma start ./build-scripts/survey-vue/karma.conf.vue.js --single-run",
"test:markup": "npm run test:knockout:single && npm run test:react:single && npm run test:vue:single",
"visual-regression-tests": "testcafe chrome ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --reporter minimal --selector-timeout 1500",
"vrt:ko": "testcafe chrome ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --reporter minimal --env=knockout --selector-timeout 1500",
"visual-regression-tests:ci": "testcafe chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal",
"visual-regression-tests:ci:knockout": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=knockout",
"visual-regression-tests:ci:angular": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server ./packages/survey-angular-ui/example/dist --proxy http://localhost:8080? -p 8080\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=angular",
Expand Down Expand Up @@ -213,4 +214,4 @@
"signature_pad": "^4.1.5",
"vite": "^3.1.8"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div [class]="model.getRootCss(container)" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div [class]="model.getRootCss(container)" [style.maxWidth]="model.progressWidth" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div *ngIf="canShowHeader" [class]="survey.css.progressButtonsHeader">
<div [class]="survey.css.progressButtonsPageTitle" [title]="model.headerText">{{ model.headerText }}</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="model.getRootCss(container)" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div :class="model.getRootCss(container)" :style="{'maxWidth': model.progressWidth}" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div v-if="canShowHeader" :class="survey.css.progressButtonsHeader">
<div :class="survey.css.progressButtonsPageTitle" :title="model.headerText">{{ model.headerText }}</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/defaultCss/defaultV2Css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export var defaultV2Css = {
progressText: "sd-progress__text",
progressButtonsRoot: "sd-progress-buttons",
progressButtonsNumbered: "sd-progress-buttons--numbered",
progressButtonsFitSurveyWidth: "sd-progress-buttons--fit-survey-width",
progressButtonsContainerCenter: "sd-progress-buttons__container-center",
progressButtonsContainer: "sd-progress-buttons__container",
progressButtonsConnector: "sd-progress-buttons__connector",
Expand Down
47 changes: 36 additions & 11 deletions src/defaultV2-theme/blocks/sd-progress-buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,32 @@
flex-wrap: nowrap;
text-align: center;
flex-direction: column;
cursor: pointer;

&:not(:first-child)>.sd-progress-buttons__connector {
display: block;
content: "";
width: 100%;
height: calcSize(0.25);
background-color: $navigation;
// opacity: 0.5;
position: absolute;
bottom: calcSize(0.875);
right: 50%;
bottom: calcSize(1.125);
// right: 50%;
right: calc(50% + 4px);
width: calc(100% - 4px);
pointer-events: none;
}

&:after {
display: flex;
content: attr(data-page-number);
width: calcSize(0);
height: calcSize(0);
margin: calcSize(0.5);
margin: calcSize(0.75);
border: calcSize(0.5) solid transparent;
background-color: $navigation;
// opacity: 0.5;
border-radius: 50%;
cursor: pointer;
align-self: center;
z-index: 1;
font-size: calcFontSize(0.75);
Expand All @@ -77,6 +81,14 @@
}
}

li:hover:after {
color: $primary;
padding: calcSize(0.25);
margin: calcSize(0.25);
border: calcSize(0.75) solid $primary;
background-color: $primary-foreground;
}

.sd-progress-buttons__list-element--passed {
&:not(:first-child)>.sd-progress-buttons__connector {
background-color: $primary;
Expand All @@ -93,11 +105,11 @@
}

&:after {
border-color: $primary;
border: calcSize(0.5) solid $primary;
background-color: $primary-foreground;
color: $primary;
padding: calcSize(0.5);
margin: 0;
padding: calcSize(0.25);
margin: calcSize(0.5);
}
}
}
Expand Down Expand Up @@ -140,7 +152,7 @@
flex-direction: column-reverse;

&:not(:first-child)>.sd-progress-buttons__connector {
top: calcSize(0.875);
top: calcSize(1.125);
}
}
}
Expand Down Expand Up @@ -169,13 +181,19 @@
.sd-progress-buttons__list {
li {
&:not(:first-child)>.sd-progress-buttons__connector {
bottom: calcSize(1.875);
bottom: calcSize(2.175);
right: calc(50% + 8px);
width: calc(100% - 8px);
}

&:after {
width: calcSize(2);
height: calcSize(2);
}

&:hover:after {
padding: calcSize(0.25);
}
}
}
}
Expand All @@ -196,7 +214,7 @@
.sd-progress-buttons__list {
li {
&:not(:first-child)>.sd-progress-buttons__connector {
top: calcSize(1.875);
top: calcSize(2.175);
}
}
}
Expand All @@ -206,4 +224,11 @@
.sd-progress-buttons {
padding: calcSize(2) calcSize(3);
}
}

.sd-progress-buttons--fit-survey-width {
max-width: calcSize(90);
box-sizing: border-box;
width: 100%;
margin: auto;
}
1 change: 1 addition & 0 deletions src/defaultV2-theme/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ $sd-panel-medium-min-width: 176px;
:root {
--sjs-transition-duration: 150ms;
}

$transition-duration: var(--sjs-transition-duration, 150ms);


Expand Down
2 changes: 1 addition & 1 deletion src/knockout/components/progress/buttons.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div data-bind="css: model.getRootCss(container)" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div data-bind="css: model.getRootCss(container), style: { maxWidth: model.progressWidth }" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<!-- ko if: canShowHeader -->
<div data-bind="css: survey.css.progressButtonsHeader">
<div data-bind="css: survey.css.progressButtonsPageTitle, text: model.headerText, attr: { title: model.headerText }"></div>
Expand Down
18 changes: 17 additions & 1 deletion src/progress-buttons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export class ProgressButtons extends Base {
if (this.showItemNumbers && this.survey.css.progressButtonsNumbered) {
result += " " + this.survey.css.progressButtonsNumbered;
}
if (this.isFitToSurveyWidth) {
result += " " + this.survey.css.progressButtonsFitSurveyWidth;
}
return result;
}
public getListElementCss(index: number | any): string {
Expand Down Expand Up @@ -79,11 +82,24 @@ export class ProgressButtons extends Base {
const listContainerElement = element.querySelector("ul");
if (!listContainerElement) return;
const listContainerElements = element.querySelectorAll(".sd-progress-buttons__connector");
const connectorWidth = listContainerElement.clientWidth / (listContainerElement.children.length - 1) - 4;
const circleWidth = this.showItemNumbers ? 17 : 7;
const connectorWidth = listContainerElement.clientWidth / (listContainerElement.children.length - 1) - circleWidth;
for (let i = 0; i < listContainerElements.length; i++) {
(listContainerElements[i] as HTMLDivElement).style.width = connectorWidth + "px";
}
}
public get isFitToSurveyWidth(): boolean {
if (surveyCss.currentType !== "defaultV2") {
return false;
}
return this.survey.progressBarInheritWidthFrom === "survey" && this.survey.widthMode == "static";
}
public get progressWidth(): string {
if (this.isFitToSurveyWidth) {
return this.survey.width;
}
return "";
}
public get showItemNumbers(): boolean {
if (surveyCss.currentType !== "defaultV2") {
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/react/progressButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class SurveyProgressButtons extends SurveyNavigationBase implements IProg
}
render(): JSX.Element {
return (
<div className={this.model.getRootCss(this.props.container)} role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-label="progress">
<div className={this.model.getRootCss(this.props.container)} style={{ "maxWidth": this.model.progressWidth }} role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-label="progress">
{this.state.canShowHeader ? <div className={this.css.progressButtonsHeader}>
<div className={this.css.progressButtonsPageTitle} title={this.model.headerText}>{this.model.headerText}</div>
</div> : null}
Expand Down
22 changes: 22 additions & 0 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,7 @@ export class SurveyModel extends SurveyElementCore
*
* Default value: `false`
* @see progressBarShowPageNumbers
* @see progressBarInheritWidthFrom
*/
@property({
getDefaultValue: (self: SurveyModel) => {
Expand All @@ -2682,8 +2683,22 @@ export class SurveyModel extends SurveyElementCore
*
* Default value: `false`
* @see progressBarShowPageTitles
* @see progressBarInheritWidthFrom
*/
@property() progressBarShowPageNumbers: boolean;
/**
* Specifies whether the progress bar spans the width of the survey or that of the survey container. Applies only when the [progress bar is visible](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#showProgressBar) and [`progressBarType`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#progressBarType) is `"pages"`.
*
* Possible values:
*
* - `"survey"`\
* The progress bar width is the same as the survey width.
* - `"container"` (default)\
* The progress bar width is the same as the survey container width.
* @see progressBarShowPageTitles
* @see progressBarShowPageNumbers
*/
@property() progressBarInheritWidthFrom: "survey" | "container";
public get isShowProgressBarOnTop(): boolean {
if (!this.canShowProresBar()) return false;
return ["auto", "aboveheader", "belowheader", "topbottom", "top", "both"].indexOf(this.showProgressBar) !== -1;
Expand Down Expand Up @@ -7825,6 +7840,13 @@ Serializer.addClass("survey", [
category: "navigation",
visibleIf: (obj: any) => { return obj.showProgressBar !== "off" && obj.progressBarType === "pages"; }
},
{
name: "progressBarInheritWidthFrom",
default: "container",
choices: ["container", "survey"],
category: "navigation",
visibleIf: (obj: any) => { return obj.showProgressBar !== "off" && obj.progressBarType === "pages"; }
},
{
name: "showTOC:switch",
default: false
Expand Down
2 changes: 1 addition & 1 deletion src/vue/progressButtons.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div :class="model.getRootCss(container)" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div :class="model.getRootCss(container)" :style="{'maxWidth': model.progressWidth}" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="progress">
<div v-if="canShowHeader" :class="survey.css.progressButtonsHeader">
<div :class="survey.css.progressButtonsPageTitle" :title="model.headerText">{{ model.headerText }}</div>
</div>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions visualRegressionTests/tests/defaultV2/progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,57 @@ frameworks.forEach(framework => {
await takeElementScreenshot("survey-custom-navigation.png", Selector(".sd-container-modern"), t, comparer);
});
});
test("Check survey with progress top pages - hover", async (t) => {
await wrapVisualTest(t, async (t, comparer) => {
await t.resizeWindow(1920, 1080);
await initSurvey(framework, json);
await ClientFunction(() => {
(<any>window).survey.progressBarType = "pages";
(<any>window).survey.currentPageNo = 1;
})();
const progressBarItemsSelector = Selector(".sd-progress-buttons__list li");
await t.hover(progressBarItemsSelector.nth(0));
await takeElementScreenshot("survey-progress-bar-hover-visited.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
await t.hover(progressBarItemsSelector.nth(1));
await takeElementScreenshot("survey-progress-bar-hover-current.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
await t.hover(progressBarItemsSelector.nth(2));
await takeElementScreenshot("survey-progress-bar-hover-next.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
});
});
test("Check survey with progress top buttons - hover", async (t) => {
await wrapVisualTest(t, async (t, comparer) => {
await t.resizeWindow(1920, 1080);
await initSurvey(framework, json);
await ClientFunction(() => {
(<any>window).survey.progressBarShowPageNumbers = true;
(<any>window).survey.currentPageNo = 1;
})();
const progressBarItemsSelector = Selector(".sd-progress-buttons__list li");
await t.hover(progressBarItemsSelector.nth(0));
await takeElementScreenshot("survey-progress-bar-buttons-hover-visited.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
await t.hover(progressBarItemsSelector.nth(1));
await takeElementScreenshot("survey-progress-bar-buttons-hover-current.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
await t.hover(progressBarItemsSelector.nth(2));
await takeElementScreenshot("survey-progress-bar-buttons-hover-next.png", Selector(".sd-progress-buttons"), t, comparer); // title + progress
});
});
test("Check survey with progress top - progressBarInheritWidthFrom modes", async (t) => {
await wrapVisualTest(t, async (t, comparer) => {
await t.resizeWindow(1920, 1080);
await initSurvey(framework, json);
await ClientFunction(() => {
(<any>window).survey.progressBarType = "pages";
(<any>window).survey.progressBarInheritWidthFrom = "survey";
(<any>window).survey.widthMode = "static";
(<any>window).survey.currentPageNo = 1;
})();
await takeElementScreenshot("survey-progress-bar-top-survey-width-static.png", Selector(".sd-container-modern"), t, comparer);
await ClientFunction(() => {
(<any>window).survey.width = "1400px";
})();
await t.resizeWindow(1900, 1000);
await t.wait(500);
await takeElementScreenshot("survey-progress-bar-top-survey-width-static-1400.png", Selector(".sd-container-modern"), t, comparer);
});
});
});
Loading