continued adaptive

This commit is contained in:
2024-09-04 16:49:55 +05:00
parent d1caddbde5
commit 6b9004d4b1
17 changed files with 421 additions and 92 deletions
@@ -7,7 +7,7 @@ import { VKIcon } from './icons/VKIcon';
import { YoutubeIcon } from './icons/YoutubeIcon';
import { Link } from 'react-router-dom';
export function Feedback() {
export function Contacts() {
return (
<div
id="contacts"
+11 -11
View File
@@ -3,21 +3,21 @@ import { FeedbackForm } from './Layout/FeedbackForm';
export function Form() {
return (
<div className="py-6 space-y-20">
<Title className="max-w-[58vw]">
<div className="py-6 lg:space-y-20 sm:space-y-10 space-y-8">
<Title className="lg:max-w-[58vw]">
Хотите интерактивное решение для выставки?
<br />
<span className="text-gradient">Давайте обсудим детали.</span>
<br className="max-lg:hidden" />
<span className="text-gradient"> Давайте обсудим детали.</span>
</Title>
<div className="relative">
<div className="relative max-lg:flex items-center gap-x-[35px]">
<FeedbackForm />
<div className="absolute bottom-0 -right-[min(136px,calc(136/1600*100vw))] animate-[spin_10s_linear_infinite]">
<div className="relative w-[calc(512/1600*100vw)] aspect-square flex justify-center transition-all duration-500 hover:w-[calc(446/1600*100vw)] origin-center">
<div className="w-[calc(116/1600*100vw)] flex flex-col justify-between h-full absolute">
<div className="max-sm:hidden absolute lg:bottom-0 lg:-right-[min(136px,calc(136/1600*100vw))] sm:-right-[min(196px,calc(196/768*100vw))] animate-[spin_10s_linear_infinite]">
<div className="relative lg:w-[calc(512/1600*100vw)] sm:w-[calc(512/768*100vw)] aspect-square flex justify-center transition-all duration-500 lg:hover:w-[calc(446/1600*100vw)] origin-center">
<div className="lg:w-[calc(116/1600*100vw)] sm:w-[calc(116/768*100vw)] flex flex-col justify-between h-full absolute">
<img src="/src/assets/form/1_1.png" alt="" />
<img src="/src/assets/form/1_2.png" alt="" />
</div>
<div className="w-[calc(116/1600*100vw)] flex flex-col justify-between h-full absolute rotate-45">
<div className="lg:w-[calc(116/1600*100vw)] sm:w-[calc(116/768*100vw)] flex flex-col justify-between h-full absolute rotate-45">
<img
src="/src/assets/form/2_1.png"
className="-rotate-45"
@@ -29,7 +29,7 @@ export function Form() {
alt=""
/>
</div>
<div className="w-[calc(116/1600*100vw)] flex flex-col justify-between h-full absolute rotate-90">
<div className="lg:w-[calc(116/1600*100vw)] sm:w-[calc(116/768*100vw)] flex flex-col justify-between h-full absolute rotate-90">
<img
src="/src/assets/form/3_1.png"
className="-rotate-90"
@@ -41,7 +41,7 @@ export function Form() {
alt=""
/>
</div>
<div className="w-[calc(116/1600*100vw)] flex flex-col justify-between h-full absolute rotate-[135deg]">
<div className="lg:w-[calc(116/1600*100vw)] sm:w-[calc(116/768*100vw)] flex flex-col justify-between h-full absolute rotate-[135deg]">
<img
src="/src/assets/form/4_1.png"
className="-rotate-[135deg]"
+8 -3
View File
@@ -79,12 +79,17 @@ export function FeedbackForm({
return (
<form
onSubmit={handleSubmit}
className={inModal ? 'space-y-6' : 'space-y-12 max-w-[66vw]'}
className={
inModal
? 'space-y-6'
: 'lg:space-y-12 sm:space-y-36 space-y-8 lg:max-w-[66vw] sm:max-w-[calc(369/720*100%)]'
}
>
<div className="space-y-6">
<div
className={
'grid gap-x-4 items-start ' + (inModal ? 'gap-y-6' : 'grid-cols-3')
'grid gap-x-4 items-start ' +
(inModal ? 'gap-y-6' : 'lg:grid-cols-3 max-lg:gap-y-4')
}
>
<div className="w-full">
@@ -171,7 +176,7 @@ export function FeedbackForm({
</div>
</div>
<div className="space-y-4 max-w-[25vw]">
<div className="space-y-4 lg:max-w-[25vw] sm:max-lg:mt-36">
<Button
width="full"
disabled={isLoading}
+13 -5
View File
@@ -10,6 +10,7 @@ import { BurgerIcon } from '../icons/BurgerIcon';
import { CloseIcon } from '../icons/CloseIcon';
import { useOnClickOutside } from 'usehooks-ts';
import { useLanguageStore } from '../../stores/languageStore';
import { LogoWithoutText } from '../icons/LogoWithoutText';
export function Header() {
const { setModal } = useModalStore();
@@ -23,9 +24,16 @@ export function Header() {
);
return (
<header className="lg:px-6 sm:px-4 flex max-lg:justify-between items-center h-16 border-b border-[#3D425C] bg-[#14161F]">
<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]">
<Link to={'/'}>
<ClassNameWrapper element={<Logo />} className="h-10" />
<ClassNameWrapper
element={<Logo />}
className="lg:h-10 h-8 max-sm:hidden"
/>
<ClassNameWrapper
element={<LogoWithoutText />}
className="h-8 sm:hidden"
/>
</Link>
<nav className="mx-auto self-stretch flex max-lg:hidden">
{[
@@ -37,9 +45,9 @@ export function Header() {
<HashLink key={link.path} {...link} />
))}
</nav>
<div className="lg:-mr-6 sm:-mr-4 flex h-full">
<div className="lg:-mr-6 -mr-4 flex h-full">
<Button
className="rounded-none h-full px-10"
className="rounded-none h-full lg:px-10 px-6 btn-text"
onClick={() => setModal(<ModalWithForm />)}
>
Оставить заявку
@@ -65,7 +73,7 @@ export function Header() {
ref={menuRef}
onClick={() => setMenuOpen(false)}
className={
'absolute z-50 w-full lg:hidden sm:max-[1350px]:max-w-[340px] right-0 top-16' +
'absolute z-50 w-full lg:hidden sm:max-[1350px]:max-w-[340px] right-0 lg:top-16 top-12' +
(menuOpen ? ' shadow-[0_0_0_9999px_rgba(0,0,0,.4)]' : '')
}
>
+7 -4
View File
@@ -1,23 +1,26 @@
import { Outlet } from 'react-router-dom';
import { Footer } from './Footer';
import { Header } from './Header';
import { Feedback } from '../Feedback';
import { Contacts } from '../Contacts';
import { Clients } from '../Clients';
import { ScrollToHashElement } from './ScrollToHashElement';
import { ModalContainer } from './ModalContainer';
import { Ellipse } from './Ellipse';
import { useWindowWidth } from '../../hooks/useWindowWidth';
export function Layout() {
const width = useWindowWidth();
return (
<div className="overflow-clip">
<ScrollToHashElement />
<Header />
<main className="lg:px-6 sm:px-4 relative">
<Ellipse />
<main className="lg:px-6 px-4 relative">
{width >= 1024 && <Ellipse />}
<Outlet />
</main>
<Clients />
<Feedback />
<Contacts />
<Footer />
<ModalContainer />
</div>
+3 -3
View File
@@ -3,13 +3,13 @@ import { Showreel } from './Showreel';
export function Motivation() {
return (
<div className="pt-20">
<div className="space-y-12 mb-6">
<div className="lg:pt-20 sm:pt-14 pt-16">
<div className="lg:space-y-12 space-y-8 mb-6">
<h1 className="h1 font-medium">
Создаем интерактивные
<span className="text-gradient"> выставочные решения</span>
</h1>
<div className="flex gap-x-5">
<div className="flex flex-wrap sm:gap-x-5 gap-x-2 gap-y-4">
{[
{ solution: 'VR и AR', count: 12 },
{ solution: 'Интерактивные приложения', count: 21 },
+5 -5
View File
@@ -4,16 +4,16 @@ import { Title } from './ui/Title';
export function Projects() {
return (
<div id={'projects'} className="space-y-6">
<div id="projects" className="sm:space-y-6 space-y-10">
<Title>Проекты</Title>
<div className="flex flex-col gap-y-16">
<div className="flex gap-x-4">
<div className="lg:flex flex-col gap-y-16 sm:space-y-10 space-y-8">
<div className="lg:flex sm:space-y-10 space-y-8 gap-x-4">
{projects.slice(0, 2).map(project => (
<Project {...project} key={project.title} />
))}
</div>
<Project {...projects[2]} className="max-w-[82vw] self-end" />
<div className="flex gap-x-4">
<Project {...projects[2]} className="lg:max-w-[82vw] self-end" />
<div className="lg:flex sm:space-y-10 space-y-8 gap-x-4">
{projects.slice(3).map(project => (
<Project {...project} key={project.title} />
))}
+77 -6
View File
@@ -1,16 +1,22 @@
import { AnimatePresence, motion } from 'framer-motion';
import { Title } from './ui/Title';
import { promotionFeatures } from '../consts/promotionFeatures';
import { useRef } from 'react';
import { useRef, useState } from 'react';
import { useHover } from 'usehooks-ts';
import { useLocation } from 'react-router-dom';
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';
export function Promotion() {
const width = useWindowWidth();
return (
<div
id="products"
className="lg:space-y-20 sm:space-y-10 lg:-mt-20 sm:-mt-10"
className="lg:space-y-20 sm:space-y-10 space-y-8 lg:-mt-20 sm:-mt-10"
>
<Title className="max-w-[calc(1310/1600*100vw)]">
Повышаем количество посетителей на стенде,
@@ -20,9 +26,17 @@ export function Promotion() {
</span>
</Title>
<div>
{promotionFeatures.map((feature, index) => (
<DesktopFeature key={feature.title} number={index + 1} {...feature} />
))}
{promotionFeatures.map((feature, index) =>
width >= 1024 ? (
<DesktopFeature
key={feature.title}
number={index + 1}
{...feature}
/>
) : (
<Feature {...feature} key={feature.title} number={index + 1} />
),
)}
</div>
</div>
);
@@ -130,10 +144,67 @@ function Feature({
title,
description,
images,
number,
}: {
title: string;
description: string;
images: string[];
number: number;
}) {
return <div></div>;
const [expanded, setExpanded] = useState(false);
return (
<div
id={hashes.get(number)}
className="sm:py-4 py-2 sm:space-y-8 space-y-4 border-t border-[#3D425C] last:border-b"
onClick={() => setExpanded(prev => !prev)}
>
<div className="flex justify-between items-center max-sm:items-start gap-x-5">
<p className="h3 font-medium">{title}</p>
<ClassNameWrapper
className="flex-1"
element={expanded ? <ChevronUpIcon /> : <ChevronDownIcon />}
/>
</div>
<AnimatePresence>
{expanded && (
<motion.p
className="l-text font-medium"
transition={{ delay: 1 }}
initial={{ opacity: 0 }}
animate={
expanded
? { opacity: 0.6, transition: { delay: 0.5 } }
: { opacity: 0 }
}
>
{description}
</motion.p>
)}
</AnimatePresence>
<div className="flex gap-x-2 max-sm:hidden">
{images.map((image, index) => (
<AnimatePresence key={image}>
<motion.div
transition={{ duration: 0.5 }}
animate={
expanded
? index === 0
? { width: '100%' }
: { width: '0%' }
: { width: '33%' }
}
className={index > 0 ? 'max-sm:hidden' : ''}
key={image}
>
<img src={image} alt={title} className="w-full" />
</motion.div>
</AnimatePresence>
))}
</div>
<div className="sm:hidden">
<img src={images[0]} className="object-cover w-full" alt={title} />
</div>
</div>
);
}
+6 -3
View File
@@ -23,7 +23,10 @@ export function SelectPhoneCode({
useOnClickOutside(ref, () => setOpen(false));
return (
<div ref={ref} className="relative flex flex-col w-1/3">
<div
ref={ref}
className="relative flex flex-col sm:w-1/3 min-w-[max(10vw,20%)]"
>
<button
className="flex gap-x-1 justify-between items-center relative"
onClick={e => {
@@ -33,7 +36,7 @@ export function SelectPhoneCode({
>
<img
src={countries.find(c => c.iso === currentCountry)?.flag}
className="w-6"
className="sm:w-6 w-4"
alt=""
/>
<p className="h4">{currentPhoneCode}</p>
@@ -59,7 +62,7 @@ export function SelectPhoneCode({
<img
src={countries.find(c => c.iso === country)?.flag}
alt=""
className="w-6"
className="sm:w-6 w-4"
/>
<p className="flex-1 h4 cursor-pointer py-1">{phoneCode}</p>
</div>
+7 -3
View File
@@ -1,10 +1,14 @@
import { ClassNameWrapper } from '../hocs/ClassNameWrapper';
import { FullScreenIcon } from './icons/FullScreenIcon';
export function Showreel() {
return (
<div className="lg:aspect-[1552/616] sm:aspect-[720/440] [background:linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.2)),center/cover_url(src/assets/motivation/Showreel.png)_no-repeat] flex justify-center items-center">
<button className="p-[22px] rounded-full border bg-[#14161F33]">
<FullScreenIcon />
<div className="lg:aspect-[1552/616] sm:aspect-[720/440] aspect-[328/204] [background:linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.2)),center/cover_url(src/assets/motivation/Showreel.png)_no-repeat] flex justify-center items-center">
<button className="sm:p-[22px] p-3 aspect-square rounded-full border bg-[#14161F33]">
<ClassNameWrapper
className="max-sm:w-5 max-sm:h-5"
element={<FullScreenIcon />}
/>
</button>
</div>
);
+12 -2
View File
@@ -3,10 +3,13 @@ import { stands } from '../consts/stands';
import { IStand } from '../types/IStand';
import { SliderWithScaling } from './ui/SliderWithScaling';
import { Title } from './ui/Title';
import { useWindowWidth } from '../hooks/useWindowWidth';
export function Stands() {
const width = useWindowWidth();
return (
<div className="space-y-20">
<div className="lg:space-y-20 sm:space-y-10">
<Title>
Мы разработчики с собственной
<span className="text-gradient">
@@ -18,7 +21,14 @@ export function Stands() {
<SliderWithScaling
slides={stands}
SlideElement={Stand}
slideSizes={['31.6vw', '31.8vw', '48vw', '48vw']}
className="space-y-8 pb-20"
slideSizes={
width >= 1024
? ['31.6vw', '31.8vw', '48vw', '48vw']
: width >= 640
? ['93.75vw', '93.75vw', '93.75vw', '93.75vw']
: ['91.11vw', '91.11vw', '91.11vw', '91.11vw']
}
childClassName="flex flex-col justify-stretch h-full"
controlsPosition={'bottom'}
/>
+80 -44
View File
@@ -1,25 +1,32 @@
import { motion, useInView, useMotionValue, useSpring } from 'framer-motion';
import { Title } from './ui/Title';
import { useEffect, useRef } from 'react';
import { IStatisticsItem } from '../types/IStatisticsItem';
import { statistics } from '../consts/statistics';
export function Statistics() {
return (
<div className="space-y-20 border-b border-[#3D425C]">
<div className="lg:space-y-20 sm:space-y-10 border-b border-[#3D425C]">
<Title>
За 15 лет работы cоздали более <br />
<span className="text-gradient"> 250 интерактивных проектов </span>с 3D
графикой
</Title>
<div className="py-24 flex gap-x-4 items-end">
<div className="lg:py-24 sm:py-10 flex lg:gap-x-4 sm:gap-x-0.5 items-end max-sm:hidden">
{statistics.map(stat => (
<Figure key={stat.title} {...stat} />
))}
</div>
<div className="flex flex-col sm:hidden">
{statistics.map(stat => (
<MobileFigure key={stat.title} {...stat} />
))}
</div>
</div>
);
}
function Figure({ color, percents, columnHeight, title }: StatisticsItem) {
function Figure({ color, percents, size, title }: IStatisticsItem) {
const percentsValue = useMotionValue<number>(0);
const percentsSpringValue = useSpring(percentsValue, {
damping: 100,
@@ -54,9 +61,9 @@ function Figure({ color, percents, columnHeight, title }: StatisticsItem) {
useEffect(() => {
if (inView) {
columnHeightValue.set(columnHeight);
columnHeightValue.set(size);
}
}, [columnHeight, columnHeightValue, inView]);
}, [size, columnHeightValue, inView]);
useEffect(() => {
columnHeightSpringValue.on('change', prev => {
@@ -84,7 +91,7 @@ function Figure({ color, percents, columnHeight, title }: StatisticsItem) {
/>
<p
ref={figureRef}
className="text-[96px] font-medium absolute self-center bottom-6 leading-none"
className="text-[clamp(64px,64px+(100vw-640px)/960*32,96px)] font-medium absolute self-center bottom-6 leading-none"
>
{percents}
</p>
@@ -92,42 +99,71 @@ function Figure({ color, percents, columnHeight, title }: StatisticsItem) {
);
}
interface StatisticsItem {
title: string;
color: string;
percents: number;
columnHeight: number;
}
function MobileFigure({ color, percents, size, title }: IStatisticsItem) {
const percentsValue = useMotionValue<number>(0);
const percentsSpringValue = useSpring(percentsValue, {
damping: 100,
stiffness: 100,
});
const statistics: StatisticsItem[] = [
{
color: '#D375FF',
percents: 15,
title: 'AR',
columnHeight: 224,
},
{
color: '#79FFA6',
percents: 62,
title: 'VR',
columnHeight: 301,
},
{
color: '#9E75FF',
percents: 97,
title: '3D интерактив',
columnHeight: 373,
},
{
color: '#FF7575',
percents: 64,
title: 'Интеактивные макеты',
columnHeight: 301,
},
{
color: '#8F95FF',
percents: 12,
title: 'Мобильные приложения',
columnHeight: 246,
},
];
const columnWidthValue = useMotionValue<number>(0);
const columnWidthSpringValue = useSpring(columnWidthValue, {
damping: 100,
stiffness: 100,
});
const figureRef = useRef<HTMLParagraphElement>(null);
const columnRef = useRef<HTMLDivElement>(null);
const root = useRef<HTMLDivElement>(null);
const inView = useInView(root);
useEffect(() => {
if (inView) {
percentsValue.set(percents);
}
}, [percentsValue, inView, percents]);
useEffect(() => {
percentsSpringValue.on('change', prev => {
if (figureRef.current) {
figureRef.current.textContent = prev.toFixed(0);
}
});
}, [figureRef, percentsSpringValue]);
useEffect(() => {
if (inView) {
columnWidthValue.set(size);
}
}, [size, columnWidthValue, inView]);
useEffect(() => {
columnWidthSpringValue.on('change', prev => {
if (columnRef.current) {
columnRef.current!.style.width = `${prev}px`;
}
});
}, [columnWidthSpringValue, columnRef, percentsSpringValue]);
return (
<motion.div ref={root} className="h-[220px]">
<p className="h4 font-medium" style={{ color }}>
{title}
</p>
<motion.div
ref={columnRef}
className="border-r-[5px] transition-[width]"
style={{
borderColor: color,
background: `linear-gradient(${color}33,#798FFF00)`,
}}
/>
<p
ref={figureRef}
className="text-[64px] font-medium self-center leading-none"
>
{percents}
</p>
</motion.div>
);
}
+149
View File
@@ -0,0 +1,149 @@
export function LogoWithoutText() {
return (
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M16.0068 31.7756C24.7187 31.7756 31.7812 24.6624 31.7812 15.8878C31.7812 14.8132 31.6752 13.7635 31.4733 12.7487H21.9434V19.0483H25.0184C23.7216 22.7909 20.1861 25.476 16.028 25.476C10.7704 25.476 6.50824 21.1832 6.50824 15.8878C6.50824 10.5924 10.7704 6.2996 16.028 6.2996V0H16.0068C7.29484 0 0.232422 7.11322 0.232422 15.8878C0.232422 24.6624 7.29484 31.7756 16.0068 31.7756Z"
fill="#798FFF"
/>
<path
d="M15.2134 0.0192822C8.43584 1.07525 3.24805 6.9655 3.24805 14.0736C3.24805 21.9287 9.58346 28.2965 17.3986 28.2965C25.2137 28.2965 31.5491 21.9287 31.5491 14.0736C31.5491 13.6206 31.528 13.1725 31.4868 12.7302H21.9386V19.0207H25.0156C23.718 22.7579 20.1803 25.4391 16.0196 25.4391C10.7587 25.4391 6.49397 21.1526 6.49397 15.8648C6.49397 10.8645 10.3077 6.7595 15.171 6.32797C15.4506 6.30316 15.7336 6.29048 16.0196 6.29048V0H15.9984C15.7352 0 15.4735 0.0064807 15.2134 0.0192822Z"
fill="#D375FF"
/>
<path
opacity="0.3"
d="M14.1721 6.49428C14.766 6.38081 15.3793 6.32141 16.0065 6.32141V0H15.985C14.7151 0 13.4796 0.146971 12.2949 0.424748L14.1721 6.49428Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M5.85411 3.5923L4.87109 17.8592L6.27619 16.5207C6.26785 16.3561 6.26363 16.1905 6.26363 16.0239C6.26363 10.7371 10.5116 6.44454 15.774 6.38605L9.46338 1.3916C8.15979 1.9647 6.94741 2.70757 5.85411 3.5923Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M0.233036 16.068L7.42135 19.9466C6.85231 18.725 6.53463 17.3632 6.53463 15.9272C6.53463 14.4893 6.85318 13.1257 7.42368 11.9028L5.22181 4.40674C2.15036 7.29096 0.232422 11.3855 0.232422 15.9272C0.232422 15.9742 0.232627 16.0211 0.233036 16.068Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M0.232422 15.4311L9.76944 29.7295L20.1824 29.92L16.1202 25.4434C16.0775 25.444 16.0347 25.4443 15.9918 25.4443C10.7435 25.4443 6.48895 21.1903 6.48895 15.9427C6.48895 15.7294 6.49598 15.5177 6.50982 15.3079L0.236835 15.3079C0.235206 15.3489 0.233735 15.39 0.232422 15.4311Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M7.15389 28.9923L13.2217 25.0028C9.29605 23.7888 6.45123 20.2061 6.45123 15.9752C6.45123 15.4316 6.4982 14.8987 6.58839 14.3801L2.55078 24.3784C3.74294 26.2084 5.31302 27.7812 7.15389 28.9923Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M21.1095 30.9426C19.4907 31.4827 17.7562 31.7755 15.9523 31.7755C12.6205 31.7755 9.5255 30.7765 6.95898 29.0657L13.0341 25.0493C13.9614 25.3396 14.9491 25.4962 15.9739 25.4962C16.0118 25.4962 16.0495 25.496 16.0872 25.4956L21.1095 30.9426Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M19.4856 31.3881C18.3496 31.6417 17.1678 31.7755 15.9543 31.7755C15.4285 31.7755 14.9087 31.7504 14.396 31.7013L12.9902 25.0493C13.18 25.1104 13.3724 25.1658 13.5672 25.2154L19.4856 31.3881Z"
fill="black"
fill-opacity="0.4"
/>
<path
opacity="0.3"
d="M22.0371 15.3079L31.5481 13.0601C31.5306 12.9586 31.5123 12.8574 31.493 12.7566H22.0371V15.3079Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M24.0147 19.0189L31.5486 12.767C31.5479 12.7636 31.5472 12.7601 31.5465 12.7566L22.2695 19.0189H24.0147Z"
fill="black"
fill-opacity="0.4"
/>
<path
opacity="0.3"
d="M28.4374 12.7566L21.5742 30.6159C24.2777 29.583 26.6241 27.8259 28.3767 25.5816L29.4614 12.7566H28.4374Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M31.4792 12.7566L21.5742 30.6159C27.5403 28.3562 31.7812 22.5945 31.7812 15.8436C31.7812 14.7871 31.6773 13.7549 31.4792 12.7566Z"
fill="black"
fill-opacity="0.4"
/>
<path d="M25.2917 0H31.5481V6.26234H25.2917V0Z" fill="#798FFF" />
<path
d="M31.5481 6.26234H25.2917L22.0371 9.50949H28.0618L31.5481 6.26234Z"
fill="#798FFF"
/>
<path
d="M25.2917 6.26234V0L22.0371 3.47908V9.50949L25.2917 6.26234Z"
fill="#798FFF"
/>
<path
opacity="0.3"
d="M31.5486 5.39675V6.27041L28.1019 9.50937H27.373V5.33447L31.5486 5.39675Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M22.0371 9.50942V3.38461L26.4051 3.01514L27.8365 3.39351L22.0371 9.50942Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M24.8196 0.695801L22.0371 3.56156V9.50947H25.7487L24.8196 0.695801Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M22.2022 3.23811L22.0371 3.41586V9.50945L25.5313 6.14701L27.1669 6.08275L30.8522 6.70395L30.5017 6.17914L26.0836 1.3916L22.2022 3.23811Z"
fill="#D375FF"
/>
<path
opacity="0.3"
d="M25.5173 0H25.2871L24.3574 0.99057L25.4543 1.62357L25.5173 0Z"
fill="black"
fill-opacity="0.6"
/>
<path
opacity="0.3"
d="M30.3896 7.46476L28.2194 9.50937H27.8379L28.1787 5.42173L29.8668 5.10254L30.3896 7.46476Z"
fill="black"
fill-opacity="0.6"
/>
<path
d="M25.2852 6.26234H31.5485V0H25.2852V6.26234Z"
fill="url(#paint0_linear_544_1013)"
/>
<defs>
<linearGradient
id="paint0_linear_544_1013"
x1="28.8491"
y1="0"
x2="28.8491"
y2="6.26234"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#D375FF" />
<stop offset="1" stop-color="#798FFF" />
</linearGradient>
</defs>
</svg>
);
}
+34
View File
@@ -0,0 +1,34 @@
import { IStatisticsItem } from '../types/IStatisticsItem';
export const statistics: IStatisticsItem[] = [
{
color: '#D375FF',
percents: 15,
title: 'AR',
columnWidth: 224,
},
{
color: '#79FFA6',
percents: 62,
title: 'VR',
columnWidth: 301,
},
{
color: '#9E75FF',
percents: 97,
title: '3D интерактив',
columnWidth: 373,
},
{
color: '#FF7575',
percents: 64,
title: 'Интеактивные макеты',
columnWidth: 301,
},
{
color: '#8F95FF',
percents: 12,
title: 'Мобильные приложения',
columnWidth: 246,
},
];
+1 -1
View File
@@ -8,7 +8,7 @@ import { Devices } from '../components/Devices';
export function MainPage() {
return (
<div className="lg:space-y-[180px] sm:space-y-[140px]">
<div className="lg:space-y-[180px] sm:space-y-[140px] space-y-20">
<Motivation />
<Promotion />
<Projects />
+6
View File
@@ -0,0 +1,6 @@
export interface IStatisticsItem {
title: string;
color: string;
percents: number;
size: number;
}
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
theme: {
extend: {
animation: {
'infinite-scroll': 'infinite-scroll 25s linear infinite',
'infinite-scroll': 'infinite-scroll 30s linear infinite',
},
keyframes: {
'infinite-scroll': {