Add animations for button icons

This commit is contained in:
Arnaud 2024-10-16 10:07:17 +02:00
parent 379fd1fc27
commit 65465d813d
No known key found for this signature in database
GPG Key ID: 69D6CE281FCAE663
3 changed files with 110 additions and 6 deletions

View File

@ -1,4 +1,9 @@
import { ComponentType, CSSProperties } from "react"; import {
AnimationEventHandler,
ComponentType,
CSSProperties,
useState,
} from "react";
import "./buttonIcon.css"; import "./buttonIcon.css";
import { attributes } from "../utils/attributes"; import { attributes } from "../utils/attributes";
@ -9,7 +14,10 @@ interface CustomStyleCSS extends CSSProperties {
} }
type Props = { type Props = {
Icon: ComponentType; Icon: ComponentType<{
className?: string;
onAnimationEnd?: AnimationEventHandler | undefined;
}>;
variant?: "big" | "small"; variant?: "big" | "small";
@ -33,6 +41,11 @@ type Props = {
* Apply custom classname. * Apply custom classname.
*/ */
className?: string; className?: string;
/**
* Apply an animation on click
*/
animation?: "buzz" | "bounce";
}; };
export function ButtonIcon({ export function ButtonIcon({
@ -41,19 +54,30 @@ export function ButtonIcon({
style, style,
onMouseEnter, onMouseEnter,
onMouseLeave, onMouseLeave,
className = "",
animation,
disabled = false, disabled = false,
variant = "big", variant = "big",
}: Props) { }: Props) {
const [animationClassName, setAnimationClassName] = useState("");
const onInternalClick = () => {
setAnimationClassName("buttonIcon--" + animation);
onClick?.();
};
const onAnimationEnd = () => setAnimationClassName("");
return ( return (
<button <button
className={`buttonIcon buttonIcon--${variant}`} className={`buttonIcon buttonIcon--${variant} ${className}`}
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
onClick={onClick} onClick={onInternalClick}
style={style} style={style}
{...attributes({ disabled: disabled, "aria-disabled": disabled })} {...attributes({ disabled: disabled, "aria-disabled": disabled })}
> >
<Icon /> <Icon className={animationClassName} onAnimationEnd={onAnimationEnd} />
</button> </button>
); );
} }

View File

@ -35,3 +35,69 @@
color: var(--codex-color-disabled); color: var(--codex-color-disabled);
cursor: not-allowed; cursor: not-allowed;
} }
.buttonIcon--buzz {
-webkit-animation-name: buzz;
animation-name: buzz;
-webkit-animation-duration: 0.45s;
animation-duration: 0.45s;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 5;
animation-iteration-count: 5;
}
@keyframes buzz {
0% {
-webkit-transform: translateX(0) rotate(0deg);
transform: translateX(0px) rotate(0deg);
}
25% {
-webkit-transform: translateX(-3px) rotate(-15deg);
transform: translateX(-3px) rotate(-15deg);
}
50% {
-webkit-transform: translateX(0) rotate(0deg);
transform: translateX(0px) rotate(0deg);
}
75% {
-webkit-transform: translateX(3px) rotate(15deg);
transform: translateX(3px) rotate(15deg);
}
100% {
-webkit-transform: translateX(0) rotate(0deg);
transform: translateX(0px) rotate(0deg);
}
}
.buttonIcon--bounce {
-webkit-animation-name: bounce;
animation-name: bounce;
-webkit-animation-duration: 0.6s;
animation-duration: 0.6s;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes bounce {
0% {
-webkit-transform: translateY(0) scale(1);
transform: translateY(0px) scale(1);
}
50% {
-webkit-transform: translateY(-10px) scale(1);
transform: translateY(-10px) scale(1);
}
100% {
-webkit-transform: translateY(0) scale(1);
transform: translateY(0px) scale(1);
}
}

View File

@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react"; import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test"; import { fn } from "@storybook/test";
import { Plus } from "lucide-react"; import { Copy, Download, Plus } from "lucide-react";
import { ButtonIcon } from "../src/components/ButtonIcon/ButtonIcon"; import { ButtonIcon } from "../src/components/ButtonIcon/ButtonIcon";
const meta = { const meta = {
@ -42,6 +42,20 @@ export const Disabled: Story = {
}, },
}; };
export const BuzzAnimation: Story = {
args: {
Icon: Copy,
animation: "buzz"
},
};
export const BounceAnimation: Story = {
args: {
Icon: Download,
animation: "bounce"
},
};
export const CustomStyle: Story = { export const CustomStyle: Story = {
args: { args: {
Icon: Plus, Icon: Plus,