Travis build: 49
This commit is contained in:
124
README.md
124
README.md
@ -95,6 +95,7 @@ import ReactDOM from 'react-dom';
|
|||||||
* [`FileDrop`](#filedrop)
|
* [`FileDrop`](#filedrop)
|
||||||
* [`Mailto`](#mailto)
|
* [`Mailto`](#mailto)
|
||||||
* [`Modal`](#modal)
|
* [`Modal`](#modal)
|
||||||
|
* [`RippleButton`](#ripplebutton)
|
||||||
* [`StarRating`](#starrating)
|
* [`StarRating`](#starrating)
|
||||||
* [`Tabs`](#tabs)
|
* [`Tabs`](#tabs)
|
||||||
* [`Ticker`](#ticker)
|
* [`Ticker`](#ticker)
|
||||||
@ -1629,6 +1630,129 @@ ReactDOM.render(<App />, document.getElementById('root'));
|
|||||||
|
|
||||||
<br>[⬆ Back to top](#contents)
|
<br>[⬆ 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 `<button>` with one or two `<span>` 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 (
|
||||||
|
<button
|
||||||
|
className="ripple-button"
|
||||||
|
onClick={e => {
|
||||||
|
var rect = e.target.getBoundingClientRect();
|
||||||
|
var x = e.clientX - rect.left;
|
||||||
|
var y = e.clientY - rect.top;
|
||||||
|
setCoords({ x, y });
|
||||||
|
onClick && onClick(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isRippling ? (
|
||||||
|
<span
|
||||||
|
className="ripple"
|
||||||
|
style={{
|
||||||
|
left: coords.x + 10,
|
||||||
|
top: coords.y
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
<span className="content">{children}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Examples</summary>
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
ReactDOM.render(
|
||||||
|
<RippleButton onClick={e => console.log(e)}>Click me</RippleButton>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<br>[⬆ Back to top](#contents)
|
||||||
|
|
||||||
### StarRating
|
### StarRating
|
||||||
|
|
||||||
Renders a star rating component.
|
Renders a star rating component.
|
||||||
|
|||||||
@ -268,6 +268,23 @@
|
|||||||
"hash": "b9d1d5a6b61d2ab8e73943da1dcf86bfa872821c9584715a2cee303a052334ea"
|
"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 `<button>` with one or two `<span>` 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",
|
"id": "Select",
|
||||||
"type": "snippetListing",
|
"type": "snippetListing",
|
||||||
|
|||||||
@ -364,6 +364,29 @@
|
|||||||
"hash": "b9d1d5a6b61d2ab8e73943da1dcf86bfa872821c9584715a2cee303a052334ea"
|
"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 `<button>` with one or two `<span>` 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 <button\n className=\"ripple-button\"\n onClick={e => {\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 <span\n className=\"ripple\"\n style={{\n left: coords.x + 10,\n top: coords.y\n }}\n />\n ) : (\n \"\"\n )}\n <span className=\"content\">{children}</span>\n </button>\n );\n}",
|
||||||
|
"example": "ReactDOM.render(\n <RippleButton onClick={e => console.log(e)}>Click me</RippleButton>,\n document.getElementById('root')\n);"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"visual",
|
||||||
|
"state",
|
||||||
|
"effect",
|
||||||
|
"intermediate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hash": "95d8e2f6113d2d38c90c3f6d0f765cc48cbc85a14cc77613b0c9b09156684116"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Select",
|
"id": "Select",
|
||||||
"title": "Select",
|
"title": "Select",
|
||||||
|
|||||||
Reference in New Issue
Block a user