Project Gallery
atlas-ui/project-galleryFreeComponent
A Project Gallery with an interactive modal.
Live preview
live · rendered by the registry
Rendered by atlas-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://atlasui.dev/r/project-gallery.jsonSource
1"use client";23import React, {4 Dispatch,5 ReactNode,6 SetStateAction,7 useEffect,8 useRef,9 useState,10} from "react";1112import Image from "next/image";13import Link from "next/link";1415import { motion, useMotionValue, useSpring } from "motion/react";1617interface ProjectGalleryProps {18 children: ReactNode;19}2021interface BaseProjectProps {22 title: string;23 subtitle: string;24 href: string;25 imgSrc: string;26 color: string;27}2829interface InternalProjectProps extends BaseProjectProps {30 index: number;31 setModal: Dispatch<SetStateAction<{ active: boolean; index: number }>>;32}3334interface ModalProps {35 modal: { active: boolean; index: number };36 projects: BaseProjectProps[];37 containerRef: React.RefObject<HTMLDivElement | null>;38}3940const ProjectGallery = ({ children }: ProjectGalleryProps) => {41 const [modal, setModal] = useState({ active: false, index: 0 });42 const containerRef = useRef<HTMLDivElement>(null);4344 return (45 <div46 ref={containerRef}47 className="relative grid grid-cols-1 sm:grid-cols-2 md:block"48 >49 {children &&50 React.Children.map(children, (child, index) => {51 if (React.isValidElement<BaseProjectProps>(child)) {52 return React.cloneElement(53 child as React.ReactElement<InternalProjectProps>,54 {55 index,56 setModal,57 }58 );59 }60 return child;61 })}62 <Modal63 modal={modal}64 projects={React.Children.toArray(children)65 .map((child) => {66 if (React.isValidElement<BaseProjectProps>(child)) {67 const { title, subtitle, imgSrc, color, href } = child.props;68 return { title, subtitle, imgSrc, color, href };69 }70 return null;71 })72 .filter((project): project is BaseProjectProps => project !== null)}73 containerRef={containerRef}74 />75 </div>76 );77};7879const Project = (props: BaseProjectProps | InternalProjectProps) => {80 const { title, subtitle, href, imgSrc, color, index, setModal } =81 props as InternalProjectProps;8283 return (84 <Link href={href}>85 <div86 className="border-primary group flex w-full cursor-pointer flex-col justify-between p-4 transition-all duration-200 ease-linear md:flex-row md:items-center md:border-t md:p-24 md:hover:opacity-40"87 onMouseEnter={() => setModal?.({ active: true, index })}88// … truncated
What it pulls in
npm packages
Files it writes
More from atlas-ui
All 99 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Mobile Navbaranimated-mobile-navbar | atlas-ui | Components | Free | 2 deps | |
| Blend Mouse Trailerblend-mouse-trailer | atlas-ui | Components | Free | 1 dep | |
| Blob Mouse Trailerblob-mouse-trailer | atlas-ui | Components | Free | 1 dep | |
| Box Revealbox-reveal | atlas-ui | Components | Free | 1 dep | |
| Cascade Textcascade-text | atlas-ui | Components | Free | 1 dep | |
| Dot And Circle Mouse Trailerdot-and-circle-mouse-trailer | atlas-ui | Components | Free | 1 dep | |
| Fancy Theme Togglefancy-theme-toggle | atlas-ui | Components | Free | 1 dep | |
| Hacker Texthacker-text | atlas-ui | Components | Free | no deps |
