first post here.
I’m a new dev. I’m building this site for a client and I was hoping for some suggestions on animating the transitions when a user uses the category filter on this portfolio site.
Right now it’s just filtering and mapping the images which match the category in state.
Front Page
I’m asking here because I wanted some expert opinions on the proper way to handle this. Being new, I wasn’t sure if there were specific animation libraries seasoned devs like to use for things like this. Or what the proper way would be to handle the images fading out and disappearing, while others ease-slide to fill the space of the ones that disappear or vice versa.
Here’s the Parent component GalleryCategoryFilter
import { useState, useEffect, ReactElement } from 'react';
import galleryData from '../../data/portfolio_images.json';
import { FoundCategories, UniqueCategories, Image } from './types';
import GalleryGrid from '../GalleryGrid/GalleryGrid';
import './GalleryCategoryFilter.scss';
const formatCategoryName = (category: string): string => {
const formatted = category
// Insert space before capital letters, g indicates a "global" search, so all instances are replaced.
// All incoming data should be camelCase, so this should work.
.replace(/([A-Z])/g, ' $1').trim()
return formatted;
};
const fetchAndFormatCategories = (): FoundCategories => {
const uniqueCategories: UniqueCategories = new Map();
uniqueCategories.set('all', 'All');
galleryData.forEach((image: Image) => {
const formattedCategory = formatCategoryName(image.category);
if (!uniqueCategories.has(image.category)) {
uniqueCategories.set(image.category, formattedCategory);
}
});
const foundCategories: FoundCategories = Array.from(uniqueCategories, ([key, value]) => ({ key, value }));
return foundCategories;
};
export default function GalleryCategoryFilter(): ReactElement {
const [selectedCategory, setSelectedCategory] = useState<string>('all')
const [categories, setCategories] = useState<FoundCategories>([]);
useEffect(() => {
const storedCategories = localStorage.getItem('galleryCategories');
if (storedCategories) {
setCategories(JSON.parse(storedCategories));
} else {
const formattedCategories = fetchAndFormatCategories();
localStorage.setItem('galleryCategories', JSON.stringify(formattedCategories));
setCategories(formattedCategories);
}
}, []);
const handleClick = (categoryKey: string): void => {
setSelectedCategory(categoryKey);
};
return (
<section className='gallery-filter'>
<aside>
<ul className='gallery-filter__list'>
{
categories.map((category: { key: string, value: string }) => {
return (
<li className='gallery-filter__list--item' onClick={() => { handleClick(category.key) }} key={category.key} >{category.value}</li>
)
})
}
</ul>
</aside>
<GalleryGrid
// Add a skeleton UI to load while the categories are being fetched.
galleryImages={galleryData}
selectedCategory={selectedCategory}
/>
</section>
);
};
And here’s the Child component GalleryGrid
import { ReactElement } from 'react';
import { GalleryGridProps } from './types';
import { Image } from '../GalleryCategoryFilter/types';
import './GalleryGrid.scss';
export default function GalleryGrid({ galleryImages, selectedCategory }: GalleryGridProps): ReactElement {
// the gallery images showing must have the category matching selectedCategory
// selectedCategory must be unformatted in order to match the category in the galleryImages
return (
<section className='gallery-grid'>
{(selectedCategory === "all" ? galleryImages : galleryImages.filter(image => image.category === selectedCategory)).map((image: Image, index: number) => {
return (
<img
key={index}
className="gallery-grid__item"
src={image.thumbSrc}
alt={image.alt}
style={{
objectPosition: `${image.thumbPosX} ${image.thumbPosY}`
}}
/>
)
})}
</section>
);
};
I tried React Transition Group, but wasn’t getting a ton out of it – couldn’t see a lot of it in use.
johnny5ive is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.