mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
added LikeButton
This commit is contained in:
parent
af86376e79
commit
501983f615
48
packages/app/src/components/LikeButton/index.jsx
Normal file
48
packages/app/src/components/LikeButton/index.jsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from "react"
|
||||
import classnames from "classnames"
|
||||
|
||||
import "./index.less"
|
||||
|
||||
export default (props) => {
|
||||
const [liked, setLiked] = React.useState(props.defaultLiked ?? false)
|
||||
const [clicked, setCliked] = React.useState(false)
|
||||
|
||||
const handleClick = async () => {
|
||||
let to = !liked
|
||||
|
||||
setCliked(to)
|
||||
|
||||
if (typeof props.onClick === "function") {
|
||||
const result = await props.onClick(to)
|
||||
if (typeof result === "boolean") {
|
||||
to = result
|
||||
}
|
||||
}
|
||||
|
||||
setLiked(to)
|
||||
}
|
||||
|
||||
return <button
|
||||
className={classnames("likeButton", { ["clicked"]: liked })}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div
|
||||
className={classnames(
|
||||
"ripple",
|
||||
{ ["clicked"]: clicked }
|
||||
)}
|
||||
></div>
|
||||
<svg
|
||||
className={classnames(
|
||||
"heart",
|
||||
{ ["liked"]: liked },
|
||||
{ ["clicked"]: clicked },
|
||||
)}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
}
|
151
packages/app/src/components/LikeButton/index.less
Normal file
151
packages/app/src/components/LikeButton/index.less
Normal file
@ -0,0 +1,151 @@
|
||||
@color-heart : #EA442B;
|
||||
@likeAnimationDuration : .5s;
|
||||
@likeAnimationEasing : cubic-bezier(.7, 0, .3, 1);
|
||||
|
||||
.likeButton {
|
||||
display : flex;
|
||||
align-items : center;
|
||||
justify-content: center;
|
||||
|
||||
.ripple,
|
||||
.ripple:before,
|
||||
.ripple:after {
|
||||
position : relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
font-size : 40px;
|
||||
border : none;
|
||||
border-radius: 50%;
|
||||
width : 1em;
|
||||
height : 1em;
|
||||
padding : 0;
|
||||
margin : 0;
|
||||
outline : none;
|
||||
z-index : 2;
|
||||
transition : transform @likeAnimationDuration @likeAnimationEasing;
|
||||
cursor : pointer;
|
||||
|
||||
background-color: transparent;
|
||||
|
||||
&:before {
|
||||
z-index : -1;
|
||||
content : '';
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
border-radius: inherit;
|
||||
transition : inherit;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content : '';
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
border-radius: inherit;
|
||||
z-index : -1;
|
||||
}
|
||||
|
||||
.heart {
|
||||
position: relative;
|
||||
|
||||
>path {
|
||||
stroke-width: 2;
|
||||
transition : fill @likeAnimationDuration @likeAnimationEasing;
|
||||
stroke : currentColor;
|
||||
fill : transparent;
|
||||
}
|
||||
|
||||
&.liked {
|
||||
>path {
|
||||
stroke: var(--primaryColor);
|
||||
fill : var(--primaryColor);
|
||||
}
|
||||
}
|
||||
|
||||
&.clicked {
|
||||
animation: heart-bounce @likeAnimationDuration @likeAnimationEasing;
|
||||
|
||||
@keyframes heart-bounce {
|
||||
40% {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
position : absolute;
|
||||
height : 1em;
|
||||
width : 1em;
|
||||
border-radius: 50%;
|
||||
overflow : hidden;
|
||||
z-index : 1;
|
||||
|
||||
&:before {
|
||||
content : '';
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
border : .4em solid var(--primaryColor);
|
||||
border-radius: inherit;
|
||||
transform : scale(0);
|
||||
}
|
||||
|
||||
&.clicked {
|
||||
&:before {
|
||||
animation: ripple-out @likeAnimationDuration @likeAnimationEasing;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple-out {
|
||||
from {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes depress {
|
||||
|
||||
from,
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(5%) scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes depress-shadow {
|
||||
|
||||
from,
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ export { default as Navigation } from "./Navigation"
|
||||
export { default as ImageUploader } from "./ImageUploader"
|
||||
export { default as ImageViewer } from "./ImageViewer"
|
||||
|
||||
export { default as LikeButton } from "./LikeButton"
|
||||
export { default as PostCard } from "./PostCard"
|
||||
export { default as PostCreator } from "./PostCreator"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user