mirror of
https://github.com/remvze/moodist.git
synced 2025-10-26 08:12:26 -04:00
refactor: seperate motion variants
This commit is contained in:
parent
b849b3aecd
commit
7fce9e1dff
@ -16,6 +16,7 @@ import { AnimatePresence, motion } from 'framer-motion';
|
|||||||
|
|
||||||
import { useSoundStore } from '@/store';
|
import { useSoundStore } from '@/store';
|
||||||
import { cn } from '@/helpers/styles';
|
import { cn } from '@/helpers/styles';
|
||||||
|
import { fade, mix, slideX } from '@/lib/motion';
|
||||||
|
|
||||||
import styles from './unselect.module.css';
|
import styles from './unselect.module.css';
|
||||||
|
|
||||||
@ -47,14 +48,17 @@ export function UnselectButton() {
|
|||||||
const hasHistory = useSoundStore(state => !!state.history);
|
const hasHistory = useSoundStore(state => !!state.history);
|
||||||
const unselectAll = useSoundStore(state => state.unselectAll);
|
const unselectAll = useSoundStore(state => state.unselectAll);
|
||||||
|
|
||||||
|
const variants = mix(fade(), slideX(20));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
{(!noSelected || hasHistory) && (
|
{(!noSelected || hasHistory) && (
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate="show"
|
||||||
exit={{ opacity: 0, x: 20 }}
|
exit="hidden"
|
||||||
initial={{ opacity: 0, x: 20 }}
|
initial="hidden"
|
||||||
|
variants={variants}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
disabled={noSelected && !hasHistory}
|
disabled={noSelected && !hasHistory}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
import { Sounds } from '@/components/sounds';
|
import { Sounds } from '@/components/sounds';
|
||||||
|
import { fade } from '@/lib/motion';
|
||||||
|
|
||||||
import styles from './category.module.css';
|
import styles from './category.module.css';
|
||||||
|
|
||||||
@ -24,12 +25,15 @@ export function Category({
|
|||||||
sounds,
|
sounds,
|
||||||
title,
|
title,
|
||||||
}: CategoryProps) {
|
}: CategoryProps) {
|
||||||
|
const variants = fade();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{ opacity: 1 }}
|
animate="show"
|
||||||
className={styles.category}
|
className={styles.category}
|
||||||
initial={{ opacity: 0 }}
|
initial="hidden"
|
||||||
layout="position"
|
layout="position"
|
||||||
|
variants={variants}
|
||||||
>
|
>
|
||||||
<div className={styles.iconContainer}>
|
<div className={styles.iconContainer}>
|
||||||
<div className={styles.tail} />
|
<div className={styles.tail} />
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { AnimatePresence, motion } from 'framer-motion';
|
|||||||
|
|
||||||
import { useFavoriteStore } from '@/store/favorite';
|
import { useFavoriteStore } from '@/store/favorite';
|
||||||
import { cn } from '@/helpers/styles';
|
import { cn } from '@/helpers/styles';
|
||||||
|
import { fade } from '@/lib/motion';
|
||||||
|
|
||||||
import styles from './like.module.css';
|
import styles from './like.module.css';
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ export function Like({ id }: LikeProps) {
|
|||||||
const isFavorite = useFavoriteStore(state => state.favorites.includes(id));
|
const isFavorite = useFavoriteStore(state => state.favorites.includes(id));
|
||||||
const toggleFavorite = useFavoriteStore(state => state.toggleFavorite);
|
const toggleFavorite = useFavoriteStore(state => state.toggleFavorite);
|
||||||
|
|
||||||
|
const variants = fade();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatePresence initial={false} mode="wait">
|
<AnimatePresence initial={false} mode="wait">
|
||||||
<button
|
<button
|
||||||
@ -25,10 +28,11 @@ export function Like({ id }: LikeProps) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<motion.span
|
<motion.span
|
||||||
animate={{ opacity: 1 }}
|
animate="show"
|
||||||
exit={{ opacity: 0 }}
|
exit="hidden"
|
||||||
initial={{ opacity: 0 }}
|
initial="hidden"
|
||||||
key={isFavorite ? `${id}-is-favorite` : `${id}-not-favorite`}
|
key={isFavorite ? `${id}-is-favorite` : `${id}-not-favorite`}
|
||||||
|
variants={variants}
|
||||||
>
|
>
|
||||||
{isFavorite ? <BiSolidHeart /> : <BiHeart />}
|
{isFavorite ? <BiSolidHeart /> : <BiHeart />}
|
||||||
</motion.span>
|
</motion.span>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { AnimatePresence, motion } from 'framer-motion';
|
|||||||
import { Sound } from '@/components/sound';
|
import { Sound } from '@/components/sound';
|
||||||
import { useLocalStorage } from '@/hooks/use-local-storage';
|
import { useLocalStorage } from '@/hooks/use-local-storage';
|
||||||
import { cn } from '@/helpers/styles';
|
import { cn } from '@/helpers/styles';
|
||||||
|
import { fade, scale, mix } from '@/lib/motion';
|
||||||
|
|
||||||
import styles from './sounds.module.css';
|
import styles from './sounds.module.css';
|
||||||
|
|
||||||
@ -45,6 +46,8 @@ export function Sounds({ functional, id, sounds }: SoundsProps) {
|
|||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const variants = mix(fade(), scale(0.85));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.sounds}>
|
<div className={styles.sounds}>
|
||||||
@ -68,11 +71,12 @@ export function Sounds({ functional, id, sounds }: SoundsProps) {
|
|||||||
{sounds.length > 6 && (
|
{sounds.length > 6 && (
|
||||||
<AnimatePresence initial={false} mode="wait">
|
<AnimatePresence initial={false} mode="wait">
|
||||||
<motion.button
|
<motion.button
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate="show"
|
||||||
exit={{ opacity: 0, scale: 0.85 }}
|
exit="hidden"
|
||||||
initial={{ opacity: 0, scale: 0.85 }}
|
initial="hidden"
|
||||||
key={showAll ? `${id}-show-less` : `${id}-show-more`}
|
key={showAll ? `${id}-show-less` : `${id}-show-more`}
|
||||||
transition={{ duration: 0.2 }}
|
transition={{ duration: 0.2 }}
|
||||||
|
variants={variants}
|
||||||
className={cn(
|
className={cn(
|
||||||
styles.button,
|
styles.button,
|
||||||
hasHiddenSelection && !showAll && styles.active,
|
hasHiddenSelection && !showAll && styles.active,
|
||||||
|
|||||||
48
src/lib/motion.ts
Normal file
48
src/lib/motion.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
type Motion = {
|
||||||
|
hidden: {
|
||||||
|
[key: string]: number | string;
|
||||||
|
};
|
||||||
|
show: {
|
||||||
|
[key: string]: number | string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function fade(): Motion {
|
||||||
|
return {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
show: { opacity: 1 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function scale(from = 0.85, to = 1): Motion {
|
||||||
|
return {
|
||||||
|
hidden: { scale: from },
|
||||||
|
show: { scale: to },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function slideX(from = -10, to = 0): Motion {
|
||||||
|
return {
|
||||||
|
hidden: { x: from },
|
||||||
|
show: { x: to },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function slideY(from = -10, to = 0): Motion {
|
||||||
|
return {
|
||||||
|
hidden: { Y: from },
|
||||||
|
show: { Y: to },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mix(...motions: Array<Motion>): Motion {
|
||||||
|
let hidden = {};
|
||||||
|
let show = {};
|
||||||
|
|
||||||
|
motions.forEach(motion => {
|
||||||
|
if (motion.hidden) hidden = { ...hidden, ...motion.hidden };
|
||||||
|
if (motion.show) show = { ...show, ...motion.show };
|
||||||
|
});
|
||||||
|
|
||||||
|
return { hidden, show };
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user