Parcourir la source

Home page UI

master
kj1352 il y a 4 ans
Parent
révision
795d4a44d5
4 fichiers modifiés avec 462 ajouts et 40 suppressions
  1. +75
    -25
      src/app/home/home.page.html
  2. +317
    -11
      src/app/home/home.page.scss
  3. +53
    -4
      src/app/home/home.page.ts
  4. +17
    -0
      src/global.scss

+ 75
- 25
src/app/home/home.page.html Voir le fichier

@@ -1,26 +1,43 @@
<ion-content>
<h2 class="main-header"> Home </h2>
<figure class="theme-bg-image">
<img src="assets/home-team/KXIP-lion-white.svg">
</figure>

<div class="heading-holder">
<h2 class="main-header"> Home </h2>
<section class="segments">
<button [ngClass]="{'active' : selectedTab === 'news'}"
(click)="selectedTab = 'news'"> News ({{ newsData.length }}) </button>
<button [ngClass]="{'active' : selectedTab === 'videos'}"
(click)="selectedTab = 'videos'"> Videos </button>
</section>
<section class="segments">
<button [ngClass]="{'active' : selectedTab === 'news'}"
(click)="selectedTab = 'news'"> News ({{ newsData.length }}) </button>
<button [ngClass]="{'active' : selectedTab === 'videos'}"
(click)="selectedTab = 'videos'"> Videos </button>
</section>
</div>

<button (click)="closeArticle()"
class="close-article-button"
[ngClass]="{'active' : selectedArticle !== null }">
<ion-icon name="close"></ion-icon>
</button>

<ion-slides [options]="slideOpts">
<ion-slide *ngFor="let news of newsData">
<ion-slides [options]="slideOpts" *ngIf="selectedTab === 'news'"
[ngClass]="{'active' : selectedArticle !== null}">

<ion-slide *ngFor="let news of newsData; let i = index">
<div class="image-holder">
<figure>
<img [src]="news.image">
</figure>

<button *ngIf="news.type === 'VIDEO'">
<button
[ngClass]="{'active' : selectedArticle !== null}"
*ngIf="news.type === 'VIDEO'">
<ion-icon name="play"></ion-icon>
</button>

<button *ngIf="news.type === 'ARTICLE'">
<button
[ngClass]="{'hide' : selectedArticle !== null}"
*ngIf="news.type === 'ARTICLE'">
<ion-icon name="newspaper"></ion-icon>
</button>
</div>
@@ -28,30 +45,63 @@
<section class="content">
<h4> {{ news.heading }} </h4>

<p>
<div class="details">
{{ news.description }}
</p>
</div>
</section>


<section class="comments" *ngIf="selectedArticle !== null">
<header> Comments </header>
<ul>
<li *ngFor="let comment of news.comments">
<p> {{ comment.comment }} <label> - {{ comment.user }} </label> </p>

<button (click)="comment.isLiked = !comment.isLiked"
[ngClass]="{'active' : comment.isLiked}">
<ion-icon *ngIf="!comment.isLiked" name="heart-outline"></ion-icon>
<ion-icon *ngIf="comment.isLiked" name="heart"></ion-icon>
<span> {{ comment.isLiked ? comment.likes + 1 : comment.likes }} </span>
</button>
</li>
<div class="input-holder" id="comment-input">
<input type="text" placeholder="Type your comment" [(ngModel)]="myComment">
<button (click)="postComment()"> <ion-icon name="send"></ion-icon> </button>
</div>
</ul>
</section>

<section class="action-buttons">
<section class="shortcuts">
<button>
<ion-icon name="share-social-outline"></ion-icon>
</button>

<button (click)="news.isLiked = !news.isLiked"
<button class="wide-button" (click)="news.isLiked = !news.isLiked"
[ngClass]="{'active' : news.isLiked}">
<ion-icon *ngIf="!news.isLiked" name="heart-outline"></ion-icon>
<ion-icon *ngIf="news.isLiked" name="heart"></ion-icon>
<span> {{ news.isLiked ? news.likes + 1 : news.likes }} </span>
</button>
</button>

<button>
<ion-icon name="share-social-outline"></ion-icon>
</button>
</section>

<button class="read-more">
<span *ngIf="news.type === 'ARTICLE'"> Read More </span>
<span *ngIf="news.type === 'VIDEO'"> Watch </span>
<ion-icon name="chevron-forward-outline"></ion-icon> </button>
<section class="shortcuts" *ngIf="selectedArticle !== null">
<button (click)="news.isBookmarked = !news.isBookmarked"
[ngClass]="{'active' : news.isBookmarked}">
<ion-icon *ngIf="!news.isBookmarked" name="bookmark-outline"></ion-icon>
<ion-icon *ngIf="news.isBookmarked" name="bookmark"></ion-icon>
</button>

<button class="wide-button" (click)="scrollToAddComment()">
<ion-icon name="chatbubble-outline"></ion-icon>
<span> {{ news.comments.length }} </span>
</button>
</section>

<button class="read-more" (click)="expandArticle(i)">
<span> More </span>
<ion-icon name="chevron-forward-outline"></ion-icon>
</button>
</section>

</ion-slide>


+ 317
- 11
src/app/home/home.page.scss Voir le fichier

@@ -1,5 +1,12 @@
ion-content {
--background: var(--brand-black);
--background: var(--brand-black);
}

.heading-holder {
position: fixed;
top: 0;
left: 0;
width: 100%;
}

.main-header {
@@ -48,9 +55,126 @@ ion-content {
}
}

.close-article-button {
width: 40px;
height: 40px;
position: fixed;
top: 10px;
right: 10px;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(#ffff, 0.5);
border-radius: 50%;
z-index: 3;
opacity: 0;
transform: translateY(10px);
pointer-events: none;
transition: opacity 0.3s, transform 0.3s;

&.active {
opacity: 1;
transition-delay: 1s;
transform: translateY(0px);
pointer-events: all;
}

ion-icon {
color: white;
font-size: 20px;
}
}

ion-slides {
margin: 12% 0%;
margin-top: 40%;
height: calc(100vh - 40%);
position: relative;
left: 0;
top: 0;
transition: transform 0.5s, height 0.3s, margin 0.3s, width 0.3s;
z-index: 1;

&.active {
margin: 0px;
width: 100%;
transform: translate(0, 0%);
height: calc(100vh - 56px);

ion-slide {
background-color: white;
border-radius: 0px;
overflow: auto;

.content {
width: 90%;
height: auto;
background-color: white;
transform: translateY(-30px);
position: relative;
border-radius: 10px;
transition-delay: 0.3s;
overflow: auto;
border-width: 0px;
box-shadow: 0px 0px 15px rgba(var(--light-grey-rgb), 0.3);

h4, .details {
opacity: 0;
animation: showUpContent 0.3s forwards;
animation-delay: 0.3s;
}
}

.action-buttons {
width: 90%;
background-color: white;
border-radius: 10px;
position: sticky;
position: -webkit-sticky;
bottom: 0;
z-index: 2;
box-shadow: 0px 0px 15px rgba(var(--light-grey-rgb), 0.3);
justify-content: center;
height: 60px;

.shortcuts {
width: 50%;

button {
background-color: rgba(var(--light-grey-rgb), 0.1);
margin: 0 auto;
width: 40px;
height: 40px;
&.wide-button {
width: auto;
padding: 0 10px;
}
}
}

.read-more {
display: none;
}
}
.image-holder figure {
filter: brightness(30%);
}
}
}
@keyframes showUpContent {
0% {
opacity: 0;
transform: translateY(20px);
-webkit-line-clamp: 4;
}
100% {
opacity: 1;
-webkit-line-clamp: unset;
transform: translateY(0px);
}
}

ion-slide {
display: block;
@@ -59,10 +183,13 @@ ion-slides {
text-align: left;
align-self: start;
height: 100%;
transition: width 0.5s, transform 0.3s, margin 0.3s;
}

.image-holder {
position: relative;
position: sticky;
position: -webkit-sticky;
top: 0;
height: 40%;
overflow: hidden;

@@ -77,10 +204,41 @@ ion-slides {
justify-content: center;
background-color: rgba(#ffff, 0.5);
border-radius: 50%;
transition: transform 0.3s, background-color 0.3s, opacity 0.3s;

&.hide {
opacity: 0;
pointer-events: none;
}

&.active {
transform: translate(calc(-50vw + 40px), -15vh);
animation: ripple 1s infinite;
background-color: rgba(var(--brand-red-rgb), 0.5);

ion-icon {
color: white;
}
}

@keyframes ripple {
0% {
box-shadow: 0px 0px 0px var(--brand-red);
}
50% {
box-shadow: 0px 0px 5px var(--brand-red);
}

100% {
box-shadow: 0px 0px 0px var(--brand-red);
}
}

ion-icon {
color: white;
font-size: 20px;
transition: color 0.3s;
}
}

@@ -90,6 +248,7 @@ ion-slides {
width: 100%;
height: 100%;
filter: brightness(60%);
transition: filter 0.3s;

img {
height: 100%;
@@ -102,11 +261,18 @@ ion-slides {

.content {
background-color: white;
padding: 5%;
padding: 0px 5% 5% 5%;
width: 100%;
margin: 0 auto;
height: calc(60% - 50px);
overflow: hidden;
margin-top: -1px;
border-bottom: 1px solid rgba(var(--light-grey-rgb), 0.8);
border-radius: 0px;
transform: translateY(0px);
box-shadow: 0px 0px 0px var(--light-grey);
transition: border-radius 0.3s, transform 0.3s, width 0.3s, margin 0.3s, box-shadow 0.3s;
border-bottom: 1px solid rgba(var(--light-grey-rgb), 0.3);
z-index: 2;
}

h4 {
@@ -114,11 +280,18 @@ ion-slides {
margin: 0px;
line-height: 1.5;
font-weight: 500;
color: var(--brand-black);
color: var(--brand-black);
transition: opacity 0.1s;
background-color: white;
position: sticky;
position: -webkit-sticky;
top: 1px;
z-index: 1;
padding: 10px 0;
}
p {
margin: 5px 0px 0px 0px;
.details {
margin: 0px;
font-size: 0.9rem;
line-height: 1.5;
font-weight: 400;
@@ -127,6 +300,7 @@ ion-slides {
-webkit-box-orient: vertical;
color: var(--light-grey);
overflow: hidden;
transition: opacity 0.1s;
}

.action-buttons {
@@ -136,16 +310,31 @@ ion-slides {
width: 100%;
height: 50px;
margin-top: -1px;
padding: 0 3%;
padding: 0 3%;
position: relative;
box-shadow: 0px 0px 0px var(--light-grey);
transition: border-radius 0.3s, transform 0.3s, width 0.3s, margin 0.3s, box-shadow 0.3s;
z-index: 1;
margin: 0 auto 20px;

.shortcuts {
display: flex;
align-items: stretch;
align-items: center;
height: 100%;

button {
background-color: transparent;
background-color: #f3f3f3;
margin-right: 5px;
width: 30px;
height: 30px;
border-radius: 50%;

&.wide-button {
width: auto;
border-radius: 5px;
padding: 0 10px;
}

&.active {
ion-icon, span {
@@ -153,6 +342,14 @@ ion-slides {
}
}

// &.bookmark-button {
// &.active {
// ion-icon, span {
// color: var(--light-grey);
// }
// }
// }

span {
vertical-align: middle;
color: var(--light-grey);
@@ -181,4 +378,113 @@ ion-slides {
}
}

.comments {
background-color: white;
width: 90%;
position: relative;
box-shadow: 0px 0px 0px var(--light-grey);
z-index: 1;
margin: 0px auto 20px;
border-radius: 10px;
box-shadow: 0px 0px 15px rgba(var(--light-grey-rgb), 0.3);
border-radius: 10px;
overflow: hidden;
header {
font-size: 1.1rem;
margin: 0px;
line-height: 1.5;
font-weight: 500;
color: var(--brand-black);
transition: opacity 0.1s;
background-color: white;
padding: 10px 5%;
}

ul {
list-style: none;
padding: 0;
margin: 0;

li {
padding: 5px 5% 10px;
border-top: 1px solid rgba(var(--light-grey-rgb), 0.3);
line-height: 1.5;
}

label {
font-size: 1rem;
font-weight: 500;
letter-spacing: 1px;
color: rgba(var(--brand-red-rgb), 0.8);
}

p {
margin: 3px 0;
font-size: 1rem;
font-weight: 400;
color: var(--light-grey);
}

button {
background-color: #f3f3f3;
margin-right: 5px;
height: 30px;
width: auto;
border-radius: 5px;
padding: 0 5px;

span {
vertical-align: middle;
color: var(--light-grey);
}
ion-icon {
vertical-align: middle;
color: var(--brand-black);
font-size: 1rem;
}

&.active {
ion-icon, span {
color: var(--brand-red);
}
}
}

.input-holder {
display: flex;
width: 100%;
height: 70px;
align-items: center;

input {
width: calc(100% - 80px);
margin: 0 auto;
border: 1px solid rgba(var(--light-grey-rgb), 0.3);
border-radius: 30px;
font-size: 14px;
color: var(--brand-black);
font-weight: 500;
height: 40px;
padding: 0 15px;
}

button {
width: 40px;
height: 40px;
background-color: var(--brand-red);
margin: 0 auto;
border-radius: 50%;

ion-icon {
color: white;
font-size: 16px;
}
}
}
}
}

}

+ 53
- 4
src/app/home/home.page.ts Voir le fichier

@@ -7,6 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class HomePage implements OnInit {
selectedTab: string = 'news';
selectedArticle: number = null;
myComment: string = '';

slideOpts = { };

@@ -22,7 +24,8 @@ export class HomePage implements OnInit {
comments: Array<{
user: string,
comment: string,
likes: number
likes: number,
isLiked: boolean
}>,
}> = [];

@@ -34,7 +37,14 @@ export class HomePage implements OnInit {
id: 1,
image: 'https://s3.india.com/wp-content/uploads/2020/10/Mayank-Agarwal-celebrates-Kings-XI-Punjabs-win-over-Mumbai-Indians-in-match-37-of-Dream11-IPL-2020-in-Dubai%C2%A9KXIP-Twitter.jpg',
heading: 'KXIP beat MI by 3 Wickets',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis ullam. Explicabo accusantium quia tempore totam repellat amet debitis adipisci deserunt iste.',
description: `Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis ullam.
Explicabo accusantium quia tempore totam repellat amet debitis adipisci deserunt iste.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis u
santium quia tempore totam repellat amet debitis adipisci deserunt iste.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis u
santium quia tempore totam repellat amet debitis adipisci deserunt iste.`,
type: 'VIDEO',
likes: 10,
isLiked: false,
@@ -43,16 +53,18 @@ export class HomePage implements OnInit {
user: 'kxipFan',
comment: 'Yay!',
likes: 2,
isLiked: true,
}, {
user: 'SehwagFan',
comment: 'finally!',
likes: 5,
isLiked: false,
}]
}, {
id: 2,
image: 'https://www.ak4tsay1.com/wp-content/uploads/2020/02/Kings-XI-Punjab-KXIP-Strengths-and-Weakness-for-IPL-2020-800x445.jpg',
heading: 'KL Rahul scores fastest 100',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis ullam. Explicabo accusantium quia tempore totam repellat amet debitis adipisci deserunt iste.',
description: `Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste ab qui, incidunt illo dolore laboriosam sapiente deserunt officiis ullam. Explicabo accusantium quia tempore totam repellat amet debitis adipisci deserunt iste.`,
type: 'ARTICLE',
isLiked: false,
isBookmarked: false,
@@ -65,8 +77,45 @@ export class HomePage implements OnInit {
spaceBetween: 30,
slidesOffsetBefore: 30,
slidesOffsetAfter: 30,
}
};

}

expandArticle(index: number) {
this.selectedArticle = index;

this.slideOpts = {
slidesPerView: 1,
spaceBetween: 0,
slidesOffsetBefore: 0,
slidesOffsetAfter: 0,
};
}

closeArticle() {
this.selectedArticle = null;
this.slideOpts = {
slidesPerView: 1.3,
spaceBetween: 30,
slidesOffsetBefore: 30,
slidesOffsetAfter: 30,
};
}

postComment() {
this.newsData[this.selectedArticle].comments.push({
user: 'Test',
comment: this.myComment,
isLiked: false,
likes: 0,
});

this.myComment = '';
}

scrollToAddComment() {
document.querySelector('#comment-input').scrollIntoView({behavior: "smooth", block: "start"});
}

}

+ 17
- 0
src/global.scss Voir le fichier

@@ -32,4 +32,21 @@
outline: none;
text-decoration: none;
letter-spacing: 0.5px;
}

.theme-bg-image {
position: fixed;
opacity: 0.1;
width: 100%;
height: 100%;
display: flex;
align-items: flex-start;
justify-content: center;
left: 0;
top: 0;

img {
display: block;
width: 80%;
}
}

Chargement…
Annuler
Enregistrer