Skip to content

Commit

Permalink
Merge pull request reactplay#466 from ammaaraslam/main
Browse files Browse the repository at this point in the history
Added New Play - React Gradients
  • Loading branch information
koustov committed Aug 10, 2022
2 parents a80a156 + 631cb9a commit 10ae2fc
Show file tree
Hide file tree
Showing 6 changed files with 307 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-helmet": "^6.1.0",
"react-hot-toast": "^2.3.0",
"react-icons": "^4.3.1",
"react-loader-spinner": "^5.1.5",
"react-organizational-chart": "^2.1.1",
Expand All @@ -33,8 +34,8 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"react-shimmer-effect": "^1.0.9",
"react-twitter-widgets": "^1.11.0",
"react-simple-maps": "^2.3.0",
"react-twitter-widgets": "^1.11.0",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"reselect": "^4.1.5",
Expand Down
93 changes: 93 additions & 0 deletions src/plays/react-gradients/GradientComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useState } from "react";
import { SiTailwindcss, SiCss3 } from "react-icons/si";
import { BsFillTriangleFill } from "react-icons/bs";
import toast from "react-hot-toast";
import { debounce } from "lodash";

const GradientComponent = ({ index, name, css, tailwind, colors }) => {
// Function to copy tailwind,css, color to clipboard.This function takes in 2 arguments. One is the text to be copied and the other is the message for the toast.
// Note:- Initially, there were three functions that executed this task. Later, combined those functions into just one function(the below one) for better practice and efficiency.
const copyCode = async (codeToCopy, message) => {
await navigator.clipboard.writeText(codeToCopy);
toast(`Copied ${message}`, {
icon: "📋",
style: {
backgroundColor: "#010326",
color: "#00f2fe",
},
});
};

return (
// Gradient Component
<div
key={index}
className="group relative h-72 w-[22.5rem] rounded-2xl transition-all duration-150 md:hover:scale-105 border-[6px] border-[#010326]"
style={{ background: css }}
>
{/* component containing buttons to copy code, colors of the gradient */}
<div className="absolute md:group-hover:flex md:hidden flex right-0 top-0 w-fit rounded-lg rounded-tl-none rounded-br-none bg-[#010326] transition-all duration-200 py-1 px-2 justify-center items-center border-2 border-[#010326]">
<GradientCopyButton
handleOnClick={() => copyCode(tailwind, "TailwindCSS")}
tooltipText="Copy TailwindCSS"
>
<SiTailwindcss />
</GradientCopyButton>
<GradientCopyButton
handleOnClick={() => copyCode(css, "CSS")}
tooltipText="Copy CSS"
>
<SiCss3 />
</GradientCopyButton>
{colors.map((color) => (
<GradientCopyButton
handleOnClick={() => copyCode(color, "Color")}
tooltipText="Copy Color"
>
<span className="text-sm uppercase font-semibold">{color}</span>
</GradientCopyButton>
))}
</div>

{/* Name of the gradient. Note:- Hoping to add a like button to this same component in the future with justify-between to evenly space the Name on the left and the like button on the right.*/}
<div class="absolute bottom-0 w-full rounded-b-lg bg-[#010326] py-4 px-6 text-xl font-bold text-white">
{name}
</div>
</div>
);
};

export default GradientComponent;

// This component is the button for copying the codes, color. Made it a separate component because it used several times and for easy customization.
const GradientCopyButton = ({ children, handleOnClick, tooltipText }) => {
// state variables for setting hover state of button.
const [isHovered, setIsHovered] = useState(false);

// onMouseEnter function that passes the event handler into lodash's debounce function to add a delay of 700s and sets setIsHovered to true.
const handleOnMouseEnter = debounce(() => setIsHovered(true), 700);

// onMouseLeave function that sets setIsHovered to false and calls the handleOnMouseEnter.cancel() to cancel the calling of the handleOnMouseEnter function.
const handleOnMouesLeave = () => {
setIsHovered(false);
handleOnMouseEnter.cancel();
};

return (
<button
className="flex p-2 text-gray-300 justify-center hover:text-white hover:bg-cyan-700 text-xl hover:bg-opacity-50 rounded-full transition-all duration-200"
onClick={handleOnClick}
onMouseEnter={handleOnMouseEnter}
onMouseLeave={handleOnMouesLeave}
>
{children}
{/* Logic that displays a tooltip when hovered. If state variable isHovered is true it is displayed, else it does not. */}
{isHovered && (
<p className="absolute inline-flex justify-center z-50 mt-10 w-fit p-2 text-xs bg-cyan-700 rounded-xl">
<BsFillTriangleFill className="absolute -mt-3 text-cyan-700" />
{tooltipText}
</p>
)}
</button>
);
};
63 changes: 63 additions & 0 deletions src/plays/react-gradients/ReactGradients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import PlayHeader from "common/playlists/PlayHeader";
import GradientComponent from "./GradientComponent";
import gradients from "./gradients.json";
import { IoColorPaletteSharp, IoAddSharp } from "react-icons/io5";
import { Toaster } from "react-hot-toast";

// WARNING: Do not change the entry componenet name
function ReactGradients(props) {
// Your Code Start below.

return (
<>
<div className="play-details">
<PlayHeader play={props} />
<div className="play-details-body">
{/* Header/Intro of play */}
<div className="w-full h-fit py-11 px-7 text-center">
<span className="font-bold md:text-4xl text-3xl w-full text-black inline-flex justify-center items-center">
React
<IoColorPaletteSharp
className="text-[#00f2fe] mt-auto mb-auto"
size={50}
/>
Gradients
</span>
<p className="mt-2 font-semibold md:text-xl text-lg w-full text-gray-700">
A collection of beautiful gradients that you can copy to easily
use in your application.
</p>
</div>

{/* Grid layout of all gradients */}
<div className="grid py-2 md:px-6 px-4 lg:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-8 place-items-center">
{gradients.map((gradient, index) => (
<GradientComponent
index={index}
name={gradient.name}
css={gradient.css}
tailwind={gradient.tailwind}
colors={gradient.colors}
/>
))}
</div>

{/* Button to add new gradient, Note:- Currently it is an <a> tag that redirects to README.md of the play. Hoping to convert it to a <button> element that opens up a modal containing a form to easily add a gradient. */}
<a
href="/reactplay/react-play/src/plays/react-gradients#contributing"
target="_blank"
rel="noreferrer"
className="fixed bottom-16 md:right-9 right-7 w-fit p-4 text-white bg-[#00f2fe] rounded-full font-semibold text-xl inline-flex justify-center items-center border-2 border-[#00f2fe] hover:bg-white hover:text-[#00f2fe] transition-all duration-200"
>
<IoAddSharp size={32} />{" "}
<span className="md:flex hidden ml-2">Add a Gradient</span>
</a>
{/* react-hot-toast component to display a message when code/color is copied */}
<Toaster position="bottom-left" reverseOrder={false} />
</div>
</div>
</>
);
}

export default ReactGradients;
75 changes: 75 additions & 0 deletions src/plays/react-gradients/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# React Gradients

React Gradients is list of beautiful gradients which you can easily use for your application by copying the CSS/TailwindCSS code for the desired gradient. You can also copy each color that has been used in the gradient.

## Play Demographic

- Language: js
- Level: Intermediate

## Creator Information

- User: ammaaraslam
- Gihub Link: https://github.com/ammaaraslam

## Implementation Details

The implementation of the play is fairly simple.
- Firstly it consumes data *(list of gradients and its details)* from a `json` file called `gradients.json`.
- Then it uses the `.map()` function to loop through this data and get each object *(gradient)*.
- Each object/gradient has the following properties:
- `name` - The Name of the gradient
- `tailwind` - The TailwindCSS code for the gradient.
- `css` - The CSS code for the gradient.
- `colors` - A list of colors used in the gradient.
- The properties of each gradient is passed to the separate component named `GradientComponent` in the `GradientComponent.js` file to be styled and displayed.
- In the `GradientComponent` component, you will find the following function:
- `copyCode` - This function is used to copy the tailwind, css, color of a gradient to the clipboard. This function **takes in 2 arguments**.
1. `codeToCopy` - The text that needs to be copied.
2. `message` - The message to be displayed in the toast. *(If user clicked to copy the TailwindCSS code, the message argument is "TailwindCSS". Then the toast says "Copied TailwindCSS")*
- >**Note:-** Initially, there were three different functions(`copyTailwind`, `copyCSS`, `copyColor`) to copy. Later combined these functions into one, the `copyCode` function for better practice and efficiency.
- Also in the `GradientComponent` component, you will find a `GradientCopyButton` component. This is a button component for copying the different TailwindCSS, CSS and color codes. It also displays a tooltip on hover. This tooltip is achieved by using react useState hook, `debounce` function of `lodash` to set delay on hover and onMouseEnter,onMouseLeave events to set the state of a state variable. Then the tooltip is conditionally displayed using that state variable.
- And finally, the play uses `react-hot-toast` *(a notification library for react)* to display a message after user has copied.

## Contributing

First of all thanks for wanting to contribute! To start contributing to this play, please go through the [Contribution guidelines of ReactPlay](https://github.com/reactplay/react-play/blob/main/CONTRIBUTING.md).

### Adding a new gradient

Currently to add a new gradient, you'll have to create a new `json` object in the `gradients.json` file. To do so, please follow the below steps.
- In the `gradients.json` file, add a new gradient of choice using the following syntax:
```json
{
"name": "Name of the Gradient",
"css": "CSS code for the gradient.",
"tailwind": "TailwindCSS code for the gradient",
"colors": ["A list containing all the colors used in the gradient"]
},
```
**Example**:
```json
{
"name": "Flamingo",
"css": "linear-gradient(to right, #f472b6, #db2777)",
"tailwind": "bg-gradient-to-r from-pink-400 to-pink-600",
"colors": ["#f472b6", "#db2777"]
},
```
- Then create a Pull Request referencing this play.
> **Note:-** Please make sure to add all your colors in the form of HEX. Please use [this converter](https://www.w3schools.com/colors/colors_converter.asp) if you have used any other format.

>**Also Note:-** In the future, I'm hoping to add a feature where you are able to add a gradient easily by filling a simple form directly from the play so that you don't have to go through the trouble of doing everything manually, so stay tuned for that!

## Resources

Learn more about `react-hot-toast` -https://react-hot-toast.com/docs

Learn more about `JSON` Objects - https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON


## Thanks for your time!

Thank you so much for taking the time to read this. If you like this play, please do share about it and tag me [@itsammaar_7](https://twitter.com/itsammaar_7) and [@ReactPlayIO](https://twitter.com/ReactPlayIO). Also star the [react-play repository](https://github.com/reactplay/react-play), it gives me and all the [contributors](https://github.com/reactplay/react-play#contributors-) a boost in confidence 🤩.

**Happy Coding!!**
Binary file added src/plays/react-gradients/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions src/plays/react-gradients/gradients.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[
{
"name": "Emerald",
"css": "linear-gradient(to right, #10b981, #65a30d)",
"tailwind": "bg-gradient-to-r from-emerald-500 to-lime-600",
"colors": ["#10b981", "#65a30d"]
},
{
"name": "Horizon",
"css": "linear-gradient(#f97316, #fde047)",
"tailwind": "bg-gradient-to-b from-orange-500 to-yellow-300",
"colors": ["#f97316", "#fde047"]
},
{
"name": "Green Apple",
"css": "linear-gradient(to right, #22c55e, #15803d)",
"tailwind": "bg-gradient-to-r from-green-500 to-green-700",
"colors": ["#22c55e", "#15803d"]
},
{
"name": "Deep Blue",
"css": "linear-gradient(to right, #2563eb, #1e40af, #1e3a8a)",
"tailwind": "bg-gradient-to-r from-blue-600 via-blue-800 to-blue-900",
"colors": ["#2563eb", "#1e40af", "#1e3a8a"]
},
{
"name": "Dawn",
"css": "linear-gradient(to right, #fb7185, #fdba74)",
"tailwind": "bg-gradient-to-r from-rose-400 to-orange-300",
"colors": ["#fb7185", "#fdba74"]
},
{
"name": "Midnight",
"css": "linear-gradient(to right, #1d4ed8, #1e40af, #111827)",
"tailwind": "bg-gradient-to-r from-blue-700 via-blue-800 to-gray-900",
"colors": ["#1d4ed8", "#1e40af", "#111827"]
},
{
"name": "Coral",
"css": "linear-gradient(to right, #60a5fa, #34d399)",
"tailwind": "bg-gradient-to-r from-blue-400 to-emerald-400",
"colors": ["#60a5fa", "#34d399"]
},
{
"name": "Flamingo",
"css": "linear-gradient(to right, #f472b6, #db2777)",
"tailwind": "bg-gradient-to-r from-pink-400 to-pink-600",
"colors": ["#f472b6", "#db2777"]
},
{
"name": "Ocean",
"css": "linear-gradient(to right, #a5f3fc, #22d3ee)",
"tailwind": "bg-gradient-to-r from-cyan-200 to-cyan-400",
"colors": ["#a5f3fc", "#22d3ee"]
},
{
"name": "Metal",
"css": "conic-gradient(at right center, #c7d2fe, #475569, #c7d2fe)",
"tailwind": "bg-conic-to-r from-indigo-200 via-slate-600 to-indigo-200",
"colors": ["#c7d2fe", "#475569", "#c7d2fe"]
},
{
"name": "Green Galaxy",
"css": "radial-gradient(at left center, #06b6d4, #047857, #dbeafe)",
"tailwind": "bg-radial-at-l from-cyan-500 via-emerald-700 to-blue-100",
"colors": ["#06b6d4", "#047857", "#dbeafe"]
},
{
"name": "Pure Blue Shade",
"css": "conic-gradient(at left top, #14b8a6, #4338ca, #1f2937)",
"tailwind": "bg-conic-to-tl from-teal-500 via-indigo-700 to-gray-800",
"colors": ["#14b8a6", "#4338ca", "#1f2937"]
}
]

0 comments on commit 10ae2fc

Please sign in to comment.