浏览代码

Home page UI

master
kj1352 4 年前
父节点
当前提交
795d4a44d5
共有 4 个文件被更改,包括 462 次插入40 次删除
  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 查看文件

@@ -1,26 +1,43 @@
<ion-content> <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"> <div class="image-holder">
<figure> <figure>
<img [src]="news.image"> <img [src]="news.image">
</figure> </figure>


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


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


<p>
<div class="details">
{{ news.description }} {{ 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>

<section class="action-buttons"> <section class="action-buttons">
<section class="shortcuts"> <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}"> [ngClass]="{'active' : news.isLiked}">
<ion-icon *ngIf="!news.isLiked" name="heart-outline"></ion-icon> <ion-icon *ngIf="!news.isLiked" name="heart-outline"></ion-icon>
<ion-icon *ngIf="news.isLiked" name="heart"></ion-icon> <ion-icon *ngIf="news.isLiked" name="heart"></ion-icon>
<span> {{ news.isLiked ? news.likes + 1 : news.likes }} </span> <span> {{ news.isLiked ? news.likes + 1 : news.likes }} </span>
</button>
</button>

<button>
<ion-icon name="share-social-outline"></ion-icon>
</button>
</section> </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> </section>


</ion-slide> </ion-slide>


+ 317
- 11
src/app/home/home.page.scss 查看文件

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

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


.main-header { .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 { ion-slides {
margin: 12% 0%;
margin-top: 40%;
height: calc(100vh - 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 { ion-slide {
display: block; display: block;
@@ -59,10 +183,13 @@ ion-slides {
text-align: left; text-align: left;
align-self: start; align-self: start;
height: 100%; height: 100%;
transition: width 0.5s, transform 0.3s, margin 0.3s;
} }


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


@@ -77,10 +204,41 @@ ion-slides {
justify-content: center; justify-content: center;
background-color: rgba(#ffff, 0.5); background-color: rgba(#ffff, 0.5);
border-radius: 50%; 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 { ion-icon {
color: white; color: white;
font-size: 20px; font-size: 20px;
transition: color 0.3s;
} }
} }


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


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


.content { .content {
background-color: white; background-color: white;
padding: 5%;
padding: 0px 5% 5% 5%;
width: 100%;
margin: 0 auto;
height: calc(60% - 50px); height: calc(60% - 50px);
overflow: hidden; overflow: hidden;
margin-top: -1px; 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 { h4 {
@@ -114,11 +280,18 @@ ion-slides {
margin: 0px; margin: 0px;
line-height: 1.5; line-height: 1.5;
font-weight: 500; 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; font-size: 0.9rem;
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;
@@ -127,6 +300,7 @@ ion-slides {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
color: var(--light-grey); color: var(--light-grey);
overflow: hidden; overflow: hidden;
transition: opacity 0.1s;
} }


.action-buttons { .action-buttons {
@@ -136,16 +310,31 @@ ion-slides {
width: 100%; width: 100%;
height: 50px; height: 50px;
margin-top: -1px; 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 { .shortcuts {
display: flex; display: flex;
align-items: stretch;
align-items: center;
height: 100%; height: 100%;


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

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


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


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

span { span {
vertical-align: middle; vertical-align: middle;
color: var(--light-grey); 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 查看文件

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


slideOpts = { }; slideOpts = { };


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


@@ -34,7 +37,14 @@ export class HomePage implements OnInit {
id: 1, 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', 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', 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', type: 'VIDEO',
likes: 10, likes: 10,
isLiked: false, isLiked: false,
@@ -43,16 +53,18 @@ export class HomePage implements OnInit {
user: 'kxipFan', user: 'kxipFan',
comment: 'Yay!', comment: 'Yay!',
likes: 2, likes: 2,
isLiked: true,
}, { }, {
user: 'SehwagFan', user: 'SehwagFan',
comment: 'finally!', comment: 'finally!',
likes: 5, likes: 5,
isLiked: false,
}] }]
}, { }, {
id: 2, id: 2,
image: 'https://www.ak4tsay1.com/wp-content/uploads/2020/02/Kings-XI-Punjab-KXIP-Strengths-and-Weakness-for-IPL-2020-800x445.jpg', 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', 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', type: 'ARTICLE',
isLiked: false, isLiked: false,
isBookmarked: false, isBookmarked: false,
@@ -65,8 +77,45 @@ export class HomePage implements OnInit {
spaceBetween: 30, spaceBetween: 30,
slidesOffsetBefore: 30, slidesOffsetBefore: 30,
slidesOffsetAfter: 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 查看文件

@@ -32,4 +32,21 @@
outline: none; outline: none;
text-decoration: none; text-decoration: none;
letter-spacing: 0.5px; 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%;
}
} }

正在加载...
取消
保存