This commit is contained in:
2026-04-16 13:12:36 +05:00
13 changed files with 415 additions and 33 deletions
Binary file not shown.
+5
View File
@@ -2,12 +2,17 @@ import { Footer } from "@/components/Layout/Footer";
import { LanguageSwitcher } from "@/components/Layout/LanguageSwitcher";
import { LocaleSync } from "@/components/Layout/LocaleSync";
import StreamDemo from "@/features/stream-demo/StreamDemo";
import Header from "@/components/Layout/Header";
export default function App() {
return (
<div className="flex min-h-dvh flex-col">
<<<<<<< HEAD
<LocaleSync />
<LanguageSwitcher />
=======
<Header />
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
{/* Без overflow-clip: иначе flex-1 + clip часто даёт пустой/обрезанный экран */}
<div className="min-h-0 flex-1 px-[10px] pb-8 pt-14 md:max-lg:pt-6 md:px-4 md:pt-4 lg:px-[1.389vw] lg:pt-8">
<StreamDemo />
+5
View File
@@ -6,6 +6,11 @@ import { useModalStore } from "@/stores/useModalStore";
import FeedbackModal from "@/components/modals/FeedbackFormModal";
import { LeadForm } from "@/features/lead-form/LeadForm";
<<<<<<< HEAD
=======
const DEFAULT_STREAM_DEMO_PRODUCTS = ["Удаленная демонстрация"] as Product[];
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
export function Feedback() {
useAddReferer();
const { t } = useTranslation();
+9
View File
@@ -93,7 +93,16 @@ export function Footer() {
className=" lg:hidden md:size-[6.25vw] size-[13.333vw] max-md:absolute max-md:right-0 max-md:bottom-6"
/>
</div>
<<<<<<< HEAD
) : null}
=======
<img
src="/img/components/header/Sk.svg"
alt="Сколково"
className=" lg:size-[3.333vw] lg:mt-[2.292vw] md:size-[6.25vw] size-[13.333vw] max-md:absolute max-md:right-0 max-md:bottom-6"
/>
</div>
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
<div className="lg:gap-x-[0.833vw] gap-y-2 flex max-lg:flex-col">
<a
+11
View File
@@ -0,0 +1,11 @@
import LanguageSwitchButton from "./LanguageSwitchButton";
export default function Header() {
return (
<header
className={`lg:mt-[1.389vw] md:mt-[2.083vw] mt-[2.778vw] relative flex justify-end items-center lg:px-[1.389vw] md:px-[2.083vw] px-[2.778vw]`}
>
<LanguageSwitchButton />
</header>
);
}
@@ -0,0 +1,27 @@
import { useState } from "react";
export default function LanguageSwitchButton({
className,
}: {
className?: string;
}) {
const [locale, setLocale] = useState<"ru" | "en">("ru");
function handleClick() {
return setLocale(locale === "ru" ? "en" : "ru");
}
return (
<button
className={`btnm bg-[#37393B99] active:bg-[#37393B80]
lg:px-[1.667vw] lg:py-[1.181vw] lg:rounded-[0.833vw]
md:px-[2.604vw] md:py-[1.302vw] md:rounded-[1.563vw]
px-[5.556vw] py-[2.778vw] rounded-[3.333vw]
${className}
`}
onClick={handleClick}
>
{locale === "ru" ? "RU" : "EN"}
</button>
);
}
+1 -1
View File
@@ -17,7 +17,7 @@ export function ModalContainer() {
}, [setModal]);
const jsx = modal ? (
<div className="fixed left-0 z-[20] w-full h-full flex justify-center items-start transition-opacity">
<div className="fixed inset-0 z-[20] flex justify-center items-start transition-opacity">
<div className="absolute [backdrop-filter:blur(16px)] bg-[#0F101199] w-full h-full z-[1]" />
{modal}
</div>
+221
View File
@@ -0,0 +1,221 @@
function LogoHorIcon() {
return (
<svg viewBox="0 0 192 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#a)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M24.214 48c13.38 0 24.215-10.738 24.215-24 0-1.618-.166-3.21-.47-4.745H33.332v9.518h4.718c-1.992 5.65-7.416 9.71-13.795 9.71-8.067 0-14.612-6.488-14.612-14.483S16.19 9.518 24.256 9.518V0h-.042C10.848 0 0 10.752 0 24c0 13.262 10.848 24 24.214 24"
fill="#798FFF"
/>
<path
d="M22.996.027C12.591 1.618 4.635 10.52 4.635 21.257c0 11.863 9.727 21.49 21.724 21.49s21.723-9.613 21.723-21.49c0-.686-.027-1.358-.097-2.03H33.318v9.504h4.719c-1.993 5.65-7.417 9.696-13.81 9.696-8.08 0-14.625-6.473-14.625-14.468 0-7.557 5.853-13.756 13.325-14.4.429-.041.858-.055 1.3-.055V0H24.2c-.401 0-.802.014-1.204.027"
fill="#D375FF"
/>
<path
opacity={0.3}
d="M21.406 9.806a16 16 0 0 1 2.823-.26V0H24.2c-1.95 0-3.846.22-5.659.645z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="M8.635 5.43 7.126 26.977l2.159-2.016c-.014-.247-.014-.494-.014-.755 0-7.981 6.517-14.468 14.598-14.564l-9.686-7.543a24 24 0 0 0-5.548 3.333"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="m0 24.274 11.028 5.856a14.2 14.2 0 0 1-1.356-6.075c0-2.167.484-4.238 1.37-6.076L7.666 6.651C2.947 11.012 0 17.198 0 24.055z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="m0 23.315 14.64 21.6 15.98.287-6.24-6.76h-.193c-8.053 0-14.584-6.433-14.584-14.36 0-.329.014-.644.027-.96H0z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="m10.627 43.79 9.312-6.02c-6.032-1.838-10.391-7.242-10.391-13.633 0-.823.07-1.632.208-2.413l-6.2 15.099a24.3 24.3 0 0 0 7.071 6.967"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="M32.048 46.738A25.6 25.6 0 0 1 24.133 48c-5.12 0-9.866-1.509-13.81-4.087l9.327-6.061c1.425.438 2.933.672 4.51.672h.18z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="M29.556 47.41c-1.744.384-3.556.59-5.424.59-.803 0-1.605-.041-2.394-.11L19.58 37.837c.29.096.58.179.885.247z"
fill="#000"
fillOpacity={0.4}
/>
<path
opacity={0.3}
d="m33.47 23.122 14.598-3.4-.083-.453H33.47z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="m36.517 28.731 11.567-9.449v-.013L33.846 28.73z"
fill="#000"
fillOpacity={0.4}
/>
<path
opacity={0.3}
d="m43.295 19.269-10.53 26.976a24.23 24.23 0 0 0 10.447-7.612l1.66-19.378h-1.577z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="M47.958 19.269 32.765 46.245c9.146-3.415 15.663-12.11 15.663-22.314 0-1.59-.166-3.154-.47-4.662"
fill="#000"
fillOpacity={0.4}
/>
<path
d="M38.467 0h9.603v9.463h-9.603zm9.601 9.463h-9.603l-4.995 4.91h9.243z"
fill="#798FFF"
/>
<path d="M38.465 9.463V0L33.47 5.253v9.106z" fill="#798FFF" />
<path
opacity={0.3}
d="M48.068 8.146v1.317l-5.286 4.896h-1.12V8.05zM33.47 14.359V5.116l6.711-.563 2.2.576z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="M37.746 1.056 33.47 5.389v8.983h5.7z"
fill="#000"
fillOpacity={0.6}
/>
<path
opacity={0.3}
d="m33.72 4.896-.25.275v9.202l5.369-5.074 2.504-.096 5.66.932-.54-.795-6.78-7.228z"
fill="#D375FF"
/>
<path
opacity={0.3}
d="M38.812 0h-.346L37.04 1.495l1.688.96zm7.487 11.273-3.334 3.086h-.582l.512-6.171 2.588-.48z"
fill="#000"
fillOpacity={0.6}
/>
<path d="M38.451 9.463h9.617V0H38.45z" fill="url(#b)" />
<path
d="M122.76 9.463h-7.223v4.882h6.642v3.62h-6.642v7.708h-4.621V5.815h11.859v3.648z"
fill="url(#c)"
/>
<path
d="M76.24 24.343a15 15 0 0 1-7.459 1.659 11.3 11.3 0 0 1-4.178-.59 10.5 10.5 0 0 1-3.584-2.07 10 10 0 0 1-2.255-3.374 9.3 9.3 0 0 1-.637-3.923 9.8 9.8 0 0 1 .72-4.114 10.5 10.5 0 0 1 2.393-3.524 11 11 0 0 1 3.806-2.277 11.8 11.8 0 0 1 4.483-.672c1.965-.041 3.916.26 5.77.878v4.183a11.94 11.94 0 0 0-5.77-1.33 6.4 6.4 0 0 0-2.546.424 6.1 6.1 0 0 0-2.117 1.372c-1.26 1.33-1.91 3.058-1.813 4.827-.11 1.715.457 3.388 1.619 4.732a5.7 5.7 0 0 0 1.965 1.275c.747.288 1.55.425 2.366.398.9.027 1.813-.124 2.643-.453v-3.84H67.55v-3.58h8.648z"
fill="url(#d)"
/>
<path
d="m104.275 17.829-2.2-6.652a9 9 0 0 1-.346-1.783h-.11a7.4 7.4 0 0 1-.346 1.728l-2.242 6.734zm7.542 7.844h-5.009l-1.439-4.416h-7.293l-1.438 4.416h-5.023l7.472-19.858h5.479z"
fill="url(#e)"
/>
<path
d="M82.094 9.161v5.527h1.992c.443.014.885-.041 1.287-.192.415-.137.788-.37 1.107-.645.29-.274.525-.603.691-.96.153-.356.236-.74.222-1.124 0-1.742-1.066-2.66-3.21-2.66zm12.591 16.512h-5.3l-3.196-5.101c-.249-.384-.484-.727-.692-1.043a4.5 4.5 0 0 0-.664-.782 2.9 2.9 0 0 0-.706-.507 1.9 1.9 0 0 0-.774-.164h-1.26v7.597h-4.607V5.815h7.306c4.995 0 7.471 1.81 7.471 5.403a5.1 5.1 0 0 1-.332 1.92 5.3 5.3 0 0 1-.927 1.591c-.401.466-.9.878-1.439 1.207a7 7 0 0 1-1.895.796c.318.096.608.246.885.438.305.22.581.467.83.727.277.288.526.576.761.892.25.315.457.644.665.946z"
fill="url(#f)"
/>
<path
d="M135.6 9.463h-7.223v4.882h6.642v3.62h-6.642v7.708h-4.635V5.815H135.6z"
fill="url(#g)"
/>
<path
d="M62.942 40.784q-1.494 0-2.59-.662-1.086-.662-1.691-1.862t-.605-2.816q0-1.672.596-2.892.594-1.218 1.672-1.88 1.087-.662 2.561-.662 1.512 0 2.58.7 1.067.69 1.616 1.984.548 1.295.5 3.09h-1.417v-.49q-.038-1.986-.86-2.997-.812-1.01-2.381-1.01-1.644 0-2.523 1.067-.87 1.068-.87 3.043 0 1.928.87 2.996.879 1.058 2.485 1.058 1.096 0 1.909-.5.822-.512 1.295-1.465l1.294.5q-.604 1.334-1.786 2.07-1.17.727-2.655.727m-3.903-5v-1.162h7.796v1.163zm13.881 4.99q-1.796 0-2.958-.775-1.152-.775-1.417-2.155l1.417-.236q.228.87 1.03 1.39.813.51 2.004.51 1.162 0 1.833-.482.671-.492.671-1.333 0-.472-.217-.765-.208-.302-.86-.558-.653-.255-1.947-.604-1.389-.379-2.173-.756-.785-.378-1.115-.87-.331-.5-.331-1.219 0-.87.491-1.521.492-.661 1.361-1.02.87-.37 2.022-.37 1.154 0 2.06.378.917.37 1.475 1.04.557.67.661 1.56l-1.417.254a2.04 2.04 0 0 0-.898-1.417q-.747-.53-1.9-.548-1.086-.029-1.767.416-.68.435-.68 1.162 0 .406.245.7.246.282.889.538.651.255 1.852.557 1.409.36 2.211.757.804.396 1.144.935.34.538.34 1.333 0 1.444-1.077 2.277-1.068.822-2.949.822m11.111-.274q-.86.18-1.7.142a3.8 3.8 0 0 1-1.494-.36 2.15 2.15 0 0 1-.992-1.001 2.95 2.95 0 0 1-.302-1.144q-.02-.585-.02-1.332V27.46h1.38v9.29q0 .642.01 1.077.02.424.198.756.34.633 1.078.756.746.122 1.842-.057zm-6.69-9.015v-1.191h6.69v1.19zm11.054 9.298q-1.152 0-1.937-.415-.775-.416-1.162-1.106a3 3 0 0 1-.388-1.503q0-.83.33-1.417.341-.595.918-.973.585-.379 1.35-.577a20 20 0 0 1 1.711-.33q.945-.151 1.843-.256a59 59 0 0 0 1.588-.217l-.492.302q.03-1.512-.586-2.24-.614-.727-2.135-.727-1.05 0-1.777.473-.719.471-1.011 1.493l-1.351-.397q.35-1.371 1.408-2.127t2.75-.756q1.398 0 2.372.53.983.519 1.389 1.512.19.444.245.992.057.548.057 1.115V40.5H92.28v-2.56l.36.15q-.52 1.314-1.617 2.004-1.095.69-2.627.69m.16-1.2q.975 0 1.702-.35a3.1 3.1 0 0 0 1.172-.954q.444-.615.576-1.38a5 5 0 0 0 .123-1.077q.01-.596.01-.888l.529.274q-.71.094-1.54.189-.823.095-1.626.217-.794.123-1.437.293-.435.123-.84.35-.407.217-.672.586-.255.368-.255.916 0 .445.218.86.226.417.718.69.501.274 1.323.274m12.412.917q-.86.18-1.701.142a3.8 3.8 0 0 1-1.493-.36 2.15 2.15 0 0 1-.992-1.001 2.9 2.9 0 0 1-.303-1.144q-.018-.585-.019-1.332V27.46h1.38v9.29q0 .642.01 1.077.018.424.198.756.34.633 1.077.756.747.122 1.843-.057zm-6.69-9.015v-1.191h6.69v1.19zm12.083 9.298q-1.493 0-2.589-.661-1.087-.662-1.692-1.862t-.605-2.816q0-1.672.596-2.892.595-1.218 1.672-1.88 1.088-.662 2.561-.662 1.512 0 2.58.7 1.068.69 1.616 1.984.549 1.295.501 3.09h-1.417v-.49q-.038-1.986-.86-2.997-.813-1.01-2.382-1.01-1.644 0-2.523 1.067-.87 1.068-.869 3.043 0 1.928.869 2.996.879 1.058 2.485 1.058 1.097 0 1.909-.5.822-.512 1.295-1.465l1.295.5q-.606 1.334-1.786 2.07-1.173.727-2.656.727m-3.903-4.998v-1.163h7.797v1.163z"
fill="url(#h)"
/>
</g>
<defs>
<linearGradient
id="b"
x1={43.264}
y1={0}
x2={43.264}
y2={9.46}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="c"
x1={116.828}
y1={5.445}
x2={116.828}
y2={26.017}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="d"
x1={67.176}
y1={5.445}
x2={67.176}
y2={26.016}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="e"
x1={101.711}
y1={5.445}
x2={101.711}
y2={26.017}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="f"
x1={86.08}
y1={5.445}
x2={86.08}
y2={26.017}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="g"
x1={129.675}
y1={5.445}
x2={129.675}
y2={26.017}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<linearGradient
id="h"
x1={88.71}
y1={20.1}
x2={88.71}
y2={46.5}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D375FF" />
<stop offset={1} stopColor="#798FFF" />
</linearGradient>
<clipPath id="a">
<path fill="#fff" d="M0 0h192v48H0z" />
</clipPath>
</defs>
</svg>
);
}
export default LogoHorIcon;
+7 -2
View File
@@ -17,6 +17,11 @@ import type { LeadFormValues } from "./types";
export type { LeadFormValues } from "./types";
<<<<<<< HEAD
=======
const GENERIC_SUBMIT_ERROR = "Не удалось отправить заявку. Попробуйте позже.";
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
export function LeadForm({
defaultProducts,
idPrefix = "",
@@ -115,7 +120,7 @@ export function LeadForm({
/>
<div className="bottom-0 absolute w-full border-b border-[#37393B] peer-focus:border-white -mb-2" />
</div>
<div className="md:flex items-stretch lg:gap-[0.833vw] gap-3">
<div className="md:flex items-stretch lg:gap-[0.833vw] gap-3 max-md:translate-y-2">
<Button
type="submit"
disabled={formState.isSubmitting}
@@ -128,7 +133,7 @@ export function LeadForm({
<a
target="_blank"
rel="noopener noreferrer"
href="/privacy-policy"
href="https://graff.estate/privacy-policy"
className="underline"
>
{t("leadForm.consentLinkData")}
+102 -25
View File
@@ -1,3 +1,4 @@
<<<<<<< HEAD
import { useState } from "react";
import { useTranslation } from "react-i18next";
import BR from "@/components/Layout/LineBreak";
@@ -5,20 +6,27 @@ import {
REMOTE_DEMO_TAG,
useGetProjectsQuery,
} from "@/queries/getProjects";
=======
import { useRef, useState, type MouseEvent as ReactMouseEvent } from "react";
import { REMOTE_DEMO_TAG, useGetProjectsQuery } from "@/queries/getProjects";
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
import { StreamingProject } from "./StreamingProject";
import { useSwipeable } from "react-swipeable";
import { useMediaQueries } from "@/hooks/useMediaQueries";
export default function AvailableDemos() {
<<<<<<< HEAD
const { t } = useTranslation();
const { isMd, isLg } = useMediaQueries();
=======
const { isMd } = useMediaQueries();
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
const { data: streamingProjects } = useGetProjectsQuery(REMOTE_DEMO_TAG);
const [current, setCurrent] = useState(0);
const projects = streamingProjects ?? [];
// Свайп на мобилке
const slideCount = Math.min(projects.length + 1, 4);
const handlers = useSwipeable({
onSwipedLeft: () =>
setCurrent((prev) => (prev + 1) % Math.max(slideCount, 1)),
@@ -32,18 +40,71 @@ export default function AvailableDemos() {
touchEventOptions: { passive: false },
});
// Скролл на десктопе
const sliderRef = useRef<HTMLDivElement>(null);
function onSliderMouseDown(e: ReactMouseEvent<HTMLDivElement>) {
const root = sliderRef.current;
if (!root) return;
const startX = e.clientX;
const startScrollLeft = root.scrollLeft;
function onMouseMove(ev: MouseEvent) {
if (!root) return;
const dx = ev.clientX - startX;
root.scrollLeft = startScrollLeft - dx;
}
function onMouseUp() {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
}
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
}
return (
<div>
<div className="flex lg:flex-row flex-col lg:mb-[4.444vw] md:mb-[8.333vw] md:gap-[3.125vw]">
<h2 className="line2 max-md:line1 w-full max-md:mb-[5.556vw]">
<<<<<<< HEAD
{t("demos.titleLine1")} <BR lg sm /> {t("demos.titleLine2")}
=======
Доступные <br className="lg:block md:hidden block" /> демонстрации
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
</h2>
{!isLg && !isMd && (
{/* Тиндер на мобилке */}
<div
className="lg:hidden md:hidden grid-cols-4 gap-3 px-5 [scrollbar-width:none] relative max-md:aspect-[340/344] [transform-style:preserve-3d] items-stretch mb-[5.556vw]"
{...handlers}
>
{projects.slice(0, 3).map((project, index, { length }) => (
<StreamingProject
key={project.id}
{...project}
index={index}
current={current}
count={length + 1}
href="/"
/>
))}
<div
className="lg:grid md:flex grid-cols-4 gap-3 px-5 md:-mx-5 md:overflow-auto [scrollbar-width:none] relative max-md:aspect-[340/344] [transform-style:preserve-3d] items-stretch mb-[5.556vw]"
{...handlers}
className={`bg-gradient-to-r from-[#FFFFFF14] to-[#FFFFFF00] [background:linear-gradient(to_right,#FFFFFF14,#FFFFFF00)] p-0.5 lg:rounded-[1.111vw] rounded-2xl flex flex-1 justify-center !duration-500 items-center md:min-w-[300px] group max-md:absolute self-stretch max-md:h-full transition-[scale,transform] will-change-[transform,scale] select-none max-md:w-[calc(100%-40px)] max-md:bg-[#0F101199] max-md:[backdrop-filter:blur(40px)] ${
slideCount - 1 === current
? "max-md:[transform:translateZ(40px)]"
: "max-md:[scale:85%]"
} ${
slideCount - 1 === (current + 1) % slideCount
? "max-md:translate-x-[calc(7.5%+20px)]"
: slideCount - 1 === (current - 1 + slideCount) % slideCount
? "max-md:translate-x-[calc(-7.5%-20px)]"
: ""
}`}
>
<<<<<<< HEAD
{projects.slice(0, 3).map((project, index, { length }) => (
<StreamingProject
key={project.id}
@@ -80,35 +141,51 @@ export default function AvailableDemos() {
{t("demos.ctaButton")}
</a>
</div>
=======
<div className="md:bg-[#0F1011] h-full w-full lg:rounded-[1.111vw] rounded-2xl flex items-center p-6">
<div className="flex flex-col items-center space-y-6">
<p className="heading2 font-medium text-center">
Расскажем и покажем как это работает на&nbsp;созвоне
</p>
<a
href="#contacts"
className="btnm font-medium group-hover:scale-105 duration-500 lg:px-[1.667vw] lg:py-[1.181vw] px-6 py-[17px] transition-transform lg:rounded-[0.833vw] rounded-xl bg-gradient"
>
Оставить заявку
</a>
>>>>>>> 258568050cbcb3e46cc31416fc9a0ba7a21ac066
</div>
</div>
</div>
)}
</div>
<p className="lg:headline1 headline2 text-[#7A7A7A] w-full pr-[8.333vw] md:max-w-[75vw]">
{t("demos.description")}
</p>
</div>
{(isLg || isMd) && (
<div className="flex md:-mx-[2.604vw] md:w-[calc(100%+5.208vw)] md:px-[2.604vw] lg:gap-[0.833vw] md:gap-[1.563vw] lg:h-[27.5vw] md:h-[51.563vw] md:overflow-x-scroll hide-scrollbars">
{projects.slice(0, 3).map((project, index, { length }) => (
<div
key={project.id}
className={`w-full ${index === 0 ? "flex-auto" : "flex-1"}`}
>
<StreamingProject
{...project}
index={index}
current={current}
count={length + 1}
href="/"
className="w-full"
/>
</div>
))}
</div>
)}
{/* Слайдер на десктопе */}
<div
ref={sliderRef}
onMouseDown={isMd ? onSliderMouseDown : undefined}
className="max-md:hidden flex md:-mx-[2.604vw] md:w-[calc(100%+5.208vw)] md:px-[2.604vw] lg:gap-[0.833vw] md:gap-[1.563vw] lg:h-[27.5vw] md:h-[51.563vw] md:overflow-x-scroll hide-scrollbars max-md:cursor-grab active:cursor-grabbing select-none touch-pan-x"
>
{projects.slice(0, 3).map((project, index, { length }) => (
<div
key={project.id}
className={`w-full ${index === 0 ? "flex-auto" : "flex-1"}`}
>
<StreamingProject
{...project}
index={index}
current={current}
count={length + 1}
href="/"
className="w-full"
/>
</div>
))}
</div>
</div>
);
}
+10 -5
View File
@@ -12,7 +12,8 @@ export default function RequestForDemo() {
<div
className="
flex max-md:flex-col flex-row lg:gap-[0.833vw] md:gap-[2.865vw] gap-[11.111vw]
lg:-mx-[1.389vw] lg:w-[calc(100%+2.778vw)] lg:pl-[1.389vw]
lg:-mx-[1.389vw] lg:w-[calc(100%+2.778vw)] lg:pl-[1.389vw] lg:pr-0
md:-mx-[{...handlers}] md:w-[calc(100%+4.167vw)] md:pr-[2.083vw]
"
>
<div className="flex flex-col lg:max-w-[31.944vw] min-h-full">
@@ -38,10 +39,14 @@ export default function RequestForDemo() {
</div>
</div>
<img
src="/img/showreel.png"
alt=""
className="lg:h-[44.444vw] md:h-[57.292vw] h-[122.222vw] max-md:rounded-[4.444vw] object-cover"
<video
poster="/img/showreel.png"
src="/videos/composition_c.mp4"
loop
autoPlay
muted
playsInline
className="lg:h-[44.444vw] md:h-[57.292vw] h-[122.222vw] lg:rounded-[1.111vw_0_0_1.111vw] md:rounded-[2.083vw_0_0_2.083vw] max-md:rounded-[4.444vw] object-cover overflow-hidden"
/>
</div>
);
@@ -48,6 +48,7 @@ export function StreamingProject({
loading="lazy"
decoding="async"
className="absolute inset-0 z-0 size-full object-cover object-bottom"
draggable={false}
/>
<div
aria-hidden
+16
View File
@@ -24,6 +24,22 @@ body {
overscroll-behavior-y: none;
}
*::-webkit-scrollbar {
width: 12px;
}
*::-webkit-scrollbar-thumb {
background-color: #798fff;
border-radius: 4px;
}
.scrollbar-gradient::-webkit-scrollbar-thumb {
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
}
*::-webkit-scrollbar-thumb:hover {
border-width: 2px;
}
.hide-scrollbars {
-ms-overflow-style: none;
scrollbar-width: none;