Skip to content

Instantly share code, notes, and snippets.

@sadiqsalau
Last active February 15, 2024 03:22
Show Gist options
  • Save sadiqsalau/9a523c58ff906216f39c55e1810a0d7a to your computer and use it in GitHub Desktop.
Save sadiqsalau/9a523c58ff906216f39c55e1810a0d7a to your computer and use it in GitHub Desktop.
React Isotope
/** npm install isotope-layout clsx **/
import IsotopeLayout from "isotope-layout";
import React from "react";
import clsx from "clsx";
const IsotopeContext = React.createContext();
export const Isotope = ({ children, ...props }) => {
const isotope = React.useRef();
const [filterKey, setFilterKey] = React.useState("*");
const containerRef = React.useRef();
React.useEffect(() => {
isotope.current = new IsotopeLayout(containerRef.current, {
itemSelector: ".isotope-filter-item",
...props,
});
return () => {
isotope.current?.destroy();
};
}, []);
React.useEffect(() => {
if (isotope.current) {
filterKey === "*"
? isotope.current.arrange({ filter: `*` })
: isotope.current.arrange({ filter: `.${filterKey}` });
}
}, [filterKey]);
const handleFilterKeyChange = (key) => () => setFilterKey(key);
return (
<IsotopeContext.Provider
value={{
isotope,
filterKey,
handleFilterKeyChange,
containerRef,
...props,
}}
>
{children}
</IsotopeContext.Provider>
);
};
export const IsotopeContainer = ({
as: Component = "div",
children,
...props
}) => {
const { containerRef } = React.useContext(IsotopeContext);
return (
<Component {...props} ref={containerRef}>
{children}
</Component>
);
};
export const IsotopeFilter = ({
as: Component = "button",
filter = "*",
children,
...props
}) => {
const { filterKey, handleFilterKeyChange } = React.useContext(IsotopeContext);
return (
<Component
{...props}
className={
typeof props.className === "function"
? props.className(filterKey === filter)
: clsx(props.className, filterKey === filter ? "active" : null)
}
onClick={handleFilterKeyChange(filter)}
>
{children}
</Component>
);
};
export const IsotopeItem = ({ filter, children, ...props }) => (
<div
{...props}
className={clsx("isotope-filter-item", filter, props.className)}
>
{children}
</div>
);
export default function IsotopeExample() {
return (
<Isotope>
<div>
<IsotopeFilter filter="*">All</IsotopeFilter>
<IsotopeFilter filter="group-1">Group 1</IsotopeFilter>
</div>
<IsotopeContainer>
<IsotopeItem filter="group-1">Group 1 - Item 1</IsotopeItem>
<IsotopeItem filter="group-2">Group 2 - Item 1</IsotopeItem>
</IsotopeContainer>
</Isotope>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment