fixes
|
Before Width: | Height: | Size: 641 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 383 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 3.9 MiB After Width: | Height: | Size: 432 KiB |
|
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 603 KiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 76 KiB |
@@ -28,16 +28,16 @@ export function Header() {
|
||||
const width = useWindowWidth();
|
||||
|
||||
return (
|
||||
<header className="w-full">
|
||||
<nav className="flex justify-between border-b border-[#3D425C] lg:pl-10 pl-4 lg:max-h-[72px] min-h-16">
|
||||
<header className="sticky top-0 z-[90] w-full bg-[#14161F]">
|
||||
<nav className="flex justify-between border-b border-[#3D425C] lg:pl-10 pl-4 xl:max-h-[72px] max-h-16">
|
||||
<Link to={'/'} className="flex items-center outline-none">
|
||||
<LogoIcon className="lg:hidden" />
|
||||
{width >= 1024 && <LogoWithTextIcon className="w-[104px]" />}
|
||||
</Link>
|
||||
<div className="flex mx-auto">
|
||||
<AnchorLink route="#products">Типы тренажеров</AnchorLink>
|
||||
<AnchorLink route="#trainings">Варианты комплектации</AnchorLink>
|
||||
<AnchorLink route="#projects">Проекты</AnchorLink>
|
||||
<AnchorLink route="#trainings">Варианты комплектации</AnchorLink>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setModal(<ModalWithForm />)}
|
||||
@@ -49,7 +49,7 @@ export function Header() {
|
||||
<button
|
||||
ref={menuBtnRef}
|
||||
onClick={() => setMenuOpen(prev => !prev)}
|
||||
className="px-6 py-5 xl:hidden border-[#3D425C] max-sm:border-l outline-none"
|
||||
className="p-5 xl:hidden border-[#3D425C] max-sm:border-l outline-none"
|
||||
>
|
||||
{!menuOpen ? <BurgerIcon /> : <CloseIcon />}
|
||||
</button>
|
||||
@@ -70,8 +70,8 @@ export function Header() {
|
||||
>
|
||||
<div>
|
||||
<BurgerAnchor route="#products">Типы тренажеров</BurgerAnchor>
|
||||
<BurgerAnchor route="#trainings">Варианты комплектации</BurgerAnchor>
|
||||
<BurgerAnchor route="#projects">Проекты</BurgerAnchor>
|
||||
<BurgerAnchor route="#trainings">Варианты комплектации</BurgerAnchor>
|
||||
</div>
|
||||
<div className="grid grid-cols-[2fr_1fr_1fr] sm:grid-cols-2">
|
||||
<Button
|
||||
|
||||
@@ -16,19 +16,12 @@ export function VideoModal({ link }: VideoModalProps) {
|
||||
<div className="w-screen h-screen absolute z-[110] top-0 left-0 overflow-hidden flex justify-center items-center">
|
||||
<div className="flex items-center justify-center w-full aspect-video">
|
||||
<button
|
||||
className="p-4 rounded-full border absolute top-4 right-4 z-[99] cursor-pointer"
|
||||
className="p-4 rounded-full border absolute top-4 right-4 z-[100] cursor-pointer"
|
||||
onClick={handleOnCloseClick}
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
<video
|
||||
src={link}
|
||||
className="h-full aspect-videop"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
/>
|
||||
<video src={link} className="h-full" autoPlay muted loop playsInline />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ export function Ellipse() {
|
||||
<div
|
||||
ref={ref}
|
||||
style={{ top: mousePos[1], left: mousePos[0] }}
|
||||
className="fixed -z-[9] bg-[url('/Ellipse.png')] bg-transparent bg-cover bg-no-repeat bg-center -translate-y-[50%] -translate-x-[50%] aspect-[348.75/262.77] w-[21.75vw]"
|
||||
className="fixed -z-[9] -translate-y-[50%] -translate-x-[50%] max-w-[10vw] w-full aspect-[348.85/262.77] [-webkit-filter:blur(25px)] [box-shadow:3px_3px_#5545AC,3px_3px_#5545AC] bg-[#5545AC] rounded-full"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export function ModalContainer() {
|
||||
|
||||
return (
|
||||
modal && (
|
||||
<div className="fixed top-0 left-0 z-50 flex items-center justify-center w-full h-full transition-opacity bg-black bg-opacity-90 [backdrop-filter:blur(10px);]">
|
||||
<div className="fixed top-0 left-0 z-[100] flex items-center justify-center w-full h-full transition-opacity bg-black bg-opacity-90 [backdrop-filter:blur(10px);]">
|
||||
<div onClick={e => e.stopPropagation()} className="cursor-default">
|
||||
{modal}
|
||||
</div>
|
||||
|
||||
@@ -189,7 +189,6 @@ export function ModalWithForm() {
|
||||
id="description"
|
||||
placeholder="Опишите вашу задачу"
|
||||
value={description}
|
||||
rows={1}
|
||||
onChange={e => setDescription(e.target.value)}
|
||||
className="bg-transparent border-b py-4 focus:border-white max-h-[300px] h-auto rounded-none border-[#3D425C] resize-none outline-none transition-all w-full placeholder:h4 placeholder:font-medium placeholder:select-none"
|
||||
/>
|
||||
@@ -199,7 +198,7 @@ export function ModalWithForm() {
|
||||
<Button
|
||||
width="full"
|
||||
disabled={isLoading}
|
||||
className="px-6 py-5 mt-12"
|
||||
className="px-6 py-3 mt-12"
|
||||
icon={
|
||||
isLoading ? (
|
||||
<LoaderIcon className="relative w-6 h-6 animate-spin" />
|
||||
|
||||
@@ -8,7 +8,7 @@ export const ForTeachingTab = forwardRef<HTMLDivElement>((_, ref) => (
|
||||
itemScope
|
||||
itemType="https://schema.org/TrainingsForEducation"
|
||||
ref={ref}
|
||||
className="overflow-hidden lg:ml-[129px] lg:h-[70vh] sm:h-[80vh] lg:min-w-[calc(100vw-129px)] h-[100vh] min-w-[100vw] sm:sticky -z-10 lg:top-[30vh] sm:top-[20vh] top-0 lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 lg:border-l bg-[#14161F] border-t border-[#3D425C]"
|
||||
className="overflow-hidden lg:ml-[129px] lg:h-[70vh] sm:h-[80vh] lg:min-w-[calc(100vw-129px)] h-[100vh] min-w-[100vw] sm:sticky lg:top-[30vh] sm:top-[20vh] top-0 lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 lg:border-l bg-[#14161F] border-t border-[#3D425C]"
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<h2 className="font-medium h2">
|
||||
|
||||
@@ -42,7 +42,7 @@ export const IndustrialTab = forwardRef<HTMLDivElement, { sticked: boolean }>(
|
||||
itemScope
|
||||
itemType="https://schema.org/IndustrialTrainings"
|
||||
ref={ref}
|
||||
className="sm:sticky top-0 min-h-[100vh] min-w-[100vw] lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 border-t border-[#3D425C] bg-[#14161F] -z-30 max-sm:flex flex-col items-center gap-y-4"
|
||||
className="sm:sticky top-0 min-h-[100vh] min-w-[100vw] lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 border-t border-[#3D425C] bg-[#14161F] max-sm:flex flex-col items-center gap-y-4"
|
||||
>
|
||||
<div className="space-y-6 lg:space-y-14 sm:space-y-10">
|
||||
<div
|
||||
|
||||
@@ -15,7 +15,7 @@ export const SimulatorsTab = forwardRef<HTMLDivElement, { sticked: boolean }>(
|
||||
itemProp="simulators"
|
||||
itemType="http://schema.org/Simulators"
|
||||
ref={ref}
|
||||
className="lg:ml-[65px] lg:h-[85dvh] lg:min-w-[calc(100vw-65px)] sm:h-[90vh] min-w-[100vw] sm:sticky -z-20 lg:top-[15vh] sm:top-[10vh] top-0 bg-[#14161F] lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 sm:space-y-10 space-y-6 lg:border-l border-t border-[#3D425C]"
|
||||
className="lg:ml-[65px] lg:h-[85dvh] lg:min-w-[calc(100vw-65px)] sm:h-[90vh] min-w-[100vw] sm:sticky lg:top-[15vh] sm:top-[10vh] top-0 bg-[#14161F] lg:px-10 lg:pt-10 sm:px-6 sm:pt-6 px-4 pt-4 sm:space-y-10 space-y-6 lg:border-l border-t border-[#3D425C]"
|
||||
>
|
||||
<div
|
||||
className={
|
||||
|
||||
@@ -64,7 +64,7 @@ export function Products() {
|
||||
id="products"
|
||||
itemScope
|
||||
itemType="http://schema.org/Products"
|
||||
className="lg:pt-[100px] sm:max-lg:pt-[70px] max-sm:py-14 lg:-mx-10 sm:-mx-6 -mx-4 sm:space-y-[500px] space-y-10 overflow-clip"
|
||||
className="xl:pt-[72px] pt-16 max-sm:py-14 lg:-mx-10 sm:-mx-6 -mx-4 sm:space-y-[500px] space-y-10 overflow-clip"
|
||||
>
|
||||
<IndustrialTab ref={ref1} sticked={stiked1} />
|
||||
<SimulatorsTab ref={ref2} sticked={stiked2} />
|
||||
|
||||
@@ -1,54 +1,50 @@
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { IProject, Media } from '../../types/IProject';
|
||||
|
||||
export const Project = forwardRef<HTMLDivElement, IProject<Media>>(
|
||||
({ src, title, tags, media, year }, ref) => {
|
||||
const [buffering, setBuffering] = useState(true);
|
||||
export function Project({ src, title, tags, media, year }: IProject<Media>) {
|
||||
const ref = useRef<HTMLVideoElement>(null);
|
||||
|
||||
return (
|
||||
<div
|
||||
itemProp="project"
|
||||
itemScope
|
||||
itemType={`https://schema.org/${title}`}
|
||||
ref={ref}
|
||||
className="relative flex flex-col aspect-square"
|
||||
>
|
||||
{media === Media.img ? (
|
||||
<div
|
||||
className="flex-1 bg-center bg-no-repeat bg-cover"
|
||||
style={{ backgroundImage: `url(${src})` }}
|
||||
return (
|
||||
<div
|
||||
itemProp="project"
|
||||
itemScope
|
||||
itemType={`https://schema.org/${title}`}
|
||||
className="relative flex flex-col aspect-square"
|
||||
>
|
||||
{media === Media.img ? (
|
||||
<div className="flex flex-1">
|
||||
<img
|
||||
className="object-cover object-center pointer-events-none"
|
||||
src={src}
|
||||
alt={title}
|
||||
/>
|
||||
) : (
|
||||
<div className="relative flex-1 overflow-hidden">
|
||||
<video
|
||||
src={src}
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
autoPlay
|
||||
className="object-cover object-center w-full h-full -mb-px"
|
||||
onPlaying={() => setBuffering(false)}
|
||||
onWaiting={() => setBuffering(true)}
|
||||
/>
|
||||
{buffering && <div className="absolute" />}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col justify-between gap-2 my-4">
|
||||
<div className="flex justify-between">
|
||||
<h4 className="text-xl font-medium">{title}</h4>
|
||||
<p className="text-xl font-medium">{year}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{tags.map(tag => (
|
||||
<p key={tag} className="font-medium m-caption text-[#737AA1]">
|
||||
{tag}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-1">
|
||||
<video
|
||||
ref={ref}
|
||||
src={src}
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
autoPlay
|
||||
className="flex-1 object-cover object-center w-full h-full -mb-px"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col justify-between gap-2 my-4">
|
||||
<div className="flex justify-between">
|
||||
<h4 className="text-xl font-medium">{title}</h4>
|
||||
<p className="text-xl font-medium">{year}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{tags.map(tag => (
|
||||
<p key={tag} className="font-medium m-caption text-[#737AA1]">
|
||||
{tag}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Project.displayName = 'Project';
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export function MainPage() {
|
||||
const width = useWindowWidth();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{width >= 1024 && <Ellipse />}
|
||||
<Motivation />
|
||||
<Showreel />
|
||||
@@ -27,6 +27,6 @@ export function MainPage() {
|
||||
<Distance />
|
||||
<MultiUser />
|
||||
<Trainings />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,14 +31,14 @@ export function SliderWithScaling<T extends { title: string }>({
|
||||
const [transiting, setTransiting] = useState(false);
|
||||
const [sliderOffset, setSliderOffset] = useState(baseoffset);
|
||||
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
// const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const controlsRef = useRef<{ left: () => void; right: () => void }>({
|
||||
left: () => {},
|
||||
right: () => {},
|
||||
});
|
||||
|
||||
const [order, dispatch] = useReducer(
|
||||
(state: typeof slides, action: 'prev' | 'next' | 2) => {
|
||||
(state: typeof slides, action: 'prev' | 'next') => {
|
||||
setTransiting(true);
|
||||
switch (action) {
|
||||
case 'prev':
|
||||
@@ -49,10 +49,6 @@ export function SliderWithScaling<T extends { title: string }>({
|
||||
setSlide(slide => (slide + 1) % slides.length);
|
||||
setSliderOffset(baseoffset);
|
||||
return [...state.slice(1), state[4]];
|
||||
case 2:
|
||||
setSlide(slide => (slide + 2) % slides.length);
|
||||
setSliderOffset(0);
|
||||
return [...state.slice(2), state[4], state[5]];
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -104,19 +100,10 @@ export function SliderWithScaling<T extends { title: string }>({
|
||||
transform: `translateX(${sliderOffset}px)`,
|
||||
transitionDuration: `${sliderOffset !== baseoffset && sliderOffset !== 3 * baseoffset && sliderOffset !== 0 ? 1 : 0}s`,
|
||||
}}
|
||||
ref={sliderRef}
|
||||
// ref={sliderRef}
|
||||
>
|
||||
{order.map((currentSlide, index) => (
|
||||
<motion.div
|
||||
onClick={
|
||||
width >= 1024
|
||||
? () => {
|
||||
if (index === 1) controlsRef.current.left();
|
||||
if (index === 3) controlsRef.current.right();
|
||||
if (index === 4) dispatch(2);
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
key={
|
||||
currentSlide.title +
|
||||
(index < 2 ? '123' : index > slides.length ? '456' : '')
|
||||
|
||||