fixed slider, refactoring

This commit is contained in:
2024-07-19 17:01:57 +05:00
parent 30d849bf37
commit 5657a53c9e
9 changed files with 65 additions and 44 deletions
-1
View File
@@ -36,7 +36,6 @@
"eslint-plugin-react-refresh": "^0.4.7",
"postcss": "^8.4.38",
"prettier": "^3.3.2",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.4",
"typescript": "^5.2.2",
"vite": "^5.3.1"
+3 -3
View File
@@ -101,7 +101,7 @@ function BurgerAnchor({
return (
<HashLink
to={route}
className="flex items-center px-10 py-6 gap-1 btn-text bg-[#14161F] w-full last:border-b-0 [&:not(:last-child)]:border-b sm:border-l font-semibold border-[#3D425C] hover:bg-[#3D425C] active:bg-[#14161F]"
className="flex items-center px-10 py-6 gap-1 btn-text bg-[#14161F] w-full last:border-b-0 [&:not(:last-child)]:border-b sm:border-l font-semibold border-[#3D425C] lg:hover:bg-[#3D425C] active:bg-[#14161F]"
>
<CubeIcon />
{children}
@@ -115,7 +115,7 @@ function ChooseLang({ currentLang }: { currentLang: 'RU' | 'EN' }) {
<button
onClick={() => setLang(currentLang)}
className={
'min-h-[72px] w-full h-full btn-text font-semibold bg-[#14161F] hover:bg-[#3D425C] border active:bg-[#14161F] ' +
'min-h-[72px] w-full h-full btn-text font-semibold bg-[#14161F] lg:hover:bg-[#3D425C] border active:bg-[#14161F] ' +
(lang === currentLang
? '[border-image:linear-gradient(to_right,#798FFF,#D375FF)_3]'
: 'border-[#3D425C]')
@@ -134,7 +134,7 @@ function LangToggler({ lang }: { lang: Lang }) {
return (
<div
ref={langTogglerRef}
className="min-w-[101px] max-[1349px]:hidden hover:bg-[#3D425C] active:bg-[#14161F]"
className="min-w-[101px] max-[1349px]:hidden lg:hover:bg-[#3D425C] active:bg-[#14161F]"
>
<button
onClick={() => setOpen(prev => !prev)}
+5 -5
View File
@@ -35,14 +35,14 @@ export function Contacts() {
<div className="space-y-2 2xl:pr-4 xl:pr-2">
<a
href="mailto:info@graff.tech"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] lg:opacity-80 lg:hover:opacity-100 transition-all"
>
<span>Написать</span>
<MailIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</a>
<a
href="tel:88007700067"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] lg:opacity-80 lg:hover:opacity-100 transition-all"
>
<span>Позвонить</span>
<PhoneIcon className="lg:w-8 lg:h-8 w-6 h-6" />
@@ -60,21 +60,21 @@ export function Contacts() {
<a
href="https://www.youtube.com/@GRAFFtech"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full lg:hover:border-[#52587A] transition-all"
>
<YouTubeIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://vk.com/graff.interactive"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full lg:hover:border-[#52587A] transition-all"
>
<VKIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://t.me/GRAFFinteractive"
target="_blank"
className="border rounded-full border-[#52587A] xl:p-4 p-3 opacity-80 hover:opacity-100 transition-all"
className="border rounded-full border-[#52587A] xl:p-4 p-3 opacity-80 lg:hover:opacity-100 transition-all"
>
<TelegramIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
+2 -2
View File
@@ -162,7 +162,7 @@ export default function ContactsForm({
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
className="text-[#798FFF] cursor-pointer opacity-95 lg:hover:opacity-100 transition-all"
>
условия использования
</a>{' '}
@@ -170,7 +170,7 @@ export default function ContactsForm({
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
className="text-[#798FFF] cursor-pointer opacity-95 lg:hover:opacity-100 transition-all"
>
политику конфиденциальности
</a>
+1 -1
View File
@@ -27,7 +27,7 @@ function ModalWithForm() {
</p>
<button
onClick={() => setModal(null)}
className="p-2 hover:bg-white hover:bg-opacity-10 transition-colors rounded-full"
className="p-2 lg:hover:bg-white lg:hover:bg-opacity-10 transition-colors rounded-full"
>
<CloseIcon className="text-white" />
</button>
+1 -1
View File
@@ -37,7 +37,7 @@ export function Products() {
<MiniTitle className="lg:hidden" text="Продукты" />
<div
className={
'flex gax-y-4 bg-[#3D425C4D] bg-opacity-3 scrollbar-none rounded-xl p-1 mb-2 w-fit max-w-full overflow-auto sm:max-lg:mt-[13px] mt-6' +
'flex gax-y-4 bg-[#3D425C4D] bg-opacity-3 [&::-webkit-scrollbar]:hidden rounded-xl p-1 mb-2 w-fit max-w-full overflow-auto sm:max-lg:mt-[13px] mt-6' +
(curTab !== 2
? ' max-[912px]:[-webkit-mask-image:_linear-gradient(to_left,rgba(32,35,50,0)_0%,rgba(32,35,50,1)_20%)]'
: '')
+52 -23
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useReducer, useState } from 'react';
import { useEffect, useReducer, useState } from 'react';
import { MiniTitle } from '../../ui/MiniTitle';
import { useWindowWidth } from '../../hooks/useWindowWidth';
import { Title } from '../../ui/Title';
@@ -10,7 +10,7 @@ export function Projects() {
return (
<div
id="projects"
className="lg:py-[70px] lg:px-10 py-14 sm:px-6 px-5 overflow-hidden select-none"
className="lg:py-[70px] lg:px-10 py-14 sm:px-6 px-5 overflow-hidden"
>
<Title className="desktop-figma:mb-[77px] lg:mb-14 mb-6">
<span className="text-gradient">Большой опыт в работе</span> с
@@ -56,12 +56,12 @@ function Project({
style={{ backgroundImage: `url(${src})` }}
/>
<div className="p-5">
<h4 className=" font-medium h4">{title}</h4>
<h4 className="font-medium h4">{title}</h4>
<div className="flex gap-2 mt-4">
{tags.map(tag => (
<p
key={tag}
className=" opacity-80 font-medium rounded-3xl py-3 px-4 border border-[#798FFF] m-text"
className="opacity-80 font-medium rounded-3xl py-3 px-4 border border-[#798FFF] m-text"
>
{tag}
</p>
@@ -78,36 +78,39 @@ function Slider({
projects: { src: string; title: string; tags: string[] }[];
}) {
const width = useWindowWidth();
const baseOffset = useMemo(
() => (width >= 1024 ? 640 : width >= 640 ? 536 : 336),
[width],
);
const baseOffset = width >= 1024 ? 640 : width >= 640 ? 536 : 336;
const [sliderOffset, setSliderOffset] = useState(-baseOffset);
const [slide, setSlide] = useState(0);
const [order, dispatch] = useReducer(
(state: typeof projects, action: string) => {
if (action === 'next') {
setSliderOffset(prev => prev + baseOffset);
return [...state.slice(1), state[2]];
}
if (action === 'prev') {
setSliderOffset(-baseOffset * 2);
return [state[state.length - 3], ...state.slice(0, -1)];
setSliderOffset(prev => prev + baseOffset);
return [...state.slice(1), state[state.length - 3]];
}
if (action === 'next') {
setSliderOffset(prev => prev - baseOffset);
return [state[state.length - 2], ...state.slice(0, -1)];
}
return state;
},
[projects[projects.length - 1], ...projects, projects[0]],
[
projects[projects.length - 2],
projects[projects.length - 1],
...projects,
projects[0],
projects[1],
],
);
const handlers = useSwipeable({
onSwipedLeft: () => {
setSlide(prev => (prev === order.length - 3 ? 0 : prev + 1));
dispatch('next');
setSlide(prev => (prev === order.length - 5 ? 0 : prev + 1));
dispatch('prev');
},
onSwipedRight: () => {
setSlide(prev => (prev === 0 ? order.length - 3 : prev - 1));
dispatch('prev');
setSlide(prev => (prev === 0 ? order.length - 5 : prev - 1));
dispatch('next');
},
trackMouse: true,
preventScrollOnSwipe: true,
@@ -115,16 +118,18 @@ function Slider({
});
useEffect(() => {
setSliderOffset(-baseOffset);
setSliderOffset(-baseOffset * 2);
}, [order, baseOffset, slide]);
useEffect(() => console.log('slider offset:', sliderOffset), [sliderOffset]);
return (
<div className="flex flex-col lg:mt-4 sm:mt-3 mt-2">
<div {...handlers}>
<div
className="flex gap-2 overflow-visible relative mb-[18px] -mr-10 select-none"
style={{
transition: `${sliderOffset === 0 || sliderOffset === -baseOffset * 2 ? 0 : 0.5}s`,
transition: `${sliderOffset === -baseOffset || sliderOffset === -baseOffset * 3 ? 0 : 0.5}s`,
transform: `translateX(${sliderOffset}px)`,
}}
>
@@ -136,7 +141,7 @@ function Slider({
<div className="flex items-center gap-4 lg:w-[clamp(720px,100vw-465px,1135px)] desktop-figma:w-[70.9vw] w-full self-start lg:ml-64">
<button
onClick={() => {
setSlide(prev => (prev === 0 ? order.length - 3 : prev - 1));
setSlide(prev => (prev === 0 ? order.length - 5 : prev - 1));
dispatch('prev');
}}
className="max-sm:hidden"
@@ -151,7 +156,7 @@ function Slider({
</div>
<button
onClick={() => {
setSlide(prev => (prev === order.length - 3 ? 0 : prev + 1));
setSlide(prev => (prev === order.length - 5 ? 0 : prev + 1));
dispatch('next');
}}
className="max-sm:hidden"
@@ -162,3 +167,27 @@ function Slider({
</div>
);
}
// next
// 2|0 1 2|0
// |0 1 2|0 1
// 0|1 2 0|1
// prev
// 2|0 1 2|0
// 1 2|0 1 2|
// 1|2 0 1|2
// next
// 1 2|0 1 2|0 1
// 2|0 1 2|0 1 2
// 2 0|1 2 0|1 2
// 0|1 2 0|1 2 0
// 0 1|2 0 1|2 0
// prev
// 1 2|0 1 2|0 1
// 0 1 2|0 1 2|0
// 0 1|2 0 1|2 0
// 2 0 1|2 0 1|2
// 2 0|1 2 0|1 2
+1 -3
View File
@@ -1,5 +1,3 @@
import tailwindScrollbar from 'tailwind-scrollbar';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
@@ -19,5 +17,5 @@ export default {
},
},
},
plugins: [tailwindScrollbar({ nocompatible: true })],
plugins: [],
};
-5
View File
@@ -2095,11 +2095,6 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
tailwind-scrollbar@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/tailwind-scrollbar/-/tailwind-scrollbar-3.1.0.tgz#ff7596407b6da5209261d8ff03860ab9206a59e3"
integrity sha512-pmrtDIZeHyu2idTejfV59SbaJyvp1VRjYxAjZBH0jnyrPRo6HL1kD5Glz8VPagasqr6oAx6M05+Tuw429Z8jxg==
tailwindcss@^3.4.4:
version "3.4.4"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.4.tgz#351d932273e6abfa75ce7d226b5bf3a6cb257c05"