Index
Craft
Projects
Blog
Connect

BrandFlow: A Smooth, Interactive Logo Showcase Inspired by Linear

Aug 31, 2025

BrandFlow is a sleek two-row logo grid with smooth hover effects and staggered transitions, inspired by Linear’s clean UI.

It is perfect for showcasing sponsors, clients, or partners on your website in an interactive way.

Key Features

  • Two-row animated grid with smooth transitions.
  • Blur and scale effect on hover for depth.
  • Staggered logo entrance and exit animations.
  • Interactive overlay button for calls to action.
  • Minimal, modern, Linear-inspired design.

Code Example

/'use client'
import { CaretRightIcon } from '@phosphor-icons/react'
import { motion, AnimatePresence } from 'framer-motion'
import { useState, useEffect } from 'react'

const logos = [
  [
    ['/crafts/logo1.svg', '/crafts/logo2.svg', '/crafts/logo3.svg'],
    ['/crafts/logo4.svg', '/crafts/logo5.svg', '/crafts/logo6.svg'],
  ],
  [
    ['/crafts/logo7.svg', '/crafts/logo8.svg', '/crafts/logo9.svg'],
    ['/crafts/logo10.svg', '/crafts/logo11.svg', '/crafts/logo12.svg'],
  ],
]

const transition = { duration: 0.5, ease: 'easeInOut' }
const transition1 = { duration: 0.15, ease: 'easeInOut' }

const rowVariants = {
  animate: { transition: { staggerChildren: 0.5 } },
  exit: { transition: { staggerChildren: 0.5, staggerDirection: -1 } },
}

const logoVariants = {
  enter: { opacity: 0, scale: 0.8, filter: 'blur(8px)' },
  center: { opacity: 1, scale: 1, filter: 'blur(0px)', transition },
  exit: { opacity: 0, scale: 1.1, filter: 'blur(8px)', transition },
}

const labelVariants = {
  hidden: { opacity: 0, scale: 0.95 },
  visible: { opacity: 1, scale: 1, transition: transition1 },
  exit: { opacity: 0, scale: 0.95, transition: transition1 },
}

const Page = () => {
  const [index, setIndex] = useState(0)
  const [hovered, setHovered] = useState(false)

  useEffect(() => {
    const interval = setInterval(() => {
      setIndex((prev) => (prev + 1) % logos.length)
    }, 3000)
    return () => clearInterval(interval)
  }, [])

  return (
    <div className="max-w-3xl mx-auto min-h-screen w-screen flex flex-col items-center justify-center relative cursor-pointer">
      <div className='flex flex-col -space-y-1 text-center tracking-tight text-xl text-white pb-15'>
        <div>Powering the world&apos;s best product teams.</div>
        <div className='text-neutral-400'>From next-gen startups to established enterprises.</div>
      </div>
      {/* Wrap both logos grid and overlay button in one hover container */}
      <div
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
        className="relative"
      >
        {/* Logos Grid with blur on hover */}
        <motion.div
  className="flex flex-col space-y-5 relative cursor-pointer pointer-events-auto"
  style={{ filter: hovered ? 'blur(6px)' : 'blur(0px)' }}
  transition={{ duration: 0.10, ease: 'easeInOut' }}
>

          {logos[index].map((row, rowIndex) => (
            <motion.div
              key={rowIndex + '-' + index}
              className="flex justify-center space-x-25"
              variants={rowVariants}
              initial="animate"
              animate="animate"
              exit="exit"
            >
              <AnimatePresence mode="wait">
                {row.map((src, i) => (
                  <motion.img
                    key={src}
                    src={src}
                    className="w-24 h-24"
                    variants={logoVariants}
                    initial="enter"
                    animate="center"
                    exit="exit"
                  />
                ))}
              </AnimatePresence>
            </motion.div>
          ))}
        </motion.div>

        {/* Overlay Label with motion */}
        <AnimatePresence>
          {hovered && (
            <motion.div
              className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 pointer-events-auto"
              variants={labelVariants}
              initial="hidden"
              animate="visible"
              exit="exit"
            >
              <button className="flex items-center justify-center text-white font-medium bg-neutral-800 border border-neutral-600/60 text-sm px-3 py-1 rounded-full">
                Meet our sponsors <CaretRightIcon size={14} className="text-neutral-400" />
              </button>
            </motion.div>
          )}
        </AnimatePresence>
      </div>

      <div className='pt-40'>
        <a
          href='/'
          target="_blank"
          rel="noopener noreferrer"
          className='underline underline-offset-4 text-sm font-medium gap-1 text-[#f9a8d5] hover:text-[#facfe6] transition-colors duration-200 cursor-pointer'
        >
          Access the code on blog
        </a>
      </div>
    </div>
  )
}

export default Page
© 2025 Sumona Biswas
When in doubt, minimise.