Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

Commit 0539e19

Browse files
crisbetoSplaktar
authored andcommitted
feat: more flexible carousels and fix homepage alignment
Currently the carousels on the front page don't align with any other elements on the page which looks odd. This seems to be due to a limitation where the item size has to be passed in to the carousel. These changes reimplement the carousel, making it more flexible and allowing it to handle any size of items and any spacing. The new carousel is used on the frontpage to lay out the items in a way that aligns with the rest of the content.
1 parent 38d3226 commit 0539e19

File tree

7 files changed

+181
-218
lines changed

7 files changed

+181
-218
lines changed

src/app/pages/homepage/_homepage-theme.scss

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,5 @@
5757
}
5858
outline: none;
5959
}
60-
61-
.docs-featured-components-carousel-item:hover {
62-
img {
63-
transform: scale(1.2);
64-
}
65-
66-
box-shadow:inset 0 0 0 1.5px mat.get-color-from-palette($foreground, divider);
67-
}
68-
69-
.docs-featured-components-carousel-item:focus {
70-
img {
71-
transform: scale(1.2);
72-
}
73-
74-
box-shadow:inset 0 0 0 1.5px mat.get-color-from-palette($foreground, disabled);
75-
}
7660
}
7761
}

src/app/pages/homepage/homepage.html

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,38 @@ <h2>Frictionless</h2>
4343
<mat-divider></mat-divider>
4444

4545
<div class="docs-homepage-featured-components docs-homepage-carousel-row">
46-
<h2>Featured components</h2>
47-
<app-carousel [itemWidth]="260" [aria-label]="'Featured components'">
48-
<a *ngFor="let comp of getTopComponents()" carousel-item class='docs-featured-components-carousel-item'
46+
<div class="docs-homepage-header">
47+
<h2>Featured components</h2>
48+
49+
<a class="docs-link" routerLink="/components">
50+
View all components
51+
<mat-icon>chevron_right</mat-icon>
52+
</a>
53+
</div>
54+
<app-carousel [aria-label]="'Featured components'">
55+
<a *ngFor="let comp of getTopComponents()" carousel-item class="carousel-item docs-featured-components-carousel-item"
4956
routerLink="/components/{{comp}}">
5057
<div class="docs-homepage-img-container">
5158
<img alt="" src="../../../assets/screenshots/{{comp}}.scene.png" role="presentation">
5259
</div>
5360
{{(comp[0].toUpperCase() + comp.slice(1)).replace('-', ' ')}}
5461
</a>
5562
</app-carousel>
56-
57-
<a class="docs-link" routerLink="/components">
58-
View all components
59-
<mat-icon>chevron_right</mat-icon>
60-
</a>
6163
</div>
6264

6365
<mat-divider></mat-divider>
6466

6567
<div class="docs-homepage-guides docs-homepage-carousel-row">
66-
<h2>Guides</h2>
67-
<app-carousel [itemWidth]="260" [aria-label]="'Guides'">
68-
<a carousel-item class='docs-homepage-guides-carousel-item' *ngFor="let guide of guideItems.getAllItems()"
68+
<div class="docs-homepage-header">
69+
<h2>Guides</h2>
70+
71+
<a class="docs-link" routerLink="/guides">
72+
View all guides
73+
<mat-icon>chevron_right</mat-icon>
74+
</a>
75+
</div>
76+
<app-carousel [aria-label]="'Guides'">
77+
<a carousel-item class="carousel-item docs-homepage-guides-carousel-item" *ngFor="let guide of guideItems.getAllItems()"
6978
routerLink='/guide/{{guide.id}}'>
7079
<mat-card class="docs-homepage-guides-card">
7180
<mat-card-title>{{guide.name}}</mat-card-title>
@@ -76,11 +85,6 @@ <h2>Guides</h2>
7685
</mat-card>
7786
</a>
7887
</app-carousel>
79-
80-
<a class="docs-link" routerLink="/guides">
81-
View all guides
82-
<mat-icon>chevron_right</mat-icon>
83-
</a>
8488
</div>
8589

8690
</main>

src/app/pages/homepage/homepage.scss

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ $margin-promotion-sections-small: 15px;
5353
display: flex;
5454
flex-direction: column;
5555
padding: 16px;
56+
width: 75%;
57+
max-width: 1080px;
58+
margin: auto;
5659

5760
a {
5861
text-decoration: none;
@@ -61,7 +64,7 @@ $margin-promotion-sections-small: 15px;
6164
h2 {
6265
font-size: 25px;
6366
font-weight: 400;
64-
margin: 16px 0;
67+
margin: 0 0 16px;
6568
padding: 0;
6669
}
6770

@@ -74,37 +77,60 @@ $margin-promotion-sections-small: 15px;
7477
}
7578

7679
mat-divider {
77-
width: 75%;
80+
width: 100%;
7881
}
7982

8083
mat-icon {
8184
vertical-align: middle;
8285
}
8386
}
8487

88+
.carousel-item {
89+
width: 48%;
90+
91+
& + & {
92+
margin-left: 2%;
93+
}
94+
95+
@media (min-width: 1020px) {
96+
max-width: 32%;
97+
}
98+
}
99+
85100
.docs-homepage-row {
86-
width: 75%;
87101
display: flex;
88102
flex-direction: row;
89103
margin: $margin-promotion-sections 0;
90104
}
91105

92106
.docs-homepage-carousel-row {
93107
margin: $margin-promotion-sections 0;
94-
width: 75%;
95108
display: flex;
96109
flex-direction: column;
110+
width: 100%;
97111

98-
a.docs-link {
99-
width: 100%;
100-
text-align: right;
112+
h2 {
113+
margin-top: 0;
101114
}
115+
}
116+
117+
.docs-homepage-header {
118+
display: flex;
119+
width: 100%;
120+
align-items: center;
121+
justify-content: space-between;
122+
margin-bottom: 16px;
102123

103124
h2 {
104-
margin-top: 0;
125+
margin: 0;
105126
}
106127
}
107128

129+
.docs-link {
130+
display: inline-flex;
131+
align-items: center;
132+
}
133+
108134
.docs-homepage-guides {
109135
.docs-homepage-guides-card-divider {
110136
width: 30%;
@@ -113,9 +139,18 @@ $margin-promotion-sections-small: 15px;
113139
}
114140

115141
.docs-homepage-guides-carousel-item {
116-
padding: 15px;
117142
display: flex;
118143
text-decoration: none;
144+
box-sizing: border-box;
145+
146+
// We need a slight padding so the box shadow doesn't get cut off by the carousel.
147+
padding: 3px;
148+
149+
.mat-card {
150+
// Ensures that the cards stretch to the full width of the item.
151+
width: 100%;
152+
min-height: 140px;
153+
}
119154
}
120155

121156
.docs-homepage-guides-card.mat-card {
@@ -131,31 +166,39 @@ $margin-promotion-sections-small: 15px;
131166
}
132167
}
133168

134-
135169
.docs-homepage-featured-components {
136170
.docs-featured-components-carousel-item {
137-
padding: 15px;
138171
text-align: center;
172+
box-sizing: border-box;
173+
font-size: 18px;
139174

140175
.docs-homepage-img-container {
141176
overflow: hidden;
142-
width: 259px;
143-
height: 144px;
144-
margin-bottom: 10px;
177+
margin-bottom: 16px;
178+
max-height: 200px;
145179
}
146180

147181
img {
148182
transition: 0.3s ease-in-out;
149183
width: 100%;
150184
}
185+
186+
&:hover, &:focus {
187+
img {
188+
transform: scale(1.1);
189+
}
190+
}
151191
}
152192
}
153193

154194
.docs-homepage-row-column {
155195
display: flex;
156196
flex-direction: column;
157-
margin: 0 auto;
158-
width: 30%;
197+
width: 32%;
198+
199+
& + & {
200+
margin-left: 2%;
201+
}
159202
}
160203

161204
.docs-header-start {
@@ -187,14 +230,17 @@ $margin-promotion-sections-small: 15px;
187230

188231
.docs-homepage-row-column {
189232
width: 100%;
233+
234+
& + & {
235+
margin-left: 0;
236+
}
190237
}
191238
}
192239

193240
/**
194241
* Rules for when the device is detected to be a small screen.
195242
*/
196243
@media (max-width: 720px) {
197-
198244
.docs-header-start {
199245
margin: $margin-promotion-sections-small 0 0 0;
200246
}

src/app/shared/carousel/carousel.html

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
<button (click)="previous()" *ngIf="this.showPrevArrow" aria-hidden="true" tabindex="-1"
2+
class="docs-carousel-nav docs-carousel-nav-prev" mat-mini-fab aria-label="previous">
3+
<mat-icon>navigate_before</mat-icon>
4+
</button>
5+
16
<div #contentWrapper (keyup)="onKeydown($event)"
2-
(window:resize)="onResize()" [style.minWidth]="shiftWidth + 'px'" class="docs-carousel-content-wrapper" role="region">
3-
<button (click)="previous()" *ngIf="this.showPrevArrow" aria-hidden="true" tabindex="-1"
4-
class="docs-carousel-nav docs-carousel-nav-prev" mat-mini-fab aria-label="previous">
5-
<mat-icon>navigate_before</mat-icon>
6-
</button>
7-
<div class= "docs-carousel-content" role="list" tabindex="0">
7+
class="docs-carousel-content-wrapper" role="region">
8+
<div class="docs-carousel-content" role="list" tabindex="0" #list>
89
<ng-content></ng-content>
910
</div>
10-
<button (click)="next()" *ngIf="this.showNextArrow" aria-hidden="true" tabindex="-1"
11-
class="docs-carousel-nav docs-carousel-nav-next" mat-mini-fab aria-label="next">
12-
<mat-icon>navigate_next</mat-icon>
13-
</button>
1411
</div>
12+
13+
<button (click)="next()" *ngIf="this.showNextArrow" aria-hidden="true" tabindex="-1"
14+
class="docs-carousel-nav docs-carousel-nav-next" mat-mini-fab aria-label="next">
15+
<mat-icon>navigate_next</mat-icon>
16+
</button>

src/app/shared/carousel/carousel.scss

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
app-carousel {
2-
display: flex;
3-
align-items: center;
4-
justify-content: center;
5-
margin: 0 40px;
2+
display: block;
3+
position: relative;
64
}
75

86
.docs-carousel-content {
97
display: flex;
108
flex-direction: row;
11-
overflow: hidden;
129
outline: none;
10+
transition: transform 0.5s ease-in-out;
1311
}
1412

1513
.docs-carousel-content-wrapper {
16-
position: relative;
14+
overflow: hidden;
1715
}
1816

1917
[carousel-item] {
2018
flex-shrink: 0;
21-
transition: transform 0.5s ease-in-out;
2219
}
2320

2421
.docs-carousel-nav {
@@ -28,9 +25,9 @@ app-carousel {
2825
}
2926

3027
.docs-carousel-nav-prev {
31-
left: -40px;
28+
left: -50px;
3229
}
3330

3431
.docs-carousel-nav-next {
35-
right: -40px;
32+
right: -50px;
3633
}

src/app/shared/carousel/carousel.spec.ts

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,63 +39,34 @@ describe('HorizontalCarousel', () => {
3939
component.next();
4040
fixture.detectChanges();
4141

42-
expect(component.index).toEqual(1);
43-
4442
const navPrevious = fixture.nativeElement.querySelector('.docs-carousel-nav-prev');
4543
expect(navPrevious).toBeDefined();
4644
});
4745

4846
it('should hide next nav arrow after reaching end of items', () => {
49-
expect(component.visibleItems).toBe(4);
50-
5147
component.next();
5248
component.next();
53-
expect(component.index).toEqual(2);
5449
fixture.detectChanges();
5550

5651
const navPrevious = fixture.nativeElement.querySelector('.docs-carousel-nav-next');
5752
expect(navPrevious).toBeNull();
58-
59-
// in case of keyboard nav at end of items
60-
component.next();
61-
expect(component.index).toEqual(2);
62-
});
63-
64-
it('should resize carousel when not all content can be displayed', () => {
65-
const carouselWrapper = fixture.nativeElement.querySelector('.docs-carousel-content-wrapper');
66-
fixture.nativeElement.style.width = '1350px';
67-
window.dispatchEvent(new Event('resize'));
68-
69-
fixture.detectChanges();
70-
71-
expect(carouselWrapper.clientWidth).toEqual(1250);
72-
expect(component.visibleItems).toEqual(5);
73-
});
74-
75-
it('should not resize carousel when all content can be displayed', () => {
76-
fixture.componentInstance.numberOfItems = 2;
77-
fixture.detectChanges();
78-
79-
const carouselWrapper = fixture.nativeElement.querySelector('.docs-carousel-content-wrapper');
80-
fixture.nativeElement.style.width = '1350px';
81-
window.dispatchEvent(new Event('resize'));
82-
83-
fixture.detectChanges();
84-
85-
expect(carouselWrapper.clientWidth).toEqual(500);
86-
expect(component.visibleItems).toEqual(2);
8753
});
8854
});
8955

9056
@Component({
9157
selector: 'test-carousel',
9258
template:
9359
`
94-
<app-carousel itemWidth="250">
60+
<app-carousel>
9561
<div carousel-item class="docs-carousel-item-container"
9662
*ngFor="let i of [].constructor(numberOfItems) "></div>
9763
</app-carousel>`,
98-
styles: ['.docs-carousel-item-container { display: flex; }']
64+
styles: [`
65+
.docs-carousel-item-container {
66+
display: flex;
67+
width: 250px;
68+
}
69+
`]
9970
})
10071
class CarouselTestComponent {
10172
numberOfItems = 6;

0 commit comments

Comments
 (0)