added clients marquee
@@ -0,0 +1,275 @@
|
||||
import { api } from '../api';
|
||||
import { phoneCodes } from '../consts/phoneCodes';
|
||||
import { ClassNameWrapper } from '../hocs/ClassNameWrapper';
|
||||
import { useModalStore } from '@/stores/useModalStore';
|
||||
import { PhoneCode } from '@/types/PhoneCode';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { FormEvent, useEffect, useRef, useState } from 'react';
|
||||
import ReactInputMask from 'react-input-mask';
|
||||
import { ArrowRightIcon } from '../icons/ArrowRightIcon';
|
||||
import { ChevronDownIcon } from '../icons/ChevronDownIcon';
|
||||
import { ChevronUpIcon } from '../icons/ChevronUpIcon';
|
||||
import { CloseIcon } from '../icons/CloseIcon';
|
||||
import { LoaderIcon } from '../icons/LoaderIcon';
|
||||
import { MailIcon } from '../icons/MailIcon';
|
||||
|
||||
export function ModalWithForm() {
|
||||
const { setModal } = useModalStore();
|
||||
const [name, setName] = useState('');
|
||||
const [phoneCode, setPhoneCode] = useState<PhoneCode>('+7');
|
||||
const [phone, setPhone] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isSend, setIsSend] = useState(false);
|
||||
|
||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (textAreaRef.current) {
|
||||
textAreaRef.current.style.height = 'auto';
|
||||
textAreaRef.current.style.height =
|
||||
textAreaRef.current.scrollHeight + 'px';
|
||||
}
|
||||
}, [textAreaRef, description]);
|
||||
|
||||
function handleSubmit(e: FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
|
||||
sendMail();
|
||||
}
|
||||
|
||||
async function sendMail() {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
await api
|
||||
.post('mail', {
|
||||
json: {
|
||||
fullname: name,
|
||||
phone: phoneCode + phone,
|
||||
email,
|
||||
request: description,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
||||
setIsSend(true);
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
if (error instanceof Error) {
|
||||
alert(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
setModal(false, 'form');
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', listener);
|
||||
return () => document.removeEventListener('keydown', listener);
|
||||
}, [setModal]);
|
||||
|
||||
return (
|
||||
<div className="fixed flex flex-col gap-4 top-0 right-0 h-full sm:w-[408px] w-full bg-[#14161F] overflow-y-auto sm:p-8 p-6">
|
||||
{!isSend ? (
|
||||
<div className="space-y-8">
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="font-medium accent">Оставьте заявку</p>
|
||||
<button
|
||||
onClick={() => setModal(null, '')}
|
||||
className="p-2 lg:hover:bg-white lg:hover:bg-opacity-10 transition-colors rounded-full"
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="space-y-6">
|
||||
<hr className="border-[#3D425C]" />
|
||||
|
||||
<div>
|
||||
<label
|
||||
className="m-text text-[#9299BD] select-none"
|
||||
htmlFor="name"
|
||||
>
|
||||
Имя
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
id="name"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
placeholder="Ваше имя"
|
||||
className="bg-transparent border-b border-[#3D425C] focus:border-white py-4 rounded-none outline-none transition-all w-full placeholder:h4 placeholder:font-medium placeholder:select-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
className="m-text text-[#9299BD] select-none"
|
||||
htmlFor="tel"
|
||||
>
|
||||
Телефон
|
||||
</label>
|
||||
<div className="flex gap-x-3 py-2 border-[#3D425C] relative">
|
||||
<SelectPhoneCode
|
||||
currentPhoneCode={phoneCode}
|
||||
onClick={setPhoneCode}
|
||||
/>
|
||||
<div className="border-l border-[#3D425C]" />
|
||||
<ReactInputMask
|
||||
required
|
||||
type="tel"
|
||||
id="tel"
|
||||
mask={'(999) 99 999 99'}
|
||||
maskChar={null}
|
||||
value={phone}
|
||||
placeholder="(900) 000 00 00"
|
||||
onChange={e => setPhone(e.target.value)}
|
||||
className="bg-transparent rounded-none outline-none transition-all w-full placeholder:h4 placeholder:font-medium placeholder:select-none peer"
|
||||
/>
|
||||
<div className="bottom-0 absolute w-full border-b border-[#3D425C] peer-focus:border-white -mb-2" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
className="m-text text-[#9299BD] select-none"
|
||||
htmlFor="email"
|
||||
>
|
||||
Email*
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
id="email"
|
||||
type="text"
|
||||
value={email}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
placeholder="Ваш email"
|
||||
className="bg-transparent border-b border-[#3D425C] focus:border-white py-4 rounded-none outline-none transition-all w-full placeholder:h4 placeholder:font-medium placeholder:select-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
className="m-text text-[#9299BD] select-none"
|
||||
htmlFor="description"
|
||||
>
|
||||
Задача
|
||||
</label>
|
||||
<textarea
|
||||
ref={textAreaRef}
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
width="full"
|
||||
disabled={isLoading}
|
||||
className="py-5 px-6 mt-[213px]"
|
||||
icon={
|
||||
isLoading ? (
|
||||
<ClassNameWrapper
|
||||
element={<LoaderIcon />}
|
||||
className="relative w-6 h-6 animate-spin"
|
||||
/>
|
||||
) : (
|
||||
<ClassNameWrapper
|
||||
element={<MailIcon />}
|
||||
className="relative w-6 h-6"
|
||||
/>
|
||||
)
|
||||
}
|
||||
>
|
||||
Отправить
|
||||
</Button>
|
||||
<p className="m-caption mt-6 text-center text-[#52587A]">
|
||||
Нажимая кнопку отправить, вы принимаете
|
||||
<span className="text-gradient">
|
||||
{' '}
|
||||
условия использования и политику конфиденциальности
|
||||
</span>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
) : (
|
||||
<div className="">
|
||||
<div className="space-y-8">
|
||||
<h2 className="h2 font-medium">Спасибо за отправку заявки!</h2>
|
||||
<p className="m-text">
|
||||
Мы ценим ваш интерес к нашей компании и в ближайшее время свяжемся
|
||||
с вами для уточнения деталей проекта.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
width="full"
|
||||
className="py-5 px-6 absolute top-[50vh]"
|
||||
icon={
|
||||
<ClassNameWrapper
|
||||
className="w-6 h-6"
|
||||
element={<ArrowRightIcon />}
|
||||
/>
|
||||
}
|
||||
onClick={() => setModal(false, '')}
|
||||
>
|
||||
На главную
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SelectPhoneCode({
|
||||
currentPhoneCode,
|
||||
onClick,
|
||||
}: {
|
||||
currentPhoneCode: PhoneCode;
|
||||
onClick: (phoneCode: PhoneCode) => void;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col">
|
||||
<button
|
||||
className="flex gap-x-4 items-center relative"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
setOpen(prev => !prev);
|
||||
}}
|
||||
>
|
||||
<p className="h4">{currentPhoneCode}</p>
|
||||
{open ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
||||
</button>
|
||||
{open && (
|
||||
<div className="absolute z-10 bg-[#14161F] top-[100%] w-[calc(100%+4px)] -left-1 border border-t-0 p-1 rounded-b-lg border-[#3D425C]">
|
||||
{phoneCodes
|
||||
.filter(phonecode => phonecode !== currentPhoneCode)
|
||||
.map(phoneCode => (
|
||||
<p
|
||||
key={phoneCode}
|
||||
className="h4 cursor-pointer hover:bg-[#3D425C] py-1"
|
||||
onClick={() => {
|
||||
onClick(phoneCode);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{phoneCode}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { Outlet } from 'react-router-dom';
|
||||
import { Footer } from './Footer';
|
||||
import { Header } from './Header';
|
||||
import { Feedback } from '../components/Feedback';
|
||||
import { Clients } from '../components/Clients';
|
||||
|
||||
export function Layout() {
|
||||
return (
|
||||
@@ -10,6 +11,7 @@ export function Layout() {
|
||||
<main className="lg:px-6">
|
||||
<Outlet />
|
||||
</main>
|
||||
<Clients />
|
||||
<Feedback />
|
||||
<Footer />
|
||||
</>
|
||||
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1021 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,52 @@
|
||||
import { clients } from '../consts/clients';
|
||||
|
||||
export function Clients() {
|
||||
return (
|
||||
<div className="space-y-6 overflow-hidden mt-16">
|
||||
<div className="flex items-center overflow-hidden w-screen min-h-[117px]">
|
||||
<MarqueeHalf items={clients.slice(0, clients.length / 3)} />
|
||||
<MarqueeHalf items={clients.slice(0, clients.length / 3)} />
|
||||
</div>
|
||||
<div className="flex items-center overflow-hidden w-screen min-h-[117px]">
|
||||
<MarqueeHalf
|
||||
reversed
|
||||
items={clients.slice(clients.length / 3, (2 * clients.length) / 3)}
|
||||
/>
|
||||
<MarqueeHalf
|
||||
reversed
|
||||
items={clients.slice(clients.length / 3, (2 * clients.length) / 3)}
|
||||
/>
|
||||
</div>
|
||||
<div className="border-b border-[#3D425C] flex items-center overflow-hidden w-screen min-h-[117px] pb-16">
|
||||
<MarqueeHalf items={clients.slice(2 * (clients.length / 3))} />
|
||||
<MarqueeHalf items={clients.slice(2 * (clients.length / 3))} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MarqueeHalf({
|
||||
reversed = false,
|
||||
items,
|
||||
}: {
|
||||
items: { src: string }[];
|
||||
reversed?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'flex flex-nowrap overflow-clip items-center py-2 [flex:0_0_auto] animate-infinite-scroll ' +
|
||||
(reversed ? '[animation-direction:reverse]' : '')
|
||||
}
|
||||
>
|
||||
{items.map(client => (
|
||||
<img
|
||||
key={client.src}
|
||||
src={client.src}
|
||||
alt={client.src}
|
||||
className="max-w-full h-auto !relative object-covesr mx-12"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { Title } from './ui/Title';
|
||||
|
||||
export function Projects() {
|
||||
return (
|
||||
<div className="space-y-6 mt-[180px]">
|
||||
<div id={'/projects'} className="space-y-6 mt-[180px]">
|
||||
<Title>Проекты</Title>
|
||||
<div className="flex flex-col gap-y-16">
|
||||
<div className="flex gap-x-4">{projects.slice(0, 2).map(Project)}</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ export function TelegramIcon() {
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M5.44748 8H2.38424C1.50903 8 1.33398 8.39579 1.33398 8.83368C1.33398 9.61432 2.37198 13.4863 6.16953 18.6072C8.70064 22.1044 12.2671 24 15.5124 24C17.4598 24 17.7004 23.5789 17.7004 22.8539V20.2105C17.7004 19.3684 17.8842 19.2 18.5013 19.2C18.9564 19.2 19.7353 19.4189 21.5522 21.1048C23.6291 23.1032 23.9713 24 25.1397 24H28.203C29.0782 24 29.5158 23.5789 29.2629 22.7478C28.9872 21.92 27.9956 20.7183 26.6792 19.2943C25.9651 18.4825 24.8938 17.6076 24.57 17.1705C24.1149 16.6088 24.2462 16.3587 24.57 15.8594C24.57 15.8594 28.3019 10.8008 28.6922 9.08379C28.8865 8.45895 28.6922 8 27.7645 8H24.7021C23.9232 8 23.5644 8.39579 23.3701 8.83368C23.3701 8.83368 21.8122 12.4867 19.6058 14.8598C18.8916 15.5469 18.5669 15.7659 18.1774 15.7659C17.9831 15.7659 17.7013 15.5469 17.7013 14.9229V9.08379C17.7013 8.33432 17.4746 8 16.8261 8H12.0124C11.5258 8 11.2335 8.34779 11.2335 8.6779C11.2335 9.38779 12.3363 9.552 12.45 11.5495V15.8905C12.45 16.8421 12.2715 17.0147 11.8812 17.0147C10.8432 17.0147 8.3173 13.3448 6.81894 9.14611C6.52486 8.32842 6.22992 8 5.44748 8Z"
|
||||
d="M4.35848 15.8486C10.7919 12.8128 15.0923 10.8506 17.2253 9.88797C23.3491 7.14829 24.622 6.66699 25.4477 6.66699C25.6197 6.66699 26.0325 6.70402 26.3077 6.92615C26.5142 7.11127 26.583 7.37042 26.6174 7.55554C26.6518 7.74065 26.6862 8.1479 26.6518 8.48111C26.3077 12.2204 24.8972 21.365 24.1403 25.5486C23.8307 27.3257 23.2114 27.9181 22.6266 27.9921C21.3537 28.1032 20.356 27.0665 19.1175 26.215C17.1909 24.8452 16.09 23.9936 14.1978 22.6608C12.0304 21.1059 13.4409 20.2543 14.6794 18.8845C14.9891 18.5143 20.6656 12.9979 20.7688 12.4796C20.7688 12.4055 20.8032 12.1834 20.6656 12.0723C20.528 11.9612 20.356 11.9983 20.2184 12.0353C20.0119 12.0723 16.9157 14.2937 10.8951 18.6624C10.0006 19.3288 9.20934 19.625 8.48687 19.625C7.69559 19.625 6.18185 19.1437 5.04655 18.7364C3.67042 18.2551 2.56952 17.996 2.67273 17.1815C2.77594 16.7372 3.32639 16.2929 4.35848 15.8486Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
|
||||
@@ -11,7 +11,7 @@ export function VKIcon() {
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M26.4181 7.23088C27.5654 7.54116 28.4689 8.45558 28.7756 9.6165C29.3327 11.7209 29.3327 16.1114 29.3327 16.1114C29.3327 16.1114 29.3327 20.502 28.7756 22.6063C28.4689 23.7671 27.5654 24.6816 26.4181 24.9918C24.3384 25.5559 15.9994 25.5559 15.9994 25.5559C15.9994 25.5559 7.66049 25.5559 5.58084 24.9918C4.43357 24.6816 3.5299 23.7671 3.22327 22.6063C2.66602 20.502 2.66602 16.1114 2.66602 16.1114C2.66602 16.1114 2.66602 11.7209 3.22327 9.6165C3.5299 8.45558 4.43357 7.54116 5.58084 7.23088C7.66049 6.66699 15.9994 6.66699 15.9994 6.66699C15.9994 6.66699 24.3384 6.66699 26.4181 7.23088ZM13.7771 12.2224V20.0002L20.4438 16.1114L13.7771 12.2224Z"
|
||||
d="M5.44748 8H2.38424C1.50903 8 1.33398 8.39579 1.33398 8.83368C1.33398 9.61432 2.37198 13.4863 6.16953 18.6072C8.70064 22.1044 12.2671 24 15.5124 24C17.4598 24 17.7004 23.5789 17.7004 22.8539V20.2105C17.7004 19.3684 17.8842 19.2 18.5013 19.2C18.9564 19.2 19.7353 19.4189 21.5522 21.1048C23.6291 23.1032 23.9713 24 25.1397 24H28.203C29.0782 24 29.5158 23.5789 29.2629 22.7478C28.9872 21.92 27.9956 20.7183 26.6792 19.2943C25.9651 18.4825 24.8938 17.6076 24.57 17.1705C24.1149 16.6088 24.2462 16.3587 24.57 15.8594C24.57 15.8594 28.3019 10.8008 28.6922 9.08379C28.8865 8.45895 28.6922 8 27.7645 8H24.7021C23.9232 8 23.5644 8.39579 23.3701 8.83368C23.3701 8.83368 21.8122 12.4867 19.6058 14.8598C18.8916 15.5469 18.5669 15.7659 18.1774 15.7659C17.9831 15.7659 17.7013 15.5469 17.7013 14.9229V9.08379C17.7013 8.33432 17.4746 8 16.8261 8H12.0124C11.5258 8 11.2335 8.34779 11.2335 8.6779C11.2335 9.38779 12.3363 9.552 12.45 11.5495V15.8905C12.45 16.8421 12.2715 17.0147 11.8812 17.0147C10.8432 17.0147 8.3173 13.3448 6.81894 9.14611C6.52486 8.32842 6.22992 8 5.44748 8Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { IClient } from '../types/IClient';
|
||||
|
||||
export const clients: IClient[] = [
|
||||
{ src: '/src/assets/clients/sezar_group.png' },
|
||||
{ src: '/src/assets/clients/legenda.png' },
|
||||
{ src: '/src/assets/clients/osnova.png' },
|
||||
{ src: '/src/assets/clients/upside.png' },
|
||||
{ src: '/src/assets/clients/brusnika.png' },
|
||||
{ src: '/src/assets/clients/capital_group.png' },
|
||||
{ src: '/src/assets/clients/a101.png' },
|
||||
{ src: '/src/assets/clients/forum.png' },
|
||||
{ src: '/src/assets/clients/leto.png' },
|
||||
{ src: '/src/assets/clients/center.png' },
|
||||
{ src: '/src/assets/clients/center-invest.png' },
|
||||
{ src: '/src/assets/clients/rodina.png' },
|
||||
{ src: '/src/assets/clients/acons.png' },
|
||||
{ src: '/src/assets/clients/alfa.png' },
|
||||
{ src: '/src/assets/clients/sk+.png' },
|
||||
{ src: '/src/assets/clients/delom.png' },
|
||||
{ src: '/src/assets/clients/kama.png' },
|
||||
{ src: '/src/assets/clients/risan.png' },
|
||||
{ src: '/src/assets/clients/golos.png' },
|
||||
{ src: '/src/assets/clients/dns.png' },
|
||||
{ src: '/src/assets/clients/sibintel.png' },
|
||||
{ src: '/src/assets/clients/kortros.png' },
|
||||
{ src: '/src/assets/clients/mayak.png' },
|
||||
{ src: '/src/assets/clients/sbk.png' },
|
||||
{ src: '/src/assets/clients/nks.png' },
|
||||
{ src: '/src/assets/clients/atom.png' },
|
||||
{ src: '/src/assets/clients/yit.png' },
|
||||
{ src: '/src/assets/clients/sinara.png' },
|
||||
{ src: '/src/assets/clients/pik.png' },
|
||||
{ src: '/src/assets/clients/as.png' },
|
||||
{ src: '/src/assets/clients/efes.png' },
|
||||
{ src: '/src/assets/clients/atmosfera.png' },
|
||||
{ src: '/src/assets/clients/abudhabi.png' },
|
||||
{ src: '/src/assets/clients/mavis.png' },
|
||||
{ src: '/src/assets/clients/enko.png' },
|
||||
{ src: '/src/assets/clients/paritet.png' },
|
||||
{ src: '/src/assets/clients/fortis.png' },
|
||||
{ src: '/src/assets/clients/ugmk.png' },
|
||||
{ src: '/src/assets/clients/atlas.png' },
|
||||
];
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface IClient {
|
||||
src: string;
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
animation: {
|
||||
'infinite-scroll': 'infinite-scroll 25s linear infinite',
|
||||
},
|
||||
keyframes: {
|
||||
'infinite-scroll': {
|
||||
from: { transform: 'translateX(0)' },
|
||||
to: { transform: 'translateX(-100%)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
};
|
||||
|
||||