Files
blitzkit/packages/website-ue/src/components/Navbar.astro
T

168 lines
3.6 KiB
Plaintext
Raw Normal View History

2026-01-12 13:46:58 -06:00
---
import { BlitzKitIcon } from "../icons/BlitzKit";
2026-01-13 20:33:14 -06:00
import { LinkI18n } from "./LinkI18n";
2026-01-18 14:51:55 -06:00
import { Text } from "./Text";
import { api } from "../core/api/dynamic";
2026-01-18 18:38:26 -06:00
import { tools } from "../core/tools/tools";
import type { Tool } from "../core/tools/tools";
2026-01-13 20:33:14 -06:00
interface Props {
locale: string;
2026-01-18 18:38:26 -06:00
selectedTool?: Tool;
2026-01-13 20:33:14 -06:00
}
2026-01-18 18:38:26 -06:00
const { locale, selectedTool } = Astro.props;
2026-01-18 14:51:55 -06:00
const strings = await api.strings(locale);
2026-01-18 18:38:26 -06:00
const toolsArray = Object.values(tools);
const toolsSorted =
selectedTool === undefined
? toolsArray
: [selectedTool, ...toolsArray.filter((tool) => tool !== selectedTool)];
2026-01-12 13:46:58 -06:00
---
<style>
2026-01-15 13:48:37 -06:00
#navbar {
2026-01-18 15:14:26 -06:00
position: fixed;
bottom: 0;
2026-01-13 20:33:14 -06:00
left: 0;
2026-01-18 15:14:26 -06:00
width: 100%;
2026-01-12 13:46:58 -06:00
display: flex;
2026-01-18 15:14:26 -06:00
flex-direction: column;
align-items: center;
2026-01-12 13:46:58 -06:00
z-index: 1;
2026-01-18 15:14:26 -06:00
background-color: var(--gray-a5);
2026-01-15 13:48:37 -06:00
box-shadow: var(--shadow-none);
2026-01-18 15:14:26 -06:00
backdrop-filter: var(--blur-glass) brightness(5%);
border-radius: var(--space-4) var(--space-4) 0 0;
2026-01-15 13:48:37 -06:00
transition-duration: var(--duration-brief);
&[data-sticky="true"] {
2026-01-18 15:14:26 -06:00
transform: translateY(100%);
}
.bar {
width: 100%;
max-width: var(--space-6);
height: var(--space-2);
margin-top: var(--space-3);
background-color: var(--white-a2);
border-radius: var(--max-size);
2026-01-15 13:48:37 -06:00
}
2026-01-13 20:33:14 -06:00
.content {
2026-01-18 15:14:26 -06:00
width: 100%;
2026-01-13 20:33:14 -06:00
max-width: calc(var(--page-width) + 2 * var(--space-4));
2026-01-12 13:46:58 -06:00
2026-01-18 18:38:26 -06:00
display: grid;
grid-template-columns: repeat(4, 1fr);
2026-01-12 13:46:58 -06:00
2026-01-18 14:51:55 -06:00
.action {
flex: 1;
2026-01-12 13:46:58 -06:00
display: flex;
2026-01-18 14:51:55 -06:00
flex-direction: column;
align-items: center;
padding: var(--space-3);
gap: var(--space-2);
2026-01-12 13:46:58 -06:00
2026-01-18 14:51:55 -06:00
cursor: pointer;
color: var(--color-regular);
text-decoration: none;
color: var(--gray-11);
2026-01-13 20:33:14 -06:00
2026-01-18 14:51:55 -06:00
&[data-selected="true"] {
color: var(--accent-12);
2026-01-13 20:33:14 -06:00
2026-01-18 14:51:55 -06:00
.selector {
background-color: var(--accent-5);
2026-01-13 20:33:14 -06:00
}
2026-01-18 14:51:55 -06:00
.label {
color: var(--gray-12) !important;
}
}
.selector {
padding: var(--space-2);
border-radius: var(--max-size);
display: flex;
justify-content: center;
width: 100%;
max-width: var(--space-6);
2026-01-13 20:33:14 -06:00
.icon {
height: 1.25em;
2026-01-18 18:38:26 -06:00
width: 100%;
2026-01-13 20:33:14 -06:00
vertical-align: top;
}
2026-01-12 13:46:58 -06:00
}
2026-01-18 14:51:55 -06:00
.label {
font-size: var(--font-size-minor);
}
2026-01-12 13:46:58 -06:00
}
}
}
</style>
2026-01-15 13:48:37 -06:00
<script>
const navbar = document.getElementById("navbar")!;
2026-01-18 15:14:26 -06:00
let lastScrollY = window.scrollY;
2026-01-15 13:48:37 -06:00
function handleScroll() {
2026-01-18 15:14:26 -06:00
const dy = window.scrollY - lastScrollY;
lastScrollY = window.scrollY;
navbar.dataset.sticky = `${dy > 0}`;
2026-01-15 13:48:37 -06:00
}
handleScroll();
window.addEventListener("scroll", handleScroll);
</script>
<div id="navbar">
2026-01-18 15:14:26 -06:00
<div class="bar"></div>
2026-01-13 20:33:14 -06:00
<div class="content">
2026-01-18 18:38:26 -06:00
<LinkI18n
{locale}
href="/"
className="action"
tabIndex={0}
data-selected={selectedTool === undefined}
>
2026-01-18 14:51:55 -06:00
<div class="selector">
2026-01-13 20:33:14 -06:00
<BlitzKitIcon className="icon" />
</div>
2026-01-18 14:51:55 -06:00
<Text lowContrast className="label">{strings.navbar.home}</Text>
</LinkI18n>
2026-01-13 20:33:14 -06:00
2026-01-18 18:38:26 -06:00
{
toolsSorted.map(({ id, Icon }) => (
<LinkI18n
key={id}
{locale}
href={`/${id}`}
className="action"
tabIndex={0}
data-selected={selectedTool?.id === id}
>
<div class="selector">
<Icon className="icon" />
</div>
2026-01-18 17:55:38 -06:00
2026-01-18 18:38:26 -06:00
<Text lowContrast className="label">
{strings.tools[id as keyof typeof strings.tools].name}
</Text>
</LinkI18n>
))
}
2026-01-12 13:46:58 -06:00
</div>
</div>