From 824be0bbd14d6ca4670d71a227c5b087a47e85e0 Mon Sep 17 00:00:00 2001 From: Lanskikh Date: Mon, 23 Sep 2024 16:48:24 +0500 Subject: [PATCH] upd --- src/components/Devices.tsx | 13 +++++---- src/components/Interactions.tsx | 2 +- src/components/Layout/Footer.tsx | 15 ++++++----- src/components/Layout/Header.tsx | 6 ++--- src/components/Promotion.tsx | 46 +++++++++++++++++--------------- src/consts/promotionFeatures.ts | 30 +++++++-------------- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/components/Devices.tsx b/src/components/Devices.tsx index 4982142..1f1be79 100644 --- a/src/components/Devices.tsx +++ b/src/components/Devices.tsx @@ -3,7 +3,7 @@ import { devices } from '../consts/devices'; import { IDevice } from '../types/IDevice'; import { Title } from './ui/Title'; import { useEffect, useRef, useState } from 'react'; -import { useHover } from 'usehooks-ts'; +import { useHover, useOnClickOutside } from 'usehooks-ts'; import { ChevronUpIcon } from './icons/ChevronUpIcon'; import { ChevronDownIcon } from './icons/ChevronDownIcon'; @@ -57,6 +57,7 @@ function DesktopDevice({ ? (root.current?.clientHeight ?? 0) + descriptionHeight + 24 : 112, }} + transition={{ delay: 0.3 }} >

{title}

@@ -86,7 +87,7 @@ function DesktopDevice({ initial={{ opacity: 0, y: 500 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 100 }} - transition={{ duration: 0.5 }} + transition={{ duration: 0.5, delay: 0.3 }} /> )} @@ -97,13 +98,13 @@ function DesktopDevice({ function Device({ title, description, img }: IDevice) { const [expanded, setExpanded] = useState(false); + const [descriptionHeight, setDescriptionHeight] = useState(0); + const [imgHeight, setImgHeight] = useState(0); + const root = useRef(null); const descriptionRef = useRef(null); const imgRef = useRef(null); - const [descriptionHeight, setDescriptionHeight] = useState(0); - const [imgHeight, setImgHeight] = useState(0); - useEffect(() => { if (!imgRef.current) return; imgRef.current!.onload = () => @@ -114,6 +115,8 @@ function Device({ title, description, img }: IDevice) { setDescriptionHeight(descriptionRef.current?.clientHeight ?? 0); }, [descriptionRef, expanded]); + useOnClickOutside(root, () => setExpanded(false)); + return ( +
С помощью интерактивных инструментов создаем систему{' '} <span className="text-gradient"> diff --git a/src/components/Layout/Footer.tsx b/src/components/Layout/Footer.tsx index fa76ac5..ca04eed 100644 --- a/src/components/Layout/Footer.tsx +++ b/src/components/Layout/Footer.tsx @@ -9,12 +9,15 @@ export function Footer() { <Logo /> </Link> <div className="flex flex-col gap-y-1"> - <Link - to="https://graff.tech/privacypolicy" - className="flex gap-4 sm:font-medium m-text" - > - Политика конфиденциальности <span>graff.tech</span> - </Link> + <div className="flex gap-x-4"> + <Link + to="https://graff.tech/privacypolicy" + className="flex gap-4 sm:font-medium m-text" + > + Политика конфиденциальности + </Link> + <Link to="https://graff.tech">graff.tech</Link> + </div> <p className="opacity-40 sm:font-medium m-text"> © 2024 GRAFF interactive. Все права защищены </p> diff --git a/src/components/Layout/Header.tsx b/src/components/Layout/Header.tsx index eb17e14..631533b 100644 --- a/src/components/Layout/Header.tsx +++ b/src/components/Layout/Header.tsx @@ -24,7 +24,7 @@ export function Header() { ); return ( - <header className="lg:px-6 px-4 flex max-lg:justify-between items-center lg:h-16 h-12 border-b border-[#3D425C] bg-[#14161F]"> + <header className="sticky top-0 lg:px-6 px-4 flex max-lg:justify-between items-center lg:h-16 h-12 border-b border-[#3D425C] bg-[#14161F] z-50"> <Link to={'/'} className="max-sm:hidden"> <ClassNameWrapper element={<Logo />} className="h-8 lg:h-10" /> </Link> @@ -34,8 +34,8 @@ export function Header() { <nav className="flex self-stretch mx-auto max-lg:hidden"> {[ { path: '/#products', text: 'Продукты' }, - { path: '/#devices', text: 'Оборудование' }, { path: '/#projects', text: 'Проекты' }, + { path: '/#devices', text: 'Оборудование' }, { path: '/#contacts', text: 'Контакты' }, ].map(link => ( <HashLink key={link.path} {...link} /> @@ -75,8 +75,8 @@ export function Header() { > <div> <HashLink text="Продукты" path={'#products'} /> - <HashLink text="Оборудование" path={'#devices'} /> <HashLink text="Проекты" path={'#projects'} /> + <HashLink text="Оборудование" path={'#devices'} /> <HashLink text="Контакты" path={'#contacts'} /> </div> <div className="grid grid-cols-[2fr_1fr_1fr] sm:grid-cols-2"> diff --git a/src/components/Promotion.tsx b/src/components/Promotion.tsx index ab12464..4672aa6 100644 --- a/src/components/Promotion.tsx +++ b/src/components/Promotion.tsx @@ -7,7 +7,6 @@ import { hashes } from '../consts/motivationHashes'; import { ChevronUpIcon } from './icons/ChevronUpIcon'; import { ChevronDownIcon } from './icons/ChevronDownIcon'; import { useWindowWidth } from '../hooks/useWindowWidth'; -import { ClassNameWrapper } from '../hocs/ClassNameWrapper'; import { useOnClickOutside } from 'usehooks-ts'; export function Promotion() { @@ -16,7 +15,7 @@ export function Promotion() { return ( <div id="products" - className="space-y-8 lg:space-y-20 sm:space-y-10 lg:-mt-20 sm:-mt-10" + className="space-y-8 lg:space-y-20 sm:space-y-10 lg:-mt-4 sm:-mt-10" > <Title className="max-w-[calc(1310/1600*100vw)]"> Повышаем количество посетителей на стенде, @@ -73,7 +72,7 @@ function DesktopFeature({ <div id={hashes.get(number)} onClick={() => setExpanded(prev => !prev)} - className="py-7 border-t border-[#3D425C] cursor-pointer relative last:border-b bg-[url(/images/promotion/Ellipse.png)] bg-[length:0%_0%] hover:bg-[length:100%_100%] transition-all bg-no-repeat bg-top" + className="select-none py-7 border-t border-[#3D425C] cursor-pointer relative last:border-b bg-[url(/images/promotion/Ellipse.png)] bg-[length:0%_0%] hover:bg-[length:100%_100%] transition-all bg-no-repeat bg-top" ref={ref} > <motion.div @@ -86,14 +85,13 @@ function DesktopFeature({ <div className="max-w-[40vw] flex flex-col xl:gap-y-12 gap-y-6 justify-between h-full"> <p className="l-text text-[#52587A] font-medium">[0{number}]</p> <div className="space-y-6"> - <p className="text-[32px] leading-none font-medium transition-all duration-700"> - {title} - </p> + <p className="text-[32px] leading-none font-medium">{title}</p> {expanded && ( <motion.p className="font-medium h4 opacity-60" + initial={{ opacity: 0 }} animate={expanded ? { opacity: 0.6 } : { opacity: 0 }} - transition={{ delay: 1 }} + transition={{ delay: 0.25 }} > {description} </motion.p> @@ -116,7 +114,7 @@ function DesktopFeature({ src={image} alt={title} transition={{ duration: 0.5 }} - className="h-full " + className="h-full pointer-events-none" animate={{ maxHeight: expanded && index === 0 ? 0.265 * width : 0.0875 * width, @@ -145,44 +143,50 @@ function Feature({ number: number; }) { const [expanded, setExpanded] = useState(false); + const [descriptionHeight, setDescriptionHeight] = useState(0); const { hash } = useLocation(); const ref = useRef<HTMLDivElement>(null); + const descriptionRef = useRef<HTMLParagraphElement>(null); useEffect(() => { setExpanded(hash.slice(1) === hashes.get(number)); }, [hash, number]); + useEffect(() => { + setDescriptionHeight(descriptionRef.current?.clientHeight ?? 0); + }, [expanded, descriptionRef]); + + useEffect(() => { + if (!ref.current) return; + ref.current.style.height = `${ref.current.clientHeight} ${descriptionHeight}px`; + }, [descriptionHeight, expanded]); + useOnClickOutside(ref, () => setExpanded(false)); return ( <div ref={ref} id={hashes.get(number)} - className="sm:py-4 py-2 sm:space-y-8 space-y-4 border-t border-[#3D425C] last:border-b flex flex-col justify-between relative" + className="select-none sm:py-4 py-2 sm:space-y-8 space-y-4 border-t border-[#3D425C] last:border-b flex flex-col justify-between relative transition-all" onClick={() => setExpanded(prev => !prev)} > - <div className="flex items-center justify-between max-sm:items-start gap-x-5"> + <div className="flex items-center justify-between gap-x-5"> <p className="font-medium h3">{title}</p> <div className="border p-2 border-[#3D425C] rounded-full"> - <ClassNameWrapper - className="flex-1" - element={expanded ? <ChevronUpIcon /> : <ChevronDownIcon />} - /> + {expanded ? <ChevronUpIcon /> : <ChevronDownIcon />} </div> </div> <AnimatePresence> {expanded && ( <motion.p + ref={descriptionRef} className="font-medium l-text" - transition={{ delay: 1 }} - initial={{ opacity: 0 }} - animate={ - expanded - ? { opacity: 0.6, transition: { delay: 0.5 } } - : { opacity: 0 } - } + transition={{ delay: 0.25 }} + initial={{ opacity: 0, y: 10 }} + animate={expanded ? { opacity: 0.6, y: 0 } : { opacity: 0, y: 10 }} + exit={{ opacity: 0, y: 10 }} > {description} </motion.p> diff --git a/src/consts/promotionFeatures.ts b/src/consts/promotionFeatures.ts index af18237..8a7bef6 100644 --- a/src/consts/promotionFeatures.ts +++ b/src/consts/promotionFeatures.ts @@ -3,8 +3,8 @@ import { IPromotionFeature } from '../types/IPromotionFeature'; export const promotionFeatures: IPromotionFeature[] = [ { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', - title: 'Интерактивные презентации', + 'Инструмент для демонстрации вашего продукта или проекта в 3D формате с возможностью донести в максимально удобном виде любые особенности и ключевые преимущества.', + title: '3D интерактивные презентации', images: [ '/images/promotion/presentations/1.png', '/images/promotion/presentations/2.png', @@ -13,8 +13,8 @@ export const promotionFeatures: IPromotionFeature[] = [ }, { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', - title: '3D интерактивные презентации техники и оборудования', + 'Дает возможность посетителям самостоятельно искать, фильтровать, сравнивать и рассматривать 3D модели продуктов.', + title: 'Интерактивный каталог продукции', images: [ '/images/promotion/devices/1.png', '/images/promotion/devices/2.png', @@ -22,29 +22,19 @@ export const promotionFeatures: IPromotionFeature[] = [ }, { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', - title: 'Интерактивный каталог продукции', + 'Комплекс сочетающий в себя физический макет и трехмерный интерактивный контентом. Сочетание физического макета и виртуального контента создает эффект присутствия и погружения. Посетители могут лучше прочувствовать замысел и идею проекта.', + title: '3D интерактивные макеты', images: ['/images/promotion/catalog/1.png'], }, { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', - title: '3D интерактивные макеты', + 'Дают возможность удаленно демонстрировать экспонаты, проводить презентации, организовывать виртуальные туры. Это повышает доступность и географию охвата мероприятия.', + title: 'Приложения с виртуальной и дополненной реальностью', images: [ '/images/promotion/templates/1.png', '/images/promotion/templates/2.png', ], }, - { - description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', - title: 'Приложения с виртуальной и дополненной реальностью', - images: [ - '/images/promotion/arvr/1.png', - '/images/promotion/arvr/2.png', - '/images/promotion/arvr/3.png', - ], - }, { description: 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', @@ -53,7 +43,7 @@ export const promotionFeatures: IPromotionFeature[] = [ }, { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', + 'Технология позволяет создавать интерактивные экспонаты с распознаванием жестов и движений посетителей для управления интерактивными дисплеями и 3D моделями.', title: 'Компьютерное зрение', images: [ '/images/promotion/computer_vision/1.png', @@ -62,7 +52,7 @@ export const promotionFeatures: IPromotionFeature[] = [ }, { description: - 'Ключевые преимущества жилого комплекса показаны на интерактивной модели. Для этого создается маршрут, демонстрирующий детали комплекса, важные для покупателя', + 'Используюся для инструмент для управления контентом сторонних приложений и взаимодействия с дополненной реальностью', title: 'Мобильные приложения', images: [ '/images/promotion/mobiles/1.png',