In my latest project, I tackled an engaging challenge: building a dynamic image gallery in React that supports drag-and-drop functionality, image uploads, and image selection. Here's a rundown of what I did, the technical challenges I faced, and how I overcame them.
🎯 Project Goal
To create a user-friendly gallery where users can:
- Upload multiple images at once.
- Select and delete specific images.
- Drag and rearrange images dynamically.
Provide a responsive layout that adapts across various screen sizes.
đź› Technologies UsedReact for building the user interface.
TypeScript for type safety and improved development experience.
Tailwind CSS for rapid styling.
HTML5 Drag-and-Drop API for implementing intuitive drag-and-drop functionality.
đź’» Code Overview
Here's a breakdown of some of the core components and functionality that make up this gallery:
- Image Uploading I used a simple element to allow users to upload multiple images simultaneously. When images are uploaded, they are previewed in the gallery by generating a URL using URL.createObjectURL(file). The uploaded images are stored in the component state, making it easy to manage and render them dynamically.
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const newImages = Array.from(event.target.files).map((file, index) => ({
id: images.length + index + 1,
url: URL.createObjectURL(file),
selected: false,
}));
setImages((prev) => [...prev, ...newImages]);
}
};
- Selecting and Deleting Images Each image in the gallery has a checkbox that allows users to select it. The selected images can be deleted in bulk with a simple click. The state management for this is straightforward, with a selected property for each image to track its selection status.
const toggleSelection = (id: number) => {
setImages((prevImages) => {
const updatedImages = prevImages.map((img) =>
img.id === id ? { ...img, selected: !img.selected } : img
);
const newSelectedCount = updatedImages.filter(
(img) => img.selected
).length;
setSelectedCount(newSelectedCount);
return updatedImages;
});
};
- Drag-and-Drop Sorting Using the HTML5 Drag-and-Drop API, I implemented a simple way to rearrange images by dragging and dropping them. This makes the gallery interactive and fun to use.
const handleDragStart = (index: number) => {
setDraggedIndex(index);
};
const handleDrop = (e: React.DragEvent<HTMLDivElement>, index: number) => {
e.preventDefault();
if (draggedIndex !== null && draggedIndex !== index) {
const updatedImages = [...images];
const [movedImage] = updatedImages.splice(draggedIndex, 1);
updatedImages.splice(index, 0, movedImage);
setImages(updatedImages);
setDraggedIndex(index);
}
};
- Responsive Layout with Tailwind CSS I utilized Tailwind CSS to create a responsive grid layout for the gallery. The images adjust their sizes dynamically based on the screen size, ensuring a seamless experience across all devices.
<div className='grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-2 max-h-[500px] overflow-y-auto'>
{/* Image Items Here */}
</div>
🎨 User Experience and Design
To enhance the user experience:
- I added an overlay that appears when hovering over images, showing the checkbox for selection.
- The layout adapts to screen size changes, offering a clean, organized look on any device.
- An "Add Images" button is always visible, enabling easy uploads without disrupting the current view.
đź“ť Key Takeaways
- State Management: Efficiently managing component state with React hooks was crucial for handling image uploads, selections, and deletions.
- Drag-and-Drop: Leveraging the native HTML5 API made implementing drag-and-drop relatively straightforward without additional dependencies.
- User Interface: Tailwind CSS proved to be an invaluable tool for quickly creating a responsive and visually appealing design.
- File Handling: Previewing images before uploading by using URL.createObjectURL is a handy trick for a better user experience
🚀 Next Steps
I plan to enhance the gallery by:
- Adding a lightbox effect to view images in larger sizes.
- Integrating a backend to save uploaded images permanently.
- Adding filters and sorting options to manage large image collections easily.
📸 Demo & Code
If you're interested in the complete code, check out my GitHub repository here. Feel free to clone, fork, and play around with it!
Live
đź’¬ Feedback
I’d love to hear your thoughts! What do you think of this image gallery? What features would you like to see added? Feel free to leave a comment or connect with me on LinkedIn!
Thanks for reading, and happy coding! 🎉