blocks/community/layout/community-layout.tsx (130 lines of code) (raw):
import React, { FC, useCallback, useMemo } from 'react';
import Head from 'next/head';
import GlobalHeader, { COMMUNITY_TITLE, COMMUNITY_URL } from '@jetbrains/kotlin-web-site-ui/out/components/header';
import GlobalFooter from '@jetbrains/kotlin-web-site-ui/out/components/footer';
import TopMenu from '@jetbrains/kotlin-web-site-ui/out/components/top-menu';
import { CtaBlock } from '@jetbrains/kotlin-web-site-ui/out/components/cta-block-v2';
import Button from '@rescui/button';
import { ThemeProvider } from '@rescui/ui-contexts';
import { useRouter } from 'next/router';
import { StickyHeader } from '../../../components/sticky-header/sticky-header';
import styles from './community-layout.module.css';
import releasesDataRaw from '../../../data/releases.yml';
import searchConfig from '../../../search-config.json';
import { CommunityAddEvent } from '../event-list/event-list';
const releasesData: ReleasesData = releasesDataRaw as ReleasesData;
const TOP_MENU_ITEMS = [
{
url: '/community/',
title: 'Overview'
},
{
url: '/community/user-groups/',
title: 'Kotlin User Groups'
}
];
interface CommunityLayoutProps {
title: string;
description?: string;
ogImageName?: string;
children: React.ReactNode;
}
export const CommunityLayout: FC<CommunityLayoutProps> = ({ title, ogImageName, description, children }) => {
const theme = 'dark';
const router = useRouter();
const pathname = addTrailingSlash(router.pathname);
let items = TOP_MENU_ITEMS;
let activeIndex = useMemo(
() => items.map((item) => item.url).indexOf(pathname),
[pathname, items]
);
const linkHandler = useCallback(
(event, url) => {
event.preventDefault();
router.push(url);
},
[router]
);
const ogImagePath = useMemo(
() => `https://kotlinlang.org/assets/images/open-graph/${ogImageName ? ogImageName : 'general.png'}`,
[ogImageName]
);
const ogImageTwitterPath = useMemo(
() => (ogImageName ? ogImagePath : 'https://kotlinlang.org/assets/images/twitter/general.png'),
[ogImageName, ogImagePath]
);
if (activeIndex === -1) {
activeIndex = items.length;
items = [...items, {
url: router.pathname + '/',
title,
}];
}
return (
<>
<Head>
<title>{title}</title>
<meta property="og:title" content={title} />
<meta property="og:type" content="website" />
<meta property="og:url" content={'https://kotlinlang.org' + router.pathname} />
<meta property="og:image" content={ogImagePath} />
{description && <meta property="og:description" content={description} />}
<meta property="og:site_name" content="Kotlin" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@kotlin" />
<meta name="twitter:title" content={title} />
{description && <meta name="twitter:description" content={description} />}
<meta name="twitter:image:src" content={ogImageTwitterPath} />
</Head>
<GlobalHeader
currentUrl={COMMUNITY_URL}
currentTitle={COMMUNITY_TITLE}
productWebUrl={releasesData.latest.url}
hasSearch={true}
searchConfig={searchConfig}
/>
<StickyHeader>
<div className={styles.sticky}>
<TopMenu
className={styles.topMenu}
homeUrl={COMMUNITY_URL}
title={COMMUNITY_TITLE}
activeIndex={activeIndex}
items={items}
linkHandler={linkHandler}
mobileOverview={false}
>
{pathname === '/community/events/' && (
<CommunityAddEvent
className={styles.add}
size="s"
href="https://github.com/JetBrains/kotlin-web-site/blob/master/README.md#community-events"
/>
)}
</TopMenu>
</div>
</StickyHeader>
{children}
<CtaBlock
topTitle={'Help us improve'}
buttons={
<Button size="l" mode="rock" href="mailto:kug@jetbrains.com">
Write to us
</Button>
}
mainTitle={
<>
Give us your feedback or ask any questions
<br />
you have about the Kotlin community
</>
}
/>
<ThemeProvider theme={theme}>
<GlobalFooter />
</ThemeProvider>
</>
);
};
function addTrailingSlash(path: string): string {
return path.endsWith('/') ? path : `${path}/`;
}