Implements Initial Stack Slider

This commit is contained in:
2023-11-08 04:15:18 -03:00
parent 100926b20d
commit 0b32845c2b
17 changed files with 327 additions and 48 deletions

View File

@@ -11,12 +11,14 @@ import { AppServiceWorkerModule } from './app-service-worker.module';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { FooterComponent } from './footer/footer.component';
import {HomeModule} from "./home/home.module";
@NgModule({
declarations: [AppComponent, HomeComponent, FooterComponent],
declarations: [AppComponent, FooterComponent],
imports: [
BrowserModule,
HeaderModule,
HomeModule,
AppRouterModule,
AppServiceWorkerModule,
SharedModule,

View File

@@ -7,7 +7,6 @@
background: rgb(46,46,46);
background: linear-gradient(180deg, rgba(46,46,46,1) 65%, rgba(46,46,46,0.45) 100%);
z-index: 50;
height: 10vh;

View File

@@ -97,10 +97,10 @@
.stack-section {
background: rgb(241,241,241);
/*background: linear-gradient(0deg, rgba(241,241,241,1) 80%, rgba(51,51,51,1) 100%);*/
height: 90vh;
height: 80vh;
}
.stack {
height: 60%;
height: 35%;
display: flex;
flex-direction: column;
justify-content: center;

View File

@@ -39,6 +39,7 @@
</div>
<div class="stack-slider">
<app-stack-slider>
</app-stack-slider>
</div>
</div>

View File

@@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {HomeComponent} from "./home.component";
import {StackSliderComponent} from "./stack-slider/stack-slider.component";
import {StackCardComponent} from "./stack-slider/stack-card/stack-card.component";
import {NgxGlideComponent} from "ngx-glide";
@NgModule({
declarations: [
HomeComponent,
StackSliderComponent,
StackCardComponent
],
imports: [
CommonModule,
NgxGlideComponent
]
})
export class HomeModule { }

View File

@@ -0,0 +1,40 @@
.stack-card {
width: 300px;
border-radius: 15px;
}
.stack-card-image {
width: 100%;
border-top-left-radius: 15px !important;
border-top-right-radius: 15px !important;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.stack-card-body {
padding: 10px;
flex-grow: 1;
width: 250px;
height: 130px;
inline-size: 250px;
}
.stack-card-text {
word-break: break-all !important;
white-space: normal !important;
}
/*CARD STATE*/
.active {
opacity: 1;
width: 300px;
}
.inactive {
opacity: 0.85;
width: 275px;
}

View File

@@ -0,0 +1,7 @@
<div class="card stack-card inactive" [@cardAnimation]="cardState">
<img class="card-img-top stack-card-image" [src]="stack.image" alt="Stack Image">
<div class="card-body stack-card-body">
<h5 class="card-title stack-card-title">{{stack.name}}</h5>
<p class="card-text stack-card-text">{{stack.description}}</p>
</div>
</div>

View File

@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { StackCardComponent } from './stack-card.component';
describe('StackCardComponent', () => {
let component: StackCardComponent;
let fixture: ComponentFixture<StackCardComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [StackCardComponent]
});
fixture = TestBed.createComponent(StackCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,35 @@
import {Component, Input} from '@angular/core';
import {Stack} from "../../../shared/model/stack/stack.model";
import {animate, state, style, transition, trigger} from "@angular/animations";
@Component({
selector: 'app-stack-card',
templateUrl: './stack-card.component.html',
styleUrls: ['./stack-card.component.css'],
animations: [
trigger('cardAnimation', [
state('active', style({
opacity: 1,
width: '300px',
})),
state('inactive', style({
opacity: 0.85,
width: '275px',
})),
transition('* => *', [
animate('0.1s')
]),
])
],
})
export class StackCardComponent {
@Input()
stack!: Stack;
@Input()
inFocus: boolean = false;
get cardState(): 'active'|'inactive' {
return this.inFocus ? 'active' : 'inactive';
}
}

View File

@@ -0,0 +1,5 @@
.slider-card {
justify-content: center;
align-items: center;
display: flex;
}

View File

@@ -0,0 +1,9 @@
<ng-container class="container" *ngIf="stacks && stacks.length > 0">
<ngx-glide #ngxGlide>
<ng-container *ngFor="let stack of stacks">
<app-stack-card class="slider-card" [stack]="stack"
[inFocus]="isInFocus(stack)">
</app-stack-card>
</ng-container>
</ngx-glide>
</ng-container>

View File

@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { StackSliderComponent } from './stack-slider.component';
describe('StackSliderComponent', () => {
let component: StackSliderComponent;
let fixture: ComponentFixture<StackSliderComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [StackSliderComponent]
});
fixture = TestBed.createComponent(StackSliderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,76 @@
import {AfterViewInit, ChangeDetectorRef, Component, ViewChild} from '@angular/core';
import {NgxGlideComponent} from "ngx-glide";
import {Stack} from "../../shared/model/stack/stack.model";
@Component({
selector: 'app-stack-slider',
templateUrl: './stack-slider.component.html',
styleUrls: ['./stack-slider.component.css']
})
export class StackSliderComponent implements AfterViewInit {
@ViewChild('ngxGlide')
ngxGlide!: NgxGlideComponent;
stacks: Stack[] = [
{
name: 'Angular',
image: 'https://picsum.photos/id/1/100/100',
description: 'Angular is a platform for building mobile and desktop web applications.',
},
{
name: 'React',
image: 'https://picsum.photos/id/2/100/100',
description: 'React is a JavaScript library for building user interfaces.',
},
{
name: 'Vue',
image: 'https://picsum.photos/id/3/100/100',
description: 'Vue is a progressive framework for building user interfaces.',
},
{
name: 'Svelte',
image: 'https://picsum.photos/id/4/100/100',
description: 'Svelte is a radical new approach to building user interfaces.',
},
{
name: 'Ember',
image: 'https://picsum.photos/id/5/100/100',
description: 'Ember.js is an open-source JavaScript web framework.',
},
{
name: 'Preact',
image: 'https://picsum.photos/id/6/100/100',
description: 'Preact is a fast 3kB alternative to React with the same modern API.',
}
]
constructor(private cd: ChangeDetectorRef) { }
ngAfterViewInit(): void {
if (this.ngxGlide)
this.buildCarousel();
this.cd.detectChanges();
}
buildCarousel(): void {
this.ngxGlide.showArrows = false;
this.ngxGlide.showBullets = false;
this.ngxGlide.type = 'carousel';
this.ngxGlide.perView = 5;
this.ngxGlide.focusAt = 'center';
this.ngxGlide.gap = 10;
this.ngxGlide.autoplay = 3000;
this.ngxGlide.recreate();
}
get currentIndex(): number {
return this.ngxGlide?.getIndex();
}
isInFocus(stack: Stack): boolean {
return this.stacks.indexOf(stack) === this.currentIndex;
}
}

View File

@@ -0,0 +1,5 @@
export interface Stack {
name: string;
image: string;
description: string;
}