Files
blitzkit/packages/website/src/components/Navbar.astro
T
2025-01-06 20:09:11 -06:00

288 lines
7.6 KiB
Plaintext

---
import { assertSecret, imgur, ImgurSize } from '@blitzkit/core';
import {
Cross1Icon,
DiscordLogoIcon,
GearIcon,
HamburgerMenuIcon,
} from '@radix-ui/react-icons';
import {
Box,
Code,
Flex,
Grid,
IconButton,
Link,
ScrollArea,
Separator,
Text,
} from '@radix-ui/themes';
import { resolveBranchName } from '../core/blitzkit/branches';
import { homeTool, TOOLS } from '../constants/tools';
import { LinkI18n } from './LinkI18n';
import { getStrings } from '../core/i18n/getStrings';
const toolsFiltered = TOOLS.filter((tool) => !('href' in tool));
const tools = [homeTool, ...toolsFiltered];
const { locale } = Astro.params;
const branchName = resolveBranchName(locale);
const isBranchNamed = branchName !== undefined;
const strings = getStrings(locale);
---
<style>
.navbar {
height: var(--navbar-height);
top: 0;
z-index: 1;
position: sticky;
}
.expander {
--navbar-height: 48px;
/* overflow: hidden; */
transition-duration: 250ms;
width: 100%;
backdrop-filter: blur(4rem) brightness(0.75);
-webkit-backdrop-filter: blur(4rem) brightness(0.75);
}
.expander[data-expanded='false'] {
height: var(--navbar-height);
}
.expander[data-expanded='false'] *[data-expanded] {
display: none;
}
.expander[data-expanded='true'] {
height: 100vh;
}
.expander[data-expanded='true'] *[data-closed] {
display: none;
}
.expander div[data-radix-scroll-area-viewport] {
overflow-y: scroll !important;
overscroll-behavior: contain;
}
.hamburger {
display: inline-flex;
}
.tools {
display: none;
}
@media (min-width: 768px) {
.hamburger {
display: none;
}
.tools {
display: flex;
}
.expander {
max-height: var(--navbar-height) !important;
}
}
</style>
<script>
const expander = document.querySelector<HTMLDivElement>('.expander');
const hamburger = document.querySelector<HTMLButtonElement>('.hamburger');
expander?.addEventListener('click', () => {
expander.dataset.expanded = 'false';
});
hamburger?.addEventListener('click', (event) => {
if (!expander) return;
event.stopPropagation();
expander.dataset.expanded = `${expander.dataset.expanded === 'false'}`;
});
</script>
<Flex className="navbar">
<Flex className="expander" data-expanded="false" direction="column" gap="2">
<Flex justify="center">
<Flex flexGrow="1" maxWidth="1024px" p="3" align="center">
<LinkI18n
{locale}
color="gray"
highContrast
href="/"
underline="hover"
weight="bold"
>
<Flex align="center" gap="1">
BlitzKit
{
isBranchNamed && (
<Code color="gray" size="1" variant="outline">
{branchName}
</Code>
)
}
</Flex>
</LinkI18n>
<Box flexGrow="1" />
<Flex align="center" gap="2" justify="center" className="tools">
{
toolsFiltered.map((tool, index) => {
const unavailableOnBranch = tool.branches?.every(
(branch) =>
branch !== assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH),
);
const selected = Astro.url.pathname.includes(`/tools/${tool.id}`);
const toolStrings =
strings.website.tools[
(tool.stringsId ??
tool.id) as keyof typeof strings.website.tools
];
if (unavailableOnBranch) return null;
return (
<Fragment key={tool.id}>
{index > 0 && <Separator orientation="vertical" size="1" />}
<LinkI18n
{locale}
color="gray"
highContrast={selected}
size="2"
href={`/tools/${tool.id}`}
underline={selected ? 'always' : 'hover'}
>
{toolStrings.name}
</LinkI18n>
</Fragment>
);
})
}
</Flex>
<Box flexGrow="1" />
<Flex align="center" gap="3">
<Link
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="https://discord.gg/nDt7AjGJQH"
underline="none"
target="_blank"
>
<DiscordLogoIcon />
</Link>
<LinkI18n
{locale}
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="/settings"
underline="none"
>
<GearIcon />
</LinkI18n>
<!-- <NavbarAccount client:idle /> -->
<IconButton variant="ghost" color="gray" className="hamburger">
<Cross1Icon data-expanded />
<HamburgerMenuIcon data-closed />
</IconButton>
</Flex>
</Flex>
</Flex>
<ScrollArea scrollbars="vertical" style={{ height: '100%', width: '100%' }}>
<Grid
columns="repeat(auto-fill, minmax(12rem, 1fr))"
flow="dense"
gap="2"
width="100%"
p="3"
pt="0"
>
{
tools.map((tool) => {
const unavailableOnBranch = tool.branches?.every(
(branch) =>
branch !== assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH),
);
const toolStrings =
strings.website.tools[
(tool.stringsId ??
tool.id) as keyof typeof strings.website.tools
];
if (unavailableOnBranch) return null;
return (
<Flex
key={tool.id}
style={{
position: 'relative',
borderRadius: 'var(--radius-2)',
overflow: 'hidden',
backgroundImage: `url(${imgur(tool.image, {
format: 'jpeg',
size: ImgurSize.MediumThumbnail,
})})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
aspectRatio: '2 / 1',
}}
>
<LinkI18n
{locale}
href={tool.id.length === 0 ? '/' : `/tools/${tool.id}`}
style={{
display: 'flex',
width: '100%',
height: '100%',
flexDirection: 'column',
textDecoration: 'none',
color: 'inherit',
}}
>
<Box
flexGrow="1"
style={{
backgroundImage: `url(${imgur(tool.image, {
format: 'jpeg',
size: ImgurSize.MediumThumbnail,
})})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
/>
<Flex
p="2"
align="center"
width="100%"
style={{
backgroundColor: 'var(--color-panel-translucent)',
backdropFilter: 'blur(4rem)',
WebkitBackdropFilter: 'blur(4rem)',
}}
>
<Text>{toolStrings.name}</Text>
</Flex>
</LinkI18n>
</Flex>
);
})
}
</Grid>
</ScrollArea>
</Flex>
</Flex>