diff --git a/README.md b/README.md
index 0196d45a8..7eb6fae14 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,7 @@ import ReactDOM from 'react-dom';
* [`FileDrop`](#filedrop)
* [`Mailto`](#mailto)
* [`Modal`](#modal)
+* [`RippleButton`](#ripplebutton)
* [`StarRating`](#starrating)
* [`Tabs`](#tabs)
* [`Ticker`](#ticker)
@@ -1629,6 +1630,129 @@ ReactDOM.render( , document.getElementById('root'));
[⬆ Back to top](#contents)
+### RippleButton
+
+### RippleButton
+
+Renders a button that animates a ripple effect when clicked.
+
+- Define some appropriate CSS styles and an animation for the ripple effect.
+- Use the `React.useState()` hook to create appropriate variables and setters for the pointer's coordinates and for the animation state of the button.
+- Use the `React.useEffect()` hook to change the state every time the `coords` state variable changes, starting the animation.
+- Use `setTimeout()` in the previous hook to clear the animation after it's done playing.
+- Use the `React.useEffect()` hook a second time to reset `coords` whenever the `isRippling` state variable is `false.`
+- Handle the `onClick` event by updating the `coords` state variable and calling the passed callback.
+- Finally, render a `` with one or two `` elements, setting the position of the `.ripple` element based on the `coords` state variable.
+
+```css
+.ripple-button {
+ border-radius: 4px;
+ border: none;
+ margin: 8px;
+ padding: 14px 24px;
+ background: #1976d2;
+ color: #fff;
+ overflow: hidden;
+ position: relative;
+ cursor: pointer;
+}
+
+.ripple-button > .ripple {
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ background: #63a4ff;
+ display: block;
+ content: "";
+ border-radius: 9999px;
+ opacity: 1;
+ animation: 1.2s ease 1 forwards ripple-effect;
+}
+
+@keyframes ripple-effect {
+ 0% {
+ transform: scale(1);
+ opacity: 1;
+ }
+ 50% {
+ transform: scale(10);
+ opacity: 0.375;
+ }
+ 100% {
+ transform: scale(35);
+ opacity: 0;
+ }
+}
+
+.ripple-button > .content {
+ position: relative;
+ z-index: 2;
+}
+```
+
+```jsx
+function RippleButton({ children, onClick }) {
+ const [coords, setCoords] = React.useState({ x: -1, y: -1 });
+ const [isRippling, setIsRippling] = React.useState(false);
+
+ React.useEffect(
+ () => {
+ if (coords.x !== -1 && coords.y !== -1) {
+ setIsRippling(true);
+ setTimeout(() => setIsRippling(false), 1200);
+ } else setIsRippling(false);
+ },
+ [coords]
+ );
+
+ React.useEffect(
+ () => {
+ if (!isRippling) setCoords({ x: -1, y: -1 });
+ },
+ [isRippling]
+ );
+
+ return (
+ {
+ var rect = e.target.getBoundingClientRect();
+ var x = e.clientX - rect.left;
+ var y = e.clientY - rect.top;
+ setCoords({ x, y });
+ onClick && onClick(e);
+ }}
+ >
+ {isRippling ? (
+
+ ) : (
+ ""
+ )}
+ {children}
+
+ );
+}
+```
+
+
+Examples
+
+```jsx
+ReactDOM.render(
+ console.log(e)}>Click me ,
+ document.getElementById('root')
+);
+```
+
+
+ [⬆ Back to top](#contents)
+
### StarRating
Renders a star rating component.
diff --git a/snippet_data/snippetList.json b/snippet_data/snippetList.json
index 1d4e01b52..555d19b80 100644
--- a/snippet_data/snippetList.json
+++ b/snippet_data/snippetList.json
@@ -268,6 +268,23 @@
"hash": "b9d1d5a6b61d2ab8e73943da1dcf86bfa872821c9584715a2cee303a052334ea"
}
},
+ {
+ "id": "RippleButton",
+ "type": "snippetListing",
+ "title": "RippleButton",
+ "attributes": {
+ "text": "### RippleButton\n\nRenders a button that animates a ripple effect when clicked.\n\n- Define some appropriate CSS styles and an animation for the ripple effect.\n- Use the `React.useState()` hook to create appropriate variables and setters for the pointer's coordinates and for the animation state of the button.\n- Use the `React.useEffect()` hook to change the state every time the `coords` state variable changes, starting the animation.\n- Use `setTimeout()` in the previous hook to clear the animation after it's done playing.\n- Use the `React.useEffect()` hook a second time to reset `coords` whenever the `isRippling` state variable is `false.`\n- Handle the `onClick` event by updating the `coords` state variable and calling the passed callback.\n- Finally, render a `` with one or two `` elements, setting the position of the `.ripple` element based on the `coords` state variable.\n\n",
+ "tags": [
+ "visual",
+ "state",
+ "effect",
+ "intermediate"
+ ]
+ },
+ "meta": {
+ "hash": "95d8e2f6113d2d38c90c3f6d0f765cc48cbc85a14cc77613b0c9b09156684116"
+ }
+ },
{
"id": "Select",
"type": "snippetListing",
diff --git a/snippet_data/snippets.json b/snippet_data/snippets.json
index b521e9c11..5aaaedfb7 100644
--- a/snippet_data/snippets.json
+++ b/snippet_data/snippets.json
@@ -364,6 +364,29 @@
"hash": "b9d1d5a6b61d2ab8e73943da1dcf86bfa872821c9584715a2cee303a052334ea"
}
},
+ {
+ "id": "RippleButton",
+ "title": "RippleButton",
+ "type": "snippet",
+ "attributes": {
+ "fileName": "RippleButton.md",
+ "text": "### RippleButton\n\nRenders a button that animates a ripple effect when clicked.\n\n- Define some appropriate CSS styles and an animation for the ripple effect.\n- Use the `React.useState()` hook to create appropriate variables and setters for the pointer's coordinates and for the animation state of the button.\n- Use the `React.useEffect()` hook to change the state every time the `coords` state variable changes, starting the animation.\n- Use `setTimeout()` in the previous hook to clear the animation after it's done playing.\n- Use the `React.useEffect()` hook a second time to reset `coords` whenever the `isRippling` state variable is `false.`\n- Handle the `onClick` event by updating the `coords` state variable and calling the passed callback.\n- Finally, render a `` with one or two `` elements, setting the position of the `.ripple` element based on the `coords` state variable.\n\n",
+ "codeBlocks": {
+ "style": ".ripple-button {\n border-radius: 4px;\n border: none;\n margin: 8px;\n padding: 14px 24px;\n background: #1976d2;\n color: #fff;\n overflow: hidden;\n position: relative;\n cursor: pointer;\n}\n\n.ripple-button > .ripple {\n width: 20px;\n height: 20px;\n position: absolute;\n background: #63a4ff;\n display: block;\n content: \"\";\n border-radius: 9999px;\n opacity: 1;\n animation: 1.2s ease 1 forwards ripple-effect;\n}\n\n@keyframes ripple-effect {\n 0% {\n transform: scale(1);\n opacity: 1;\n }\n 50% {\n transform: scale(10);\n opacity: 0.375;\n }\n 100% {\n transform: scale(35);\n opacity: 0;\n }\n}\n\n.ripple-button > .content {\n position: relative;\n z-index: 2;\n}",
+ "code": "function RippleButton({ children, onClick }) {\n const [coords, setCoords] = React.useState({ x: -1, y: -1 });\n const [isRippling, setIsRippling] = React.useState(false);\n\n React.useEffect(\n () => {\n if (coords.x !== -1 && coords.y !== -1) {\n setIsRippling(true);\n setTimeout(() => setIsRippling(false), 1200);\n } else setIsRippling(false);\n },\n [coords]\n );\n\n React.useEffect(\n () => {\n if (!isRippling) setCoords({ x: -1, y: -1 });\n },\n [isRippling]\n );\n\n return (\n {\n var rect = e.target.getBoundingClientRect();\n var x = e.clientX - rect.left;\n var y = e.clientY - rect.top;\n setCoords({ x, y });\n onClick && onClick(e);\n }}\n >\n {isRippling ? (\n \n ) : (\n \"\"\n )}\n {children} \n \n );\n}",
+ "example": "ReactDOM.render(\n console.log(e)}>Click me ,\n document.getElementById('root')\n);"
+ },
+ "tags": [
+ "visual",
+ "state",
+ "effect",
+ "intermediate"
+ ]
+ },
+ "meta": {
+ "hash": "95d8e2f6113d2d38c90c3f6d0f765cc48cbc85a14cc77613b0c9b09156684116"
+ }
+ },
{
"id": "Select",
"title": "Select",