feat: home page

This commit is contained in:
TrèsAbhi committed 2025-05-28 11:28:22 -05:00
1 parent 64d12bba8b
commit 4129a1964f
21 files changed
+425 -24

No files matched your search

@@ -0,0 +1,156 @@
---
import { Code, Flex, Heading, Text } from '@radix-ui/themes';
import { resolveBranchName } from '../core/blitzkit/branches';
import { getStrings } from '../core/i18n/getStrings';
import { literals } from '@blitzkit/i18n/src/literals';
interface Props {
locale: string;
}
const { locale } = Astro.props;
const strings = await getStrings(locale);
const branchName = resolveBranchName();
const isBranchNamed = branchName !== undefined;
---
<style>
#home-hero {
--p-1: 0%;
--p-2: 0%;
--p-3: 0%;
--p-4: 0%;
--p-7: 0%;
--g-1-dark: var(--blue-3);
--g-1-light: var(--blue-7);
--g-2-dark: var(--violet-3);
--g-2-light: var(--violet-7);
--g-3-dark: var(--purple-3);
--g-3-light: var(--purple-7);
--g-4-dark: var(--crimson-3);
--g-4-light: var(--crimson-7);
--g-7-dark: var(--tomato-3);
--g-7-light: var(--tomato-7);
--g-1: color-mix(in srgb, var(--g-1-dark), var(--g-1-light) var(--p-1));
--g-2: color-mix(in srgb, var(--g-2-dark), var(--g-2-light) var(--p-2));
--g-3: color-mix(in srgb, var(--g-3-dark), var(--g-3-light) var(--p-3));
--g-4: color-mix(in srgb, var(--g-4-dark), var(--g-4-light) var(--p-4));
--g-7: color-mix(in srgb, var(--g-7-dark), var(--g-7-light) var(--p-7));
background: linear-gradient(
45deg,
var(--g-1),
var(--g-2),
var(--g-3),
var(--g-4),
var(--g-7)
);
}
#home-hero[data-variant='pride'] {
--g-1-dark: var(--crimson-3);
--g-1-light: var(--crimson-7);
--g-2-dark: var(--orange-3);
--g-2-light: var(--orange-7);
--g-3-dark: var(--yellow-3);
--g-3-light: var(--yellow-7);
--g-4-dark: var(--blue-3);
--g-4-light: var(--blue-7);
--g-7-dark: var(--purple-3);
--g-7-light: var(--purple-7);
}
#home-hero[data-variant='spooky'] {
--g-1-dark: var(--orange-3);
--g-1-light: var(--orange-7);
--g-2-dark: var(--tomato-3);
--g-2-light: var(--tomato-7);
--g-3-dark: var(--orange-3);
--g-3-light: var(--orange-7);
--g-4-dark: var(--tomato-3);
--g-4-light: var(--tomato-7);
--g-7-dark: var(--orange-3);
--g-7-light: var(--orange-7);
}
</style>
<script>
import { clamp, times } from 'lodash-es';
const n = 5;
const homeHero = document.getElementById('home-hero');
if (homeHero) {
switch (new Date().getMonth()) {
case 5:
homeHero.dataset.variant = 'pride';
break;
case 9:
homeHero.dataset.variant = 'spooky';
break;
}
window.addEventListener('pointermove', (event) => {
const x = event.clientX / window.innerWidth;
const c = clamp(
(1 -
(event.clientY + homeHero.getBoundingClientRect().top) /
window.innerHeight) **
2,
0,
1,
);
// https://www.desmos.com/calculator/ndz2poxk32
times(n, (i) => {
const p = c * clamp(-n * Math.abs(x - i / (n - 1)) + 1, 0, 3);
homeHero.style.setProperty(`--p-${i + 1}`, `${p * 100}%`);
});
});
}
</script>
<Flex
id="home-hero"
align="center"
justify="center"
position="relative"
px="4"
py="9"
overflow="hidden"
>
<Flex
direction="column"
gap="6"
align="center"
justify="center"
position="relative"
width="100%"
>
<Flex direction="column" align="center" gap="1">
<Heading size={{ initial: '8', xs: '9' }} weight="bold" align="center">
<Flex align="center" gap={{ initial: '2', xs: '4' }}>
BlitzKit
{
isBranchNamed && (
<Code
size={{ initial: '7', xs: '8' }}
color="gray"
variant="outline"
>
{branchName}
</Code>
)
}
</Flex>
</Heading>
<Text color="gray" align="center" size="4"
>{literals(strings.website.home.hero.credit, ['TrèsAbhi'])}</Text
>
</Flex>
</Flex>
</Flex>
@@ -0,0 +1,136 @@
---
import { assertSecret } from '@blitzkit/core';
import { CaretRightIcon } from '@radix-ui/react-icons';
import { Box, Button, Code, Flex, Heading, Text } from '@radix-ui/themes';
import type { Tool } from '../constants/tools';
import { getStrings } from '../core/i18n/getStrings';
import { LinkI18n } from './LinkI18n';
interface Props {
tool: Tool;
locale: string;
}
const { tool, locale } = Astro.props;
const strings = await getStrings(locale);
const disabled = false;
const toolStrings =
strings.website.tools[
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
];
---
<style>
.container {
border-radius: var(--radius-2);
background-size: cover;
background-position: center;
height: 16rem;
&[data-disabled='true'] {
opacity: 0.25;
}
&[data-significant='true'] {
height: min(20rem, 50vh);
flex: 1;
}
}
.link {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
color: inherit;
}
</style>
<Flex
style={{ backgroundImage: `url(/assets/tool-backgrounds/${tool.id}.webp)` }}
data-disabled={disabled}
data-significant={tool.significant}
className="container"
position="relative"
overflow="hidden"
flexGrow={tool.significant ? undefined : '1'}
flexBasis={tool.significant ? undefined : { initial: undefined, sm: '0' }}
>
<LinkI18n
{locale}
className="link"
underline="none"
href={disabled ? '#' : `/${tool.id}`}
>
<Box
flexGrow="1"
style={{
backgroundImage: `url(/assets/tool-backgrounds/${tool.id}.webp)`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
/>
<Flex
px={{ initial: '6', md: tool.significant ? '8' : '6' }}
py={{ initial: '4', sm: tool.significant ? '6' : '4' }}
gap="4"
align="center"
justify="between"
width="100%"
direction={{ initial: 'column', xs: 'row' }}
style={{
backgroundColor: 'var(--color-panel-translucent)',
backdropFilter: 'blur(64px)',
WebkitBackdropFilter: 'blur(64px)',
}}
>
<Flex
direction="column"
justify="center"
align={{ initial: 'center', xs: 'start' }}
>
<Heading
align={{ initial: 'center', sm: 'left' }}
size={{ initial: '6', sm: tool.significant ? '7' : '5' }}
weight="medium"
>
{toolStrings.name}
</Heading>
<Text
align={{ initial: 'center', sm: 'left' }}
size={{ initial: '3', sm: tool.significant ? '4' : '3' }}
color="gray"
>
{
disabled ? (
<>
Unavailable on{' '}
<Code>{assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH)}</Code>
</>
) : (
toolStrings.description
)
}
</Text>
</Flex>
{
!disabled && (
<Button
highContrast={tool.button.contrast}
size={{
initial: undefined,
sm: tool.significant ? '3' : undefined,
}}
color={tool.button.color}
style={{ cursor: 'inherit' }}
>
{toolStrings.button}
<CaretRightIcon />
</Button>
)
}
</Flex>
</LinkI18n>
</Flex>
+21 -21
View File
@@ -1,6 +1,6 @@
import type { ButtonProps } from '@radix-ui/themes';
interface Tool {
export interface Tool {
id: string;
enabled: boolean;
strings?: string;
@@ -8,7 +8,7 @@ interface Tool {
button: { color: ButtonProps['color']; contrast?: boolean };
}
export const tanks: Tool = {
export const tanksTool: Tool = {
id: 'tanks',
enabled: true,
strings: 'tankopedia',
@@ -16,70 +16,70 @@ export const tanks: Tool = {
button: { color: 'purple' },
};
export const compare: Tool = {
export const compareTool: Tool = {
id: 'compare',
enabled: true,
button: { color: 'crimson' },
};
export const performance: Tool = {
export const performanceTool: Tool = {
id: 'performance',
enabled: true,
button: { color: 'jade' },
};
export const guess: Tool = {
export const guessTool: Tool = {
id: 'guess',
enabled: false,
button: { color: 'bronze' },
};
export const charts: Tool = {
export const chartsTool: Tool = {
id: 'charts',
enabled: false,
button: { color: 'bronze' },
};
export const gallery: Tool = {
export const galleryTool: Tool = {
id: 'gallery',
enabled: true,
button: { color: 'gold' },
};
export const session: Tool = {
export const sessionTool: Tool = {
id: 'session',
enabled: true,
button: { color: 'blue' },
};
export const tierList: Tool = {
export const tierListTool: Tool = {
id: 'tier-list',
enabled: true,
strings: 'tier_list',
button: { color: 'orange' },
};
export const embed: Tool = {
export const embedTool: Tool = {
id: 'embed',
enabled: true,
button: { color: 'cyan' },
};
export const rating: Tool = {
export const ratingTool: Tool = {
id: 'rating',
enabled: false,
button: { color: 'orange' },
};
export const tools: Tool[] = [
tanks,
compare,
performance,
guess,
charts,
gallery,
session,
tierList,
embed,
rating,
tanksTool,
compareTool,
performanceTool,
guessTool,
chartsTool,
galleryTool,
sessionTool,
tierListTool,
embedTool,
ratingTool,
];
@@ -1,6 +1,6 @@
import { assertSecret } from 'packages/core/src';
export function resolveBranchName(locale: string) {
export function resolveBranchName() {
if (assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH) === 'main') {
return undefined;
}
@@ -1,6 +1,18 @@
---
import { AstroSeo } from '@astrolib/seo';
import locales from '@blitzkit/i18n/locales.json';
import { ExternalLinkIcon } from '@radix-ui/react-icons';
import { Flex, Link } from '@radix-ui/themes';
import type { GetStaticPaths } from 'astro';
import { literals } from 'packages/i18n/src';
import HomeHero from '../../components/HomeHero.astro';
import ToolCard from '../../components/ToolCard.astro';
import { type Tool, tools } from '../../constants/tools';
import { getStrings } from '../../core/i18n/getStrings';
import { Var } from '../../core/radix/var';
import BaseLayout from '../../layouts/BaseLayout.astro';
const MAX_TOOLS_PER_ROW = 2;
export const getStaticPaths = (() => {
return locales.supported.map(({ locale, blitz }) => ({
@@ -10,6 +22,92 @@ export const getStaticPaths = (() => {
}) satisfies GetStaticPaths;
const { locale } = Astro.props;
const strings = await getStrings(locale);
const rows: Tool[][] = [];
toolLoop: for (const tool of tools.filter((tool) => tool.enabled)) {
if (tool.significant) {
rows.push([tool]);
} else {
for (const row of rows) {
if (!row[0]?.significant && row.length < MAX_TOOLS_PER_ROW) {
row.push(tool);
continue toolLoop;
}
}
rows.push([tool]);
}
}
---
Hello in {locale}!
<AstroSeo
title="BlitzKit"
description={strings.website.home.seo_description}
canonical={Astro.url.href}
openGraph={{
url: Astro.url.href,
title: 'BlitzKit',
description: strings.website.home.seo_description,
site_name: 'BlitzKit',
}}
twitter={{ cardType: 'summary_large_image' }}
/>
<BaseLayout {locale}>
<Flex direction="column" gap="8" pb="9">
<HomeHero {locale} />
{
locale !== locales.default && (
<Flex justify="center">
<Link
href="https://crowdin.com/project/blitzkrieg"
target="_blank"
underline="hover"
color="gray"
highContrast
style={{
color: Var('gray-3'),
}}
>
<Flex
align="center"
px="5"
py="4"
gap="3"
style={{
backgroundImage: 'url(/assets/morphing-diamonds.svg)',
borderRadius: Var('radius-full'),
boxShadow: Var('shadow-2'),
}}
>
{literals(strings.website.home.help_translate, [
'BlitzKit',
strings.common.locales[
locale as keyof typeof strings.common.locales
],
])}
<ExternalLinkIcon />
</Flex>
</Link>
</Flex>
)
}
<Flex px="4" justify="center" gap="4">
<Flex maxWidth="80rem" flexGrow="1" gap="4" direction="column">
{
rows.map((row) => (
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
{row.map((tool) => (
<ToolCard {locale} tool={tool} />
))}
</Flex>
))
}
</Flex>
</Flex>
</Flex>
</BaseLayout>