Skip to content

Commit

Permalink
Add bounce animations to vote buttons and swipe actions (#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeharding authored Jul 20, 2023
1 parent 7243b23 commit 16fe490
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@
"lemmy-js-client": "0.18.0",
"lodash": "^4.17.21",
"mdast-util-gfm-autolink-literal-lemmy": "^1.0.3",
"photoswipe": "^5.3.8",
"mdast-util-gfm-strikethrough": "^1.0.3",
"mdast-util-gfm-table": "^1.0.7",
"micromark": "^3.0.0",
"micromark-extension-gfm-strikethrough": "^1.0.0",
"micromark-extension-gfm-table": "^1.0.0",
"micromark-util-combine-extensions": "^1.0.0",
"photoswipe": "^5.3.8",
"prettier": "^2.8.8",
"pwa-asset-generator": "^6.3.1",
"react": "^18.2.0",
Expand All @@ -81,6 +81,7 @@
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"react-textarea-autosize": "^8.5.2",
"react-transition-state": "^2.1.1",
"react-virtuoso": "^4.3.11",
"remark-gfm": "^3.0.1",
"terser": "^5.18.1",
Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 21 additions & 2 deletions src/features/post/shared/VoteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import styled from "@emotion/styled";
import { IonIcon, useIonToast } from "@ionic/react";
import { useContext } from "react";
import { useContext, useEffect } from "react";
import { useAppDispatch, useAppSelector } from "../../../store";
import { voteOnPost } from "../postSlice";
import { css } from "@emotion/react";
import { arrowDownSharp, arrowUpSharp } from "ionicons/icons";
import { ActionButton } from "../actions/ActionButton";
import { voteError } from "../../../helpers/toastMessages";
import { PageContext } from "../../auth/PageContext";
import { bounceAnimationOnTransition, bounceMs } from "../../shared/animations";
import { useTransition } from "react-transition-state";

export const Item = styled(ActionButton, {
shouldForwardProp: (prop) => prop !== "on" && prop !== "activeColor",
})<{
on?: boolean;
activeColor?: string;
}>`
${bounceAnimationOnTransition}
${({ on, activeColor }) =>
on
? css`
Expand All @@ -37,6 +41,10 @@ export function VoteButton({ type, postId }: VoteButtonProps) {
const postVotesById = useAppSelector((state) => state.post.postVotesById);
const myVote = postVotesById[postId];

const [state, toggle] = useTransition({
timeout: bounceMs,
});

const icon = (() => {
switch (type) {
case "down":
Expand Down Expand Up @@ -64,14 +72,25 @@ export function VoteButton({ type, postId }: VoteButtonProps) {
}
})();

const on = myVote === selectedVote;

useEffect(() => {
if (!on) toggle(false);
}, [on, toggle]);

return (
<Item
on={myVote === selectedVote}
on={on}
className={state.status}
onClick={async (e) => {
e.stopPropagation();

if (presentLoginIfNeeded()) return;

if (!on) {
toggle(true);
}

try {
await dispatch(
voteOnPost(postId, myVote === selectedVote ? 0 : selectedVote)
Expand Down
25 changes: 25 additions & 0 deletions src/features/shared/animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { css, keyframes } from "@emotion/react";

const bounce = keyframes`
0% {
transform: scale(1);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
`;

export const bounceMs = 175;

export const bounceAnimation = css`
animation: ${bounce} ${bounceMs}ms linear;
`;

export const bounceAnimationOnTransition = css`
&.entering {
${bounceAnimation}
}
`;
3 changes: 3 additions & 0 deletions src/features/shared/sliding/SlidingItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IonItemSliding,
} from "@ionic/react";
import React, { useMemo, useRef, useState } from "react";
import { bounceAnimation } from "../animations";

const StyledIonItemSliding = styled(IonItemSliding)`
--ion-item-border-color: transparent;
Expand Down Expand Up @@ -39,6 +40,8 @@ const OptionContainer = styled.div<{ active: boolean }>`
active &&
css`
opacity: 1;
${bounceAnimation}
`}
`;

Expand Down

0 comments on commit 16fe490

Please sign in to comment.