Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions blocks/server-side/ecosystem/ecosystem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';

import cn from 'classnames';

Expand All @@ -11,13 +11,23 @@ import { Card } from '../card/card';
import { primaryCardsData, secondaryCardsData } from './ecosystem-data';

import Link from 'next/link';
import { trackEvent } from '../../../utils/event-logger';
import { useIntersectionTracking } from '../../../utils/use-untersection-tracking';

export const Ecosystem: FC = ({}) => {

const textCn = useTextStyles();

const handleIntersection = useCallback(() => {
trackEvent({
eventAction: 'kt_server_side_ecosystem_read'
});
}, []);

const sectionRef = useIntersectionTracking(handleIntersection);

return (
<section className="ktl-layout ktl-layout--center">
<section className="ktl-layout ktl-layout--center" ref={sectionRef}>
<div className="ktl-container section-offset" id={'ecosystem'}>

<h2 className={cn(textCn('rs-h1'))}>
Expand Down
14 changes: 12 additions & 2 deletions blocks/server-side/favorite-tools/favorite-tools.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';

import cn from 'classnames';

Expand All @@ -17,13 +17,23 @@ import MavenLogo from './images/maven.svg';
import GradleLogo from './images/gradle.svg';
import AntLogo from './images/ant.svg';
import BazelLogo from './images/bazel.svg';
import { useIntersectionTracking } from '../../../utils/use-untersection-tracking';
import { trackEvent } from '../../../utils/event-logger';

export const FavoriteTools: FC = ({}) => {

const textCn = useTextStyles();

const handleIntersection = useCallback(() => {
trackEvent({
eventAction: 'kt_server_side_tools_read'
});
}, []);

const sectionRef = useIntersectionTracking(handleIntersection);

return (
<section className="ktl-layout ktl-layout--center">
<section className="ktl-layout ktl-layout--center" ref={sectionRef}>
<div className="ktl-container section-offset" id={'tools'}>

<h2 className={cn(textCn('rs-h1'))}>
Expand Down
24 changes: 8 additions & 16 deletions blocks/server-side/features-carousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ArrowLeftIcon, ArrowRightIcon } from '@rescui/icons';

import styles from './index.module.css';
import { SnapCarousel } from '../../../components/snap-carousel/snap-carousel';
import { trackEvent } from '../../../utils/event-logger';

interface FeatureSlideItem {
id: string;
Expand All @@ -20,10 +21,15 @@ interface FeatureSlideItem {

interface CopyCodeButtonProps {
codeSample: string;
label: string;
}

const CopyCodeButton: FC<CopyCodeButtonProps> = ({ codeSample }) => {
const CopyCodeButton: FC<CopyCodeButtonProps> = ({ codeSample, label }) => {
const handleCopy = () => {
trackEvent({
eventAction: 'kt_server_side_code_snippet_copy',
eventLabel: label,
});
navigator.clipboard.writeText(codeSample);
};

Expand Down Expand Up @@ -76,7 +82,7 @@ const FeatureCard: FC<FeatureCardProps> = ({
</div>
</div>
<div className={styles.imageWrapper}>
<CopyCodeButton codeSample={codeSample} />
<CopyCodeButton codeSample={codeSample} label={title.toString()} />
<CodeHighlight code={codeSample} className={styles.codeBlock} />
</div>
</div>
Expand All @@ -89,20 +95,6 @@ interface FeaturesCarouselProps {
}

export const FeaturesCarousel: FC<FeaturesCarouselProps> = ({ featuresData, className }) => {
const [activeIndex, setActiveIndex] = useState(0);

const handleChangeIndex = (index: number) => {
setActiveIndex(index);
};

const handlePrev = () => {
setActiveIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : prevIndex));
};

const handleNext = () => {
setActiveIndex((prevIndex) => (prevIndex < featuresData.length - 1 ? prevIndex + 1 : prevIndex));
};

return (
<div className={classNames(styles.carouselContainer, className)}>

Expand Down
25 changes: 21 additions & 4 deletions blocks/server-side/features-section/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';
import classNames from 'classnames';
import { useTextStyles } from '@rescui/typography';
import { useTL } from '@jetbrains/kotlin-web-site-ui/out/components/breakpoints';

import { featureSlideshowItems } from './items';
import { FeaturesCarousel } from '../features-carousel';
import { FeaturesSwitcher } from '../features-switcher';
import { trackEvent } from '../../../utils/event-logger';
import { useIntersectionTracking } from '../../../utils/use-untersection-tracking';

const FeaturesSection: FC = () => {
const textCn = useTextStyles();
const isTL = useTL();

const handleTabClick = useCallback((label: string) => {
trackEvent({
eventAction: 'kt_server_side_safety_click',
eventLabel: label
});
}, []);

const handleIntersection = useCallback(() => {
trackEvent({
eventAction: 'kt_server_side_safety_read'
});
}, []);

const sectionRef = useIntersectionTracking(handleIntersection);

return (
<section className="ktl-layout ktl-layout--center">
<section className="ktl-layout ktl-layout--center" ref={sectionRef}>
<div className="ktl-container section-offset" id={'safety'}>
<h2 className={classNames(textCn('rs-h1'))}>
Safety: fewer production bugs and crashes
</h2>

{isTL ? (
<FeaturesCarousel featuresData={featureSlideshowItems} className="" />
<FeaturesCarousel featuresData={featureSlideshowItems} />
) : (
<FeaturesSwitcher slides={featureSlideshowItems} className="" />
<FeaturesSwitcher slides={featureSlideshowItems} onTab={handleTabClick} />
)}
</div>
</section>
Expand Down
30 changes: 23 additions & 7 deletions blocks/server-side/features-switcher/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React, { FC, useState } from 'react';
import React, { FC, useCallback, useState } from 'react';
import classNames from 'classnames';
import { useTextStyles } from '@rescui/typography';
import { Button } from '@rescui/button';
import { CodeHighlight } from '../../../components/code-highlight/code-highlight';

import styles from './index.module.css';
import { trackEvent } from '../../../utils/event-logger';

interface CopyCodeButtonProps {
codeSample: string;
label: string;
}

const CopyCodeButton: FC<CopyCodeButtonProps> = ({ codeSample }) => {
const CopyCodeButton: FC<CopyCodeButtonProps> = ({ codeSample, label }) => {
const handleCopy = () => {
trackEvent({
eventAction: 'kt_server_side_code_snippet_copy',
eventLabel: label,
});
navigator.clipboard.writeText(codeSample);
};

Expand All @@ -24,11 +30,12 @@ const CopyCodeButton: FC<CopyCodeButtonProps> = ({ codeSample }) => {

interface CustomSlideProps {
codeSample: string;
label: string;
}

const CustomSlide: FC<CustomSlideProps> = ({ codeSample }) => (
const CustomSlide: FC<CustomSlideProps> = ({ codeSample, label }) => (
<div className={styles.slide}>
<CopyCodeButton codeSample={codeSample} />
<CopyCodeButton codeSample={codeSample} label={label} />
<CodeHighlight code={codeSample} className={styles.codeBlock} />
</div>
);
Expand All @@ -44,12 +51,21 @@ interface FeatureSlideItem {
interface FeaturesSwitcherProps {
slides: FeatureSlideItem[];
className?: string;
onTab?: (label: string) => void
}

export const FeaturesSwitcher: FC<FeaturesSwitcherProps> = ({ slides, className }) => {
export const FeaturesSwitcher: FC<FeaturesSwitcherProps> = ({ slides, className, onTab }) => {
const textCn = useTextStyles();
const [currentSlideIndex, setCurrentSlideIndex] = useState(0);

const onSelect = useCallback((index: number, id: string) => {
setCurrentSlideIndex(index);

if (onTab) {
onTab(id);
}
}, []);

return (
<div className={classNames(styles.slideshow, className)}>
<div className={styles.slidesPanel}>
Expand All @@ -59,7 +75,7 @@ export const FeaturesSwitcher: FC<FeaturesSwitcherProps> = ({ slides, className
<button
type="button"
tabIndex={0}
onClick={() => setCurrentSlideIndex(i)}
onClick={() => onSelect(i, slide.id)}
className={classNames(styles.tab, i === currentSlideIndex ? styles.tabActive : '')}
>

Expand Down Expand Up @@ -94,7 +110,7 @@ export const FeaturesSwitcher: FC<FeaturesSwitcherProps> = ({ slides, className
: styles.slideHidden
)}
>
<CustomSlide key={slide.id} {...slide} />
<CustomSlide key={slide.id} label={slide.title.toString()} {...slide} />
</div>
))}
</div>
Expand Down
81 changes: 66 additions & 15 deletions blocks/server-side/hero/hero.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';

import cn from 'classnames';

Expand All @@ -13,49 +13,100 @@ import Img from 'next/image';
import Link from 'next/link';

import heroImg from './images/hero-graphics.webp'
import { trackEvent } from '../../../utils/event-logger';

export const ServerSideHero: FC = ({}) => {

const textCn = useTextStyles();

const handleAnchorClick = useCallback((anchorName: string) => {
trackEvent({
eventAction: 'kt_server_side_hero_anchor',
eventLabel: anchorName
});
}, []);

const handleGetStartedClick = useCallback(() => {
trackEvent({
eventAction: 'kt_server_side_hero_get_started'
});
}, []);

return (
<div className={styles.wrapper} data-testid={'hero-block'}>

<Img className={styles.heroImage} src={heroImg} alt={'Server-side graphic'} width={1000} height={1000} />

<div className={cn('ktl-layout', 'ktl-layout--center')}>
<div className={styles.content}>
<h1 className={cn(textCn('rs-hero'), styles.heroTitle)} data-testid={'hero-block-title'}>
Modern backend<br /> development <br /> with Kotlin
Modern backend
<br /> development <br /> with Kotlin
</h1>

<p className={cn(textCn('rs-subtitle-2'), styles.heroSubtitle)} data-testid={'hero-block-subtitle'}>
Kotlin is a perfect fit for building backends on the JVM, including AI-powered services, and is trusted by major tech companies worldwide.
Kotlin is a perfect fit for building backends on the JVM, including AI-powered services, and is
trusted by major tech companies worldwide.
</p>

<div className={styles.featuresList}>

<Link href={'#safety'} className={styles.feature} data-testid={'hero-block-anchor'}>
<Link
href={'#safety'}
className={styles.feature}
data-testid={'hero-block-anchor'}
onClick={() => handleAnchorClick('safety')}
>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>Safety</p>
</Link>
<Link href={'#performance'} className={styles.feature} data-testid={'hero-block-anchor'}>
<Link
href={'#performance'}
className={styles.feature}
data-testid={'hero-block-anchor'}
onClick={() => handleAnchorClick('performance')}
>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>Runtime performance</p>
</Link>
<Link href={'#ecosystem'} className={styles.feature} data-testid={'hero-block-anchor'}>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>Access to the rich JVM ecosystem</p>
<Link
href={'#ecosystem'}
className={styles.feature}
data-testid={'hero-block-anchor'}
onClick={() => handleAnchorClick('ecosystem')}
>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>
Access to the rich JVM ecosystem
</p>
</Link>
<Link href={'#tools'} className={styles.feature} data-testid={'hero-block-anchor'}>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>Great developer experience</p>
<Link
href={'#tools'}
className={styles.feature}
data-testid={'hero-block-anchor'}
onClick={() => handleAnchorClick('tools')}
>
<p className={cn(textCn('rs-subtitle-2'), styles.featureTitle)}>
Great developer experience
</p>
</Link>

</div>

<div className={styles.buttons}>
<Button mode={'rock'} size={'l'} href={'#get-started'} data-testid={'hero-block-get-started-link'}>Get started</Button>
<Button mode={'outline'} size={'l'} href={'https://kotlinlang.org/lp/server-side/case-studies/'} data-testid={'hero-block-case-studies-link'}>Who uses Kotlin</Button>
<Button
mode={'rock'}
size={'l'}
href={'#get-started'}
data-testid={'hero-block-get-started-link'}
onClick={handleGetStartedClick}
>
Get started
</Button>
<Button
mode={'outline'}
size={'l'}
href={'https://kotlinlang.org/lp/server-side/case-studies/'}
data-testid={'hero-block-case-studies-link'}
>
Who uses Kotlin
</Button>
</div>
</div>

</div>
</div>
);
Expand Down
Loading