Todos os componentes

Magnified Tab

Magnified Tab é um componente de navegação para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.

UI Layouts MIT navigation

O que é

Magnified Tab é um componente de navegação para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.

Como usar

Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.

Abrir no catálogo

Cinco cópias grátis por mês. Sem cartão.

Precisa de

npm i motion @radix-ui/react-tooltip

Licença

Este componente vem de UI Layouts e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.

Magnified Tab

./registry/components/tabs/magnified-tabs.tsx
//@ts-nocheck
'use client';

import { Icons } from '@/assets/icons/Icons';
import preview from '@/assets/preview/Preview';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/magnified-doc';
import { apps } from '@/components/website/constant';
import {
  AnimatePresence,
  type MotionValue,
  motion,
  useMotionValue,
  useSpring,
  useTransform,
} from 'motion/react';
import Image from 'next/image';
import React, { useRef, useState } from 'react';

const Component = React.forwardRef((props, ref) => <Image {...props} ref={ref} alt='App' />);

const MotionComponent = motion(Component);

function MagnifiedDocOneFile() {
  const mouseX = useMotionValue(Number.POSITIVE_INFINITY);
  const [index, setIndex] = useState(0);
  const [prevIndex, setPrevIndex] = useState(0);

  const handleClick = (i: React.SetStateAction<number>) => {
    setPrevIndex(index);
    setIndex(i);
  };

  const isForward = index > prevIndex || (index === 0 && prevIndex === apps.length - 1);

  return (
    <>
      <div className='relative [box-shadow] w-4/5 mx-auto  rounded-xl  dark:bg-neutral-950 bg-neutral-300  [box-shadow:inset_1px_-1px_4px_rgba(0_0_0,0.5)] overflow-hidden '>
        <div className='relative'>
          {apps.map((app, i) => {
            return (
              <>
                <AnimatePresence mode={'popLayout'}>
                  {index === i && (
                    <motion.div
                      initial={{
                        opacity: 0,
                        y: isForward ? 30 : -30,
                      }}
                      animate={{
                        opacity: 1,
                        y: 0,
                      }}
                      exit={{
                        opacity: 0,
                        y: isForward ? -30 : 30,
                      }}
                      transition={{
                        ease: 'easeInOut',
                        duration: 0.3,
                        delay: 0.4,
                      }}
                      className='w-full h-full cursor-pointer'
                      onClick={app?.onClick}
                    >
                      <Image
                        src={app?.imgSrc}
                        alt='images'
                        width={1000}
                        height={1000}
                        className='w-full sm:h-[500px] h-[400px] object-cover  rounded-lg'
                      />
                    </motion.div>
                  )}
                </AnimatePresence>
              </>
            );
          })}

          <div className='absolute bottom-0 left-0 w-full z-20'>
            <div className='w-fit mx-auto'>
              <TooltipProvider delayDuration={0}>
                <motion.div
                  onMouseMove={(e) => mouseX.set(e.pageX)}
                  onMouseLeave={() => mouseX.set(Number.POSITIVE_INFINITY)}
                  className='mx-auto flex sm:h-[57px] h-[52px] w-fit items-end gap-2 rounded-t-lg px-2 pb-2 dark:bg-neutral-800/80 bg-white/50 backdrop-blur-xs border-t border-l border-r  '
                >
                  {apps.map((app, i) => {
                    return (
                      <Tooltip key={app.id}>
                        <TooltipTrigger onClick={() => handleClick(i)}>
                          <span className='sr-only'>{app.name}</span>
                          <AppIcon mouseX={mouseX} src={app.icon} />
                        </TooltipTrigger>
                        <TooltipContent className='py-1 px-3 rounded-xs' sideOffset={8}>
                          <p className='text-xs'>{app.name}</p>
                        </TooltipContent>
                      </Tooltip>
                    );
                  })}
                </motion.div>
              </TooltipProvider>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

function AppIcon({ mouseX, src }: { mouseX: MotionValue; src: any }) {
  const ref = useRef<HTMLDivElement>(null);

  const distance = useTransform(mouseX, (val) => {
    const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };

    return val - bounds.x - bounds.width / 2;
  });

  const widthSync = useTransform(distance, [-100, 0, 100], [40, 55, 40]);
  const width = useSpring(widthSync, {
    mass: 0.1,
    stiffness: 150,
    damping: 12,
  });

  return (
    <>
      <MotionComponent
        src={src}
        width={60}
        height={60}
        alt=''
        quality={100}
        ref={ref}
        style={{ width }}
        className='aspect-square rounded-lg sm:w-8 w-6  object-cover'
      />
    </>
  );
}
export default MagnifiedDocOneFile;
./components/ui/magnified-doc.tsx
'use client';

import { cn } from '@/lib/utils';
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import * as React from 'react';

const TooltipProvider = TooltipPrimitive.Provider;

const Tooltip = TooltipPrimitive.Root;

const TooltipTrigger = TooltipPrimitive.Trigger;

const TooltipContent = React.forwardRef<
  React.ElementRef<typeof TooltipPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
  <TooltipPrimitive.Portal>
    <TooltipPrimitive.Content
      ref={ref}
      sideOffset={sideOffset}
      className={cn(
        'z-50 overflow-hidden rounded-lg border dark:bg-neutral-800 bg-neutral-50 backdrop-filter dark:border-[#2C2C2C] backdrop-blur-lg dark:bg-[#1A1A1A]/95 px-4 py-3 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
        className
      )}
      {...props}
    />
  </TooltipPrimitive.Portal>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;

export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };

Componentes parecidos