File: //var/www/quadcode.com/src/components/blocks/main/Kickstart.svelte
<script lang="ts">
import Button from '../../button/Button.svelte';
import { popupForm } from '../../../store';
import { t } from '$lib/translations';
import { onMount, onDestroy, tick } from 'svelte';
import Swiper from 'swiper';
import 'swiper/css';
import { Pagination } from 'swiper/modules';
let swiperInstance: Swiper | null = null;
let activeIndex = 0;
let progress = 0;
let progressInterval: number | null = null;
let slideInterval: number | null = null;
import desktopImage from '../../../assets/images/main/hero/desktop.webp';
import mobileImage from '../../../assets/images/main/hero/sample-mobile.webp';
$: steps = [
{
number: '01',
title: $t('Leave request'),
description: '',
},
{
number: '02',
title: $t('Check out the demo'),
description: $t('Check out our demo to learn everything you need to know about the platform'),
},
{
number: '03',
title: $t('Customise the platform'),
description: '',
},
{
number: '04',
title: $t('Sign the contract'),
description: '',
},
{
number: '05',
title: $t('Get brokerage solution'),
description: '',
},
];
function startProgress() {
if (progressInterval !== null) {
cancelAnimationFrame(progressInterval);
}
progress = 0;
const startTime = Date.now();
const duration = 3000;
function updateProgress() {
const elapsed = Date.now() - startTime;
const newProgress = Math.min((elapsed / duration) * 100, 100);
progress = newProgress;
if (newProgress < 100) {
progressInterval = requestAnimationFrame(updateProgress);
} else {
progressInterval = null;
progress = 100;
nextSlide();
}
}
progressInterval = requestAnimationFrame(updateProgress);
}
function nextSlide() {
activeIndex = (activeIndex + 1) % steps.length;
progress = 0;
startProgress();
}
onMount(async () => {
await tick();
const container: HTMLElement | null = document.querySelector('.block-kickstart__swiper');
if (!container) return;
swiperInstance = new Swiper(container, {
modules: [Pagination],
slidesPerView: 'auto',
spaceBetween: 20,
loop: false,
allowTouchMove: false,
pagination: {
enabled: false,
},
});
activeIndex = 0;
startProgress();
});
onDestroy(() => {
if (progressInterval !== null) {
cancelAnimationFrame(progressInterval);
}
if (slideInterval !== null) {
clearInterval(slideInterval);
}
});
</script>
<div class="block-kickstart">
<div class="container">
<div class="block-kickstart__content">
<h1 class="block-kickstart__title">{@html $t('Kickstart your broker within 14 days')}</h1>
<div class="block-kickstart__right">
<p class="block-kickstart__description">
{@html $t(
'Fill out the form and chat with our managers to discuss your project and see how quickly you can set up your brokerage business'
)}
</p>
<div class="block-kickstart__button-wrapper">
<Button text={$t('Leave request')} onClick={() => popupForm.set(true)} />
</div>
</div>
</div>
<div class="block-kickstart__images">
<img
src={desktopImage}
alt="Desktop trading platform"
class="block-kickstart__image block-kickstart__image--desktop"
/>
<img
src={mobileImage}
alt="Mobile trading platform"
class="block-kickstart__image block-kickstart__image--mobile"
/>
</div>
<div class="block-kickstart__slider">
<div class="swiper block-kickstart__swiper">
<div class="swiper-wrapper">
{#each steps as step, index (step.number)}
<div class="swiper-slide">
<div class="block-kickstart__step" class:active={activeIndex === index}>
<div class="block-kickstart__step-line-wrapper">
<div class="block-kickstart__step-line">
{#if activeIndex === index}
<div class="block-kickstart__step-progress" style="width: {progress}%" />
{:else}
<div class="block-kickstart__step-progress" style="width: 0%" />
{/if}
</div>
</div>
<div class="block-kickstart__step-number">{step.number}.</div>
<div class="block-kickstart__step-title">{step.title}</div>
{#if step.description}
<div class="block-kickstart__step-description">{step.description}</div>
{/if}
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
</div>
<style lang="scss">
@import 'src/scss/variables';
@import 'src/scss/media';
@import 'src/scss/mixins';
.block-kickstart {
padding: 120px 56px 100px 56px;
background: #161618;
overflow-x: hidden;
@media (max-width: 1366px) {
padding: 120px 40px 100px 40px;
}
@media (max-width: 1365px) {
padding: 120px 32px;
}
@media (max-width: 1023px) {
padding: 120px 32px 40px 32px;
}
@media (max-width: 719px) {
padding: 120px 24px 40px 24px;
}
@media (max-width: 393px) {
padding: 90px 20px 40px 20px;
}
& .container {
@media (max-width: 1366px) {
padding: 0;
}
}
&__content {
display: flex;
align-items: flex-start;
gap: 96px;
@media (max-width: 720px) {
flex-direction: column;
gap: 24px;
}
}
&__title {
flex: 1;
font-weight: 400;
font-size: 64px;
line-height: 72px;
max-width: 804px;
background: linear-gradient(180deg, #f9fbfc 0%, #adb1b7 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
@media (max-width: 1024px) {
font-size: 56px;
line-height: 68px;
max-width: 440px;
}
@media (max-width: 720px) {
font-size: 52px;
line-height: 64px;
max-width: 648px;
}
@media (max-width: 393px) {
font-size: 36px;
line-height: 44px;
}
}
&__right {
display: flex;
flex-direction: column;
gap: 31px;
flex: 1;
padding-left: 4px;
max-width: 424px;
@media (max-width: 1366px) {
padding-left: 0;
}
@media (max-width: 720px) {
max-width: 540px;
}
}
&__description {
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
line-height: 24px;
}
&__button-wrapper {
align-self: flex-start;
:global(.button) {
padding: 8px 16px;
font-size: 14px;
line-height: 20px;
width: fit-content;
font-weight: 450;
}
}
&__images {
background: #28282c;
padding: 56px 56px 0 56px;
margin-top: 58px;
border-radius: 32px;
display: flex;
justify-content: center;
gap: 32px;
overflow: hidden;
position: relative;
height: 388px;
@media (max-width: 720px) {
gap: 16px;
padding: 32px 0px 0 24px;
height: 364px;
justify-content: flex-start;
}
@media (max-width: 480px) {
height: 308px;
}
@media (max-width: 393px) {
gap: 8px;
padding: 32px 0px 0 24px;
height: 208px;
justify-content: flex-start;
border-radius: 16px;
}
}
&__image {
max-width: 100%;
object-fit: contain;
object-position: bottom;
height: auto;
margin-top: auto;
align-self: flex-end;
&--desktop {
flex: 1;
max-width: 80%;
@media (max-width: 1366px) {
width: 872px;
max-width: 872px;
flex: 0 0 872px;
}
@media (max-width: 1365px) {
width: 594px;
max-width: 594px;
flex: 0 0 594px;
}
@media (max-width: 1024px) {
width: 594px;
max-width: 594px;
flex: 0 0 594px;
}
@media (max-width: 720px) {
order: 2;
width: 800px;
max-width: none;
flex: none;
object-fit: cover;
object-position: left center;
}
@media (max-width: 480px) {
width: 480px;
max-width: 480px;
}
@media (max-width: 480px) {
width: 440px;
max-width: 440px;
}
}
&--mobile {
max-width: 270px;
@media (max-width: 720px) {
order: 1;
width: 176px;
max-width: 176px;
object-fit: cover;
}
@media (max-width: 480px) {
width: 160px;
max-width: 160px;
}
@media (max-width: 393px) {
width: 106px;
height: 223px;
max-width: 106px;
}
}
}
&__slider {
margin-top: 58px;
overflow: visible;
}
&__swiper {
padding-bottom: 60px;
@media (max-width: 720px) {
padding-bottom: 80px;
height: 200px;
}
:global(.swiper-wrapper) {
display: flex;
width: 100%;
@media (max-width: 1365px) {
justify-content: center;
}
@media (max-width: 1024px) {
justify-content: flex-start;
}
}
}
&__step {
position: relative;
padding-top: 24px;
padding-bottom: 16px;
display: flex;
flex-direction: column;
gap: 16px;
flex: 1 1 0;
min-width: 0;
align-items: flex-start;
overflow: visible;
transition: width 0.3s ease, flex 0.3s ease;
@media (max-width: 720px) {
gap: 12px;
padding-top: 16px;
padding-bottom: 12px;
}
&.active {
flex: 0 0 427px;
width: 427px;
@media (max-width: 720px) {
flex: 0 0 234px;
width: 234px;
}
@media (max-width: 480px) {
flex: 0 0 168px;
width: 168px;
}
@media (max-width: 393px) {
flex: 0 0 168px;
width: 168px;
}
}
}
&__step-line-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
}
&__step-line {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: rgba(255, 255, 255, 0.1);
opacity: 1;
}
&__step-line {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: rgba(255, 255, 255, 0.1);
opacity: 1;
}
&__step-progress {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: $redPrimary;
transition: width 0.1s linear;
}
&__step-number {
font-size: 16px;
line-height: 20px;
color: rgba(255, 255, 255, 0.6);
transition: color 0.3s ease;
}
&__step.active &__step-number {
color: rgba(255, 255, 255, 0.6);
}
&__step-title {
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #f9fbfc;
transition: color 0.3s ease;
@media (max-width: 720px) {
font-size: 14px;
line-height: 20px;
}
@media (max-width: 880px) {
display: none;
}
}
&__step.active &__step-title {
color: $techWhite;
@media (max-width: 880px) {
display: block;
}
}
&__step-description {
position: absolute;
top: 100%;
left: 0;
font-size: 16px;
line-height: 20px;
font-weight: 400;
color: #7d8387;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
max-width: 427px;
@media (max-width: 393px) {
font-size: 14px;
line-height: 20px;
}
}
&__step.active &__step-description {
opacity: 1;
}
&__swiper :global(.swiper-slide) {
height: auto;
flex: 1 1 0;
min-width: 0;
transition: flex 0.3s ease, width 0.3s ease;
&:has(.block-kickstart__step.active) {
flex: 0 0 427px;
width: 427px;
@media (max-width: 720px) {
flex: 0 0 234px;
width: 234px;
}
@media (max-width: 480px) {
flex: 0 0 168px;
width: 168px;
}
@media (max-width: 393px) {
flex: 0 0 168px;
width: 168px;
}
}
@media (max-width: 1024px) {
margin-right: 24px !important;
}
@media (max-width: 480px) {
margin-right: 16px !important;
}
}
}
</style>