React Components | Gallary
Tags: react, javascript, webdev, tutorial
Published: 2023-09-06 08:00:09

Hello Everyone, today i will show, how we can create a simple Image gallary in react using tailwind CSS and make it reusable.

Let's get started...

## Updating Tailwind config file
```js
 safelist: [
    'justify-center',
    'justify-self-center',
      ...[...[1,2,3,4,5,6,7,8,9,10,11,12,14,16,20].values()].flatMap(i => [`gap-x-${i}`, `gap-y-${i}`]),
      ...[...Array(12).keys()].flatMap(i => [`grid-cols-${i+1}`]),
  ]
```
* Add this safelist property inside tailwind config, it is used to safelist tailwind classes that we want to use dynamically in our project, basically tailwind remove those classes which are not used in the project, so if you try to dynamically add a class, it won't apply the stylings as the class is not there in the stylesheet.
* So, we are safelisting "justify-center" and "justify-self-center", which we will apply dynamically, then using array and flatMap, we are safelisting gap-x and gap-y value upto 20, so we can use classes with value upto 20 only like, gap-x-20 and gap-y-20, we can't use gap-x/y-22 or above. Same we applied to the grid-cols classes which contains value from 1 to 12.

## Gallary Props
```js
const Gallary = ({
    images = [],
    position = "left",
    gridLayout = "flex",
    gridCols = 2,
    colGap = "2",
    rowGap = "2",
    hoverFilter = false,
    gallaryClassName = "",
    imageClassName = ""
}) => {
```
This code defines a functional React component named Gallary. The component takes several props as an object destructure, which allows you to customize its behavior. Here's what each prop does:

* images: An array of objects representing images to be displayed in the gallery.
* position: The positioning of the gallery (e.g., "left").
* gridLayout: The layout style for the gallery (either "flex" or a CSS grid layout).
* gridCols: The number of columns in the grid layout.
* colGap: The gap between columns in the grid.
* rowGap: The gap between rows in the grid.
* hoverFilter: A boolean flag to determine whether a hover filter effect should be applied to the images.
* gallaryClassName: Additional CSS classes for the gallery container.
* imageClassName: Additional CSS classes for the individual images.

## Creating container - 
```js
return (
  <div 
    className={`${gallaryClassName} 
      ${gridLayout === "flex" ? "flex flex-wrap" : `grid grid-cols-${gridCols}`} 
     justify-${position} gap-y-${rowGap} gap-x-${colGap}`}>
```
This part of the code returns the JSX (JavaScript XML) that represents the gallery component. It uses template literals to dynamically generate the CSS classes based on the props provided. The classes determine the layout, positioning, and styling of the gallery.

## Rendering images using map
```js
    {
        images?.map(({ imgName, imgUrl, imgWidth, imgHeight, className }, index) => {
            return (
                <div className={`relative ${gridLayout !== "flex" ? `justify-self-${position}` : ""}`} key={index}>
                    <img 
                        name={imgName} 
                        src={imgUrl} 
                        width={imgWidth} 
                        height={imgHeight} 
                        alt={imgName} 
                        className={`text-center ${imageClassName} ${hoverFilter ?  "md:grayscale md:hover:grayscale-0" : ""} ${className}`} 
                        style={{ width: imgWidth, height: imgHeight }} />
                    {
                        imgName && imgName !== "" && 
                        <p className='absolute bottom-2 right-1/2 translate-x-1/2 bg-slate-100 px-4 py-2 rounded-xl'>{imgName}</p>
                    }
                </div>
            )
        })
    }
```
This section maps through the images array and renders each image within a <div>. The properties of each image are extracted from the array and used to set the image attributes and CSS classes. Additionally, if the hoverFilter prop is true, a grayscale filter is applied to the image when hovered.

## Full Code with usage - 
```js
{/* 

PROPS -
images = [
    {
        imgName:"Image 1",
        imgUrl:"imageurl",
        imgWidth: "300px",
        imgHeight: "300px",
        className: "border-4 !rounded-full !border-red-600"
    }
    .
    .
]
position = left/center
gridLayout = flex/grid
gridCols = 1 -> 12
colGap = 1,2,3,4,5,6,7,8,9,10,11,12,14,16,20
rowGap = 1,2,3,4,5,6,7,8,9,10,11,12,14,16,20
hoverFilter = true/false
gallaryClassName = CSS/ Tailwind classes
imageClassName = CSS/ Tailwind classes


USAGE - 
<Gallary 
    images={images} 
    position="center" 
    gridLayout="grid" 
    rowGap="4" 
    colGap="6" 
    gridCols={columns} 
    gallaryClassName="p-10 bg-slate-900 pt-20" 
    imageClassName="rounded-xl border border-white" 
    hoverFilter={true} />

*/}

import React from 'react'

const Gallary = ({
    images=[],
    position="left",
    gridLayout="flex",
    gridCols=2,
    colGap="2",
    rowGap="2",
    hoverFilter=false, 
    gallaryClassName="", 
    imageClassName=""
}) => {

  return (
    <div 
       className={`${gallaryClassName} 
       ${gridLayout === "flex" ? "flex flex-wrap" : `grid grid-cols-${gridCols}`} 
      justify-${position} gap-y-${rowGap} gap-x-${colGap}`}>
        {
            images?.map(({imgName,imgUrl,imgWidth,imgHeight,className},index) => {
                return (
                    <div className={`relative ${gridLayout !== "flex" ? `justify-self-${position}` : ""}`} key={index}>
                        <img 
                            name={imgName} 
                            src={imgUrl} 
                            width={imgWidth} 
                            height={imgHeight} 
                            alt={imgName} 
                            className={`text-center ${imageClassName} ${hoverFilter ?  "md:grayscale md:hover:grayscale-0" : ""} ${className}`} 
                            style={{width:imgWidth,height:imgHeight}} />
                        {
                            imgName && imgName !== "" && 
                            <p className='absolute bottom-2 right-1/2 translate-x-1/2 bg-slate-100 px-4 py-2 rounded-xl'>{imgName}</p>
                        }
                    </div>
                )
            })
        }
    </div>
  )
}

export default Gallary
```

## Changing columns dynamically
```js
// App.js
"use client"

import { useState } from "react"
import Gallary from "./components/Gallary"
import { images } from "@/app/data"

export default function Home() {

  const [columns, setColumns] = useState(4)

  return (
    <main className='min-h-screen grid place-items-center'>
      <select className="fixed top-4 right-4 px-4 py-2 rounded-xl z-10" value={columns} onChange={(e) => setColumns(e.target.value)}>
        {
          [...Array(12).keys()].flatMap(i => [`${i + 1}`]).map(value => {
            return (
              <option value={value} key={value}>
                {value} Column
              </option>
            )
          })
        }
      </select>
      <Gallary images={images} position="center" gridLayout="grid" rowGap="4" colGap="6" gridCols={columns} gallaryClassName="p-10 bg-slate-900 pt-20" imageClassName="rounded-xl border border-white" hoverFilter={true} />
    </main>
  )
}
```
* We are using a select element and map it with an array of value from 1-12, it will set the columns state which in turn change the columns in the Gallary component as the gridCols props is dependent on columns state value

#### It's not an advance gallary component, still you can apply more things like tailwind placeholders to give values in px or percentage, apply different filters other than grayscale or destructure it in way where we can pass other elements instead of just images only. 
Feel free to give suggestions in comments to improve the component and make it more reusable and efficient.
THANK YOU FOR CHECKING THIS POST
You can contact me on -
Instagram - https://www.instagram.com/supremacism__shubh/
LinkedIn - https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email - shubhmtiwri00@gmail.com

^^You can help me with some donation at the link below Thank you👇👇 ^^
☕ --> https://www.buymeacoffee.com/waaduheck <--

Also check these posts as well
https://dev.to/shubhamtiwari909/website-components-you-should-know-25nm

https://dev.to/shubhamtiwari909/smooth-scrolling-with-js-n56

https://dev.to/shubhamtiwari909/swiperjs-3802

https://dev.to/shubhamtiwari909/custom-tabs-with-sass-and-javascript-4dej