ソースを参照

Implement reply bubbles and add hover opacity effect to post footer

sbkwgh 8 年 前
コミット
b15cbfb8fb
2 ファイル変更93 行追加29 行削除
  1. 42 18
      src/components/PostReply.vue
  2. 51 11
      src/components/routes/Thread.vue

+ 42 - 18
src/components/PostReply.vue

@@ -1,5 +1,10 @@
 <template>
-	<div class='post_reply' @mouseenter='setState(true)' @mouseleave='setState(false)'>
+	<div
+		class='post_reply'
+		@mouseenter='setState(true)'
+		@mouseleave='setState(false)'
+		:class="{ 'post_reply--expanded': expanded }"
+	>
 		<div
 			class='post_reply__post'
 			:class="{
@@ -7,17 +12,24 @@
 				'post_reply__post--pointer_events': pointerEvents,
 			}"
 		>
-			<div class='post_reply__date'>{{post.createdAt | formatDate('date|time', ' - ')}}</div>
+			<div style='margin-top: -0.25rem;'>
+				<div class='post_reply__username'>{{post.User.username}}</div>
+				<div class='post_reply__date'>{{post.createdAt | formatDate('date|time', ' - ')}}</div>
+			</div>
 			<div class='post_reply__content' v-html='post.content'></div>
 		</div>
 		<div
 			class='post_reply__display'
 			:class="{
-				'post_reply__display--hover': show,
+				'post_reply__display--hover': show
 			}"
 		>
-			<div class='post_reply__letter' :style='{"background-color": post.User.color}'>{{post.User.username[0]}}</div>
-			<div class='post_reply__username'>{{post.User.username}}</div>
+			<div
+				class='post_reply__letter'
+				:style='{"background-color": post.User.color}'
+			>
+				{{post.User.username[0]}}
+			</div>
 		</div>
 	</div>
 </template>
@@ -25,7 +37,7 @@
 <script>
 	export default {
 		name: 'PostReply',
-		props: ['post'],
+		props: ['post', 'expanded'],
 		data () {
 			return {
 				show: false,
@@ -55,11 +67,32 @@
 
 	.post_reply {
 		position: relative;
+		transition: all 0.2s;
+		margin-left: -0.4rem;
 
-		@at-root #{&}__date {
+		&:first-child {
+			margin-left: 0rem;
+		}
+
+		@at-root #{&}--expanded {
+			margin: 0 0.125rem;
+
+			&:first-child {
+				margin-left: 0rem;
+			}
+		}
+
+
+		@at-root #{&}__date  {
+			display: inline-block;
 			color: $color__gray--darkest;
 			font-size: 0.8rem;
 		}
+		@at-root #{&}__username {
+			display: inline-block;
+			font-size: 0.9rem;
+			color: #000;
+		}
 
 		@at-root #{&}__post {
 			opacity: 0;
@@ -101,16 +134,11 @@
 		@at-root #{&}__display {
 			display: inline-flex;
 			align-items: baseline;
-			border: thin solid $color__darkgray--primary;
-			padding: 0.25rem 0.375rem;
+			border: 0.125rem solid $color__gray--darkest;
 			justify-content: center;
-			margin: 0 0.25rem;
 			position: relative;
 			border-radius: 1rem;
-
 			cursor: pointer;
-			transition: background-color 0.2s;
-			transition-delay: 0.1s;
 
 			@at-root #{&}--hover {
 				background-color: $color__lightgray--primary;
@@ -127,15 +155,11 @@
 			height: 1.25rem;
 			width: 1.25rem;
 			line-height: 1.25rem;
-			@include text($font--role-emphasis, 0.85rem)
+			@include text($font--role-emphasis, 0.9rem)
 			text-align: center;
 			border-radius: 100%;
 			background-color: $color__gray--darkest;
 			color: #fff;
-			margin-right: 0.25rem;
-		}
-		@at-root #{&}__username {
-			font-size: 0.85rem;
 		}
 	}
 </style>

+ 51 - 11
src/components/routes/Thread.vue

@@ -24,7 +24,12 @@
 		>
 		</input-editor>
 		<div class='posts'>
-			<div class='post' v-for='post in posts'>
+			<div
+				class='post'
+				v-for='(post, index) in posts'
+				@mouseenter='setPostFooterState(index, true)'
+				@mouseleave='setPostFooterState(index, false)'
+			>
 				<div class='post__meta_data'>
 					<div class='post__avatar' :style='{"background-color": post.User.color}'>{{post.User.username[0]}}</div>
 					<div class='post__user'>{{post.User.username}}</div>
@@ -33,12 +38,19 @@
 					<div class='post__date'>{{post.createdAt | formatDate('time|date', ', ')}}</div>
 				</div>
 				<div class='post__content' v-html='post.content'></div>
-				<div class='post__footer'>
-					<div class='post__footer_group'>
-						Replies:
-						<post-reply v-for='reply in post.Replies' :post='reply'></post-reply>
+				<div class='post__footer' :class='{ "post__footer--show": postIndexHover === index }'>
+					<div
+						class='post__footer_group'
+						:class='{ "post__footer_group--replies": post.Replies.length }'
+					>
+						<post-reply
+							v-for='reply in post.Replies'
+							:post='reply'
+							:expanded='postIndexHover === index'
+						></post-reply>
 					</div>
-					<div class='post__footer_group'>
+					<div
+						class='post__footer_group'>
 						<div class='post__action post__share'>Share</div>
 						<div
 							class='post__action post__reply'
@@ -68,7 +80,10 @@
 			PostReply
 		},
 		data () {
-			return { headerTitle: false }
+			return {
+				headerTitle: false,
+				postIndexHover: null
+			}
 		},
 		computed: {
 			thread () {
@@ -117,6 +132,13 @@
 			},
 			addPost () {
 				this.$store.dispatch('addPostAsync', this);
+			},
+			setPostFooterState (index, state) {
+				if(state) {
+					this.postIndexHover = index
+				} else {
+					this.postIndexHover = null
+				}
 			}
 		},
 		created () {
@@ -230,23 +252,41 @@
 			display: flex;
 			align-items: baseline;
 			justify-content: space-between;
+			opacity: 0.75;
+			transition: opacity 0.2s;
+
+			@at-root #{&}--show {
+				opacity: 1;
+				transition: opacity 0.2s;
+			}
 
 			@at-root #{&}_group {
 				align-items: baseline;
 				display: inline-flex;
+				position: relative;
+
+
+				@at-root #{&}--replies {
+					&::before {
+						content: 'Replies:';
+						bottom: 0.25rem;
+						left: -3.75rem;
+						font-size: 0.9rem;
+						position: absolute;	
+						color: $color__darkgray--primary;
+						transition: opacity 0.2s, bottom 0.2s;
+					}
+				}
 			}
 		}
 		@at-root #{&}__action {
-			color: $color__gray--darkest;
+			color: $color__darkgray--primary;
 			cursor: pointer;
 			margin-right: 0.75rem;
 
 			transition: all 0.2s;
 
 			&:hover {
-				color: $color__darkgray--primary;
-			}
-			&:active {
 				color: $color__darkgray--darkest;
 			}
 		}