Skip to content

Commit

Permalink
feat(ui): add option to make steps scrollable EBS-1314 (#227)
Browse files Browse the repository at this point in the history
* feat(ui): add option to make steps scrollable EBS-1314

* fix(ui): axe storybook check EBS-1314

* feat(ui): code review changes EBS-1314

* fix(ui): axe aria-label error EBS-1314

---------

Co-authored-by: Vanessa.Jalakas <vanessa.jalakas@nortal.ee>
  • Loading branch information
kasutajaVJ and Vanessa.Jalakas authored May 8, 2024
1 parent 73a81dd commit 6d77fb1
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 59 deletions.
8 changes: 8 additions & 0 deletions apps/ui-e2e/src/component/steps.component.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ describe('StepsComponent', () => {
cy.wait(1500);
cy.runStepsCommonTest();
});

it('Renders steps with scrollbar and clicks right button to make left button visible', () => {
cy.loadStory('Angular Steps Steps', 'Default with scroll');
cy.shouldNotExist('button[aria-label="Scroll left"]');
cy.get('button[aria-label="Scroll right"]').click();

cy.shouldExist('button[aria-label="Scroll left"]');
});
});
61 changes: 60 additions & 1 deletion libs/styles/src/lib/scss/components/_steps.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@
flex-direction: column;
}
@include cvi-breakpoint-up(sm) {
#{$base}.is-scrollable & {
display: flex;
padding-left: get-spacing('loksa');
padding-right: get-spacing('loksa');
}

display: grid;
grid-template-columns: repeat(auto-fit, minmax(209px, 1fr));
column-gap: 0;
Expand All @@ -99,6 +105,11 @@

}
@include cvi-breakpoint-up(sm) {
#{$base}.is-scrollable & {
min-width: 247px;
height: 100%;
}

min-height: 72px;
flex-grow: 1;
flex-shrink: 1;
Expand Down Expand Up @@ -347,5 +358,53 @@
@include cvi-screenreader-text;
}
}

#{$base}.is-scrollable {
#{$base}__scroll-wrapper {
position: relative;
}
#{$base}__scroll-container {
@include cvi-breakpoint-down(sm) {
display: grid;
}

display: flex;
width: 100%;
overflow-x: auto;
scrollbar-width: none;
scroll-behavior: smooth;
}
}

#{$base}__scroll-button {
@include cvi-breakpoint-down(sm) {
display: none;
}
@include cvi-breakpoint-up(sm) {
position: absolute;
z-index: get-z-index('steps', '__scroll-button');
height: calc(100% - get-spacing('kuressaare'));
width: 32px;
background-color: get-color(black-coral-20);
opacity: 0.8;
display: flex;
line-height: 0;
justify-content: center;
align-items: center;

&--left-scroll {
left: 0;
}

&--right-scroll {
right: 0;
}
}
}

#{$base}__scroll-button-icon {
height: get-spacing('haapsalu');
fill: get-color(white);
}
}
}
}
3 changes: 3 additions & 0 deletions libs/styles/src/lib/scss/settings/variables/_z-indexes.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ $cvi-z-indexes: (
'datepicker': (
'__calender',
),
'steps': (
'__scroll-button',
),
);
133 changes: 80 additions & 53 deletions libs/ui/src/lib/steps/steps/steps.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,88 @@ <h1 *ngIf="title" class="cvi-steps__title" dataAttribute="steps_title">{{ title
</div>
<div class="cvi-steps__inner-wrapper">
<div class="cvi-steps__inner" dataAttribute="steps_container">
<ol class="cvi-steps__list">
<li class="cvi-steps__list-item"
*ngFor="let stepTitle of stepTitles; let i = index"
[ngClass]="{'is-past': this.currentStepIndex !== null && i <= currentStepIndex, 'is-current': i === currentStepIndex}"
[dataAttribute]="'cvi-steps__list-item_' + i">
<button class="cvi-steps__list-item-button" [dataAttribute]="'cvi-steps__list-item-button_' + i"
(click)="stepSelected(i)">
<cvi-ng-track [layout]="'flex'" [horizontalAlignment]="'justify'" [verticalAlignment]="'center'">
<div class="cvi-steps__list-item-circle-wrapper--desktop">
<cvi-ng-track [gap]="2" [verticalAlignment]="'center'">
<cvi-ng-circle
[theme]="i === currentStepIndex || this.stepStatuses[i] === 'success' || this.stepStatuses[i] === 'error' ? 'light' : 'dark'"
[severity]="this.stepStatuses[i] | toStepCircleSeverity"
[iconName]="this.stepStatuses[i] | toStepCircleIconName">
{{ i + 1 }}
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ stepTitle }}</span>
</cvi-ng-track>
</div>
<div class="cvi-steps__list-item-circle-wrapper--mobile">
<cvi-ng-track [gap]="4" [verticalAlignment]="'center'">
<cvi-ng-circle
size="m"
style="--cvi-circle-border-color: var(--cvi-color-sapphire-blue-10); --cvi-circle-color: var(--cvi-color-sapphire-blue-10);"
[progressPercentage]="anyStepSelected ? currentProgressCSSVar : undefined">
{{ i + 1 }}
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ stepTitle }}</span>
<div class="cvi-steps__scroll-wrapper">
<div #stepScrollBar class="cvi-steps__scroll-container">
<div>
<button *ngIf="isScrollable && !leftEdgeVisible"
aria-label="Scroll left"
class="cvi-steps__scroll-button cvi-steps__scroll-button--left-scroll"
(click)="onClickScroll(-150)">
<cvi-ng-icon [name]="'arrow_a_left'"
svgClass="cvi-steps__scroll-button-icon">
</cvi-ng-icon>
</button>

<button *ngIf="isScrollable && !rightEdgeVisible"
aria-label="Scroll right"
class="cvi-steps__scroll-button cvi-steps__scroll-button--right-scroll"
(click)="onClickScroll(150)">
<cvi-ng-icon [name]="'arrow_a_right'"
svgClass="cvi-steps__scroll-button-icon">
</cvi-ng-icon>
</button>
</div>

<div #leftEdge style="width: 1px"></div>
<ol class="cvi-steps__list">
<li class="cvi-steps__list-item"
*ngFor="let stepTitle of stepTitles; let i = index"
[ngClass]="{'is-past': this.currentStepIndex !== null && i <= currentStepIndex, 'is-current': i === currentStepIndex}"
[dataAttribute]="'cvi-steps__list-item_' + i">
<button class="cvi-steps__list-item-button" [dataAttribute]="'cvi-steps__list-item-button_' + i"
(click)="stepSelected(i)">
<cvi-ng-track [layout]="'flex'" [horizontalAlignment]="'justify'" [verticalAlignment]="'center'">
<div class="cvi-steps__list-item-circle-wrapper--desktop">
<cvi-ng-track [gap]="2" [verticalAlignment]="'center'">
<cvi-ng-circle
[theme]="i === currentStepIndex || this.stepStatuses[i] === 'success' || this.stepStatuses[i] === 'error' ? 'light' : 'dark'"
[severity]="this.stepStatuses[i] | toStepCircleSeverity"
[iconName]="this.stepStatuses[i] | toStepCircleIconName">
{{ i + 1 }}
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ stepTitle }}</span>
</cvi-ng-track>
</div>
<div class="cvi-steps__list-item-circle-wrapper--mobile">
<cvi-ng-track [gap]="4" [verticalAlignment]="'center'">
<cvi-ng-circle
size="m"
style="--cvi-circle-border-color: var(--cvi-color-sapphire-blue-10); --cvi-circle-color: var(--cvi-color-sapphire-blue-10);"
[progressPercentage]="anyStepSelected ? currentProgressCSSVar : undefined">
{{ i + 1 }}
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ stepTitle }}</span>
</cvi-ng-track>
</div>
<cvi-ng-track [gap]="4">
<cvi-ng-icon [name]="'arrow_a_right'" class="cvi-steps__list-item-arrow-icon-wrapper"
[svgClass]="'cvi-steps__list-item-arrow-icon'"></cvi-ng-icon>
</cvi-ng-track>
</cvi-ng-track>
</div>
<cvi-ng-track [gap]="4">
<cvi-ng-icon [name]="'arrow_a_right'" class="cvi-steps__list-item-arrow-icon-wrapper"
[svgClass]="'cvi-steps__list-item-arrow-icon'"></cvi-ng-icon>
</cvi-ng-track>
</cvi-ng-track>
</button>
</li>
<li *ngIf="urlStepTitle"
class="cvi-steps__list-item cvi-steps__list-item--is-url-step">
<button class="cvi-steps__list-item-button" style="background-color: white;" (click)="urlStepClicked()">
<cvi-ng-track [layout]="'flex'" [horizontalAlignment]="'justify'" [verticalAlignment]="'center'">
<div class="cvi-steps__list-item-circle-wrapper--desktop">
<cvi-ng-track [gap]="2" [verticalAlignment]="'center'">
<cvi-ng-circle [iconName]="'arrow_a_right'"
[theme]="'light'"
[severity]="'info'"
style="--cvi-circle-border-color: var(--cvi-color-sapphire-blue-13)">
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ urlStepTitle }}</span>
</button>
</li>
<li *ngIf="urlStepTitle"
class="cvi-steps__list-item cvi-steps__list-item--is-url-step">
<button class="cvi-steps__list-item-button" style="background-color: white;" (click)="urlStepClicked()">
<cvi-ng-track [layout]="'flex'" [horizontalAlignment]="'justify'" [verticalAlignment]="'center'">
<div class="cvi-steps__list-item-circle-wrapper--desktop">
<cvi-ng-track [gap]="2" [verticalAlignment]="'center'">
<cvi-ng-circle [iconName]="'arrow_a_right'"
[theme]="'light'"
[severity]="'info'"
style="--cvi-circle-border-color: var(--cvi-color-sapphire-blue-13)">
</cvi-ng-circle>
<span class="cvi-steps__list-item-title">{{ urlStepTitle }}</span>
</cvi-ng-track>
</div>
</cvi-ng-track>
</div>
</cvi-ng-track>
</button>
</li>
</ol>
</button>
</li>
</ol>
<div #rightEdge style="width: 1px"></div>
</div>
</div>

<ng-content></ng-content>
<div *ngIf="this.stepChildren.length > 1 && this.currentStepIndex !== null"
class="cvi-steps__directional-buttons"
Expand Down
16 changes: 14 additions & 2 deletions libs/ui/src/lib/steps/steps/steps.component.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default {
args: {
title: 'Abiellumine',
currentStepIndex: null,
isScrollable: false,
stepsContent: [
'<a href="https://www.eesti.ee">Nevertheless, Cosy Moments thrives. It has its public.</a>',
'Its contents are mildly interesting, if you like that sort of thing.',
Expand All @@ -57,7 +58,7 @@ const DefaultTemplate: StoryFn<StepsComponent> = (args: StepsComponent) => {
},
/* template */
template: `
<cvi-ng-steps [title]="title" [currentStepIndex]="currentStepIndex" [hasTableOfContents]="hasTableOfContents">
<cvi-ng-steps [title]="title" [currentStepIndex]="currentStepIndex" [hasTableOfContents]="hasTableOfContents" [isScrollable]="isScrollable">
<p cvi-steps="after-title" dataAttribute="steps-description">You can now add custom content before steps</p>
<cvi-ng-step dataAttribute="step_1">
<cvi-ng-step-panel [title]="title">
Expand Down Expand Up @@ -105,6 +106,18 @@ export const DefaultWithSelectedStep = {
},
};

export const DefaultWithScroll = {
...Default,
parameters: {
viewport: {
defaultViewport: 'ipad',
},
},
args: {
isScrollable: true,
},
};

export const Mobile = {
...Default,
parameters: {
Expand Down Expand Up @@ -257,7 +270,6 @@ export const WithStepStatus = {
};

const TemplateWithUrlStep: StoryFn = (args) => ({
component: StepsComponent,
props: {
...args,
urlClicked: false,
Expand Down
Loading

0 comments on commit 6d77fb1

Please sign in to comment.