aboutsummaryrefslogtreecommitdiff
path: root/apps/website/src
diff options
context:
space:
mode:
Diffstat (limited to 'apps/website/src')
-rw-r--r--apps/website/src/components/base/Header.astro57
-rw-r--r--apps/website/src/components/base/Navbar.astro21
-rw-r--r--apps/website/src/components/base/NavbarElement.astro86
-rw-r--r--apps/website/src/components/base/ScreenOverlay.astro16
-rw-r--r--apps/website/src/components/base/ScrollbarOverlayContainer.astro51
-rw-r--r--apps/website/src/components/base/Tag.astro14
-rw-r--r--apps/website/src/components/icons/ChevronDown.astro16
-rw-r--r--apps/website/src/components/logos/Logo.astro52
-rw-r--r--apps/website/src/layouts/Layout.astro38
-rw-r--r--apps/website/src/pages/index.astro10
-rw-r--r--apps/website/src/styles/global.css11
-rw-r--r--apps/website/src/types/Config.d.ts34
12 files changed, 406 insertions, 0 deletions
diff --git a/apps/website/src/components/base/Header.astro b/apps/website/src/components/base/Header.astro
new file mode 100644
index 0000000..ad8267b
--- /dev/null
+++ b/apps/website/src/components/base/Header.astro
@@ -0,0 +1,57 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+const sizes = {
+ "xl": "h1",
+ "lg": "h2",
+ "md": "h3",
+ "sm": "h4",
+ "xs": "h5",
+ "xxs": "h6"
+};
+
+type Headers = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
+
+interface Props extends HTMLAttributes<Headers> {
+ size: keyof typeof sizes;
+}
+
+const { size, ...attr } = Astro.props;
+const Element = sizes[size] as any; // Unfortunately gotta do this
+---
+
+<Element {...attr}>
+ <slot />
+</Element>
+
+<style>
+ h1 {
+ font-size: theme("fontSize.header-lg");
+ font-weight: 700;
+ }
+
+ h2 {
+ font-size: theme("fontSize.header");
+ font-weight: 700;
+ }
+
+ h3 {
+ font-size: theme("fontSize.header-sm");
+ font-weight: 600;
+ }
+
+ h4 {
+ font-size: theme("fontSize.body-lg");
+ font-weight: 500;
+ }
+
+ h5 {
+ font-size: theme("fontSize.body");
+ font-weight: 500;
+ }
+
+ h6 {
+ font-size: theme("fontSize.body-sm");
+ font-weight: 500;
+ }
+</style> \ No newline at end of file
diff --git a/apps/website/src/components/base/Navbar.astro b/apps/website/src/components/base/Navbar.astro
new file mode 100644
index 0000000..f4f2f49
--- /dev/null
+++ b/apps/website/src/components/base/Navbar.astro
@@ -0,0 +1,21 @@
+---
+import config from "config";
+import type { Config } from "@webtypes/Config";
+import NavbarElement from "./NavbarElement.astro";
+
+---
+
+<div class="w-full flex flex-row justify-center h-screen max-h-[110px] px-3">
+ <nav class="w-full max-w-[1080px] flex flex-col md:flex-row justify-between items-center">
+ <ul class="flex flex-row justify-start gap-4">
+ {(config as Config).navbar.left.map((element, index) => (
+ <NavbarElement {element} {index} />
+ ))}
+ </ul>
+ <ul class="flex flex-row justify-end gap-4">
+ {(config as Config).navbar.right.map((element, index) => (
+ <NavbarElement {element} {index} />
+ ))}
+ </ul>
+ </nav>
+</div> \ No newline at end of file
diff --git a/apps/website/src/components/base/NavbarElement.astro b/apps/website/src/components/base/NavbarElement.astro
new file mode 100644
index 0000000..4f82e8b
--- /dev/null
+++ b/apps/website/src/components/base/NavbarElement.astro
@@ -0,0 +1,86 @@
+---
+import ChevronDown from "@components/icons/ChevronDown.astro";
+import type { LogoType, NavbarElement } from "@webtypes/Config";
+import ScreenOverlay from "./ScreenOverlay.astro";
+import Header from "./Header.astro";
+import Tag from "./Tag.astro";
+import Logo from "@components/logos/Logo.astro";
+import ScrollbarOverlayContainer from "./ScrollbarOverlayContainer.astro";
+
+interface Props {
+ element: NavbarElement;
+ index: number;
+}
+
+const {
+ element,
+ index
+} = Astro.props;
+---
+
+<li class="sm:relative max-sm:overflow-hidden flex flex-row justify-center items-center text-center">
+ <label for={`navbar-input-${index}`} class="group">
+
+ {element.path ? (
+ <a href={element.path} class="p-2 flex flex-row justify-center items-center text-gray-700 hover:text-blue-500">
+ {element.text && element.text}
+ {element.logo && <Logo size={element.logo[1] < 0 ? undefined : element.logo[1]} logo={element.logo[0] as LogoType} />}
+ {element.dropdown && <ChevronDown />}
+ </a>
+ ) : (
+ <p class="p-2 flex flex-row justify-center items-center text-gray-700 hover:text-blue-500 cursor-default">
+ {element.text && element.text}
+ {element.logo && <Logo size={element.logo[1] < 0 ? undefined : element.logo[1]} logo={element.logo[0] as LogoType} />}
+ {element.dropdown && <ChevronDown />}
+ </p>
+ )}
+
+ {element.dropdown && (
+ <ScreenOverlay class="max-sm:group-focus-within:opacity-100" />
+ <input type="checkbox" id={`navbar-input-${index}`} class="peer appearance-none absolute">
+ <div class={`transition-opacity
+ absolute right-0 max-sm:bottom-0
+ max-sm:overflow-hidden
+ max-sm:max-h-[70vh] max-sm:h-screen max-sm:w-screen
+ pointer-events-none opacity-0
+
+ md:top-full md:right-0
+
+ group-focus-within:pointer-events-auto group-focus-within:opacity-100
+ focus-within:pointer-events-auto focus-within:opacity-100
+ hover:pointer-events-auto hover:opacity-100
+ `}>
+ <ScrollbarOverlayContainer class={`
+ bg-gray-50
+ rounded-t-lg md:rounded-lg
+ transition-transform
+ max-sm:translate-y-1/3 max-sm:left-0
+ group-focus-within:translate-y-0
+ max-h-full md:max-h-96 overflow-y-auto
+ `}>
+ <ul class="p-4">
+ {element.dropdown.map((item) => (
+ <li>
+ <a href={item.path} class="flex sm:min-w-[400px] sm:max-w-[400px]">
+ <div class="transition-colors text-left w-full flex flex-row justify-start rounded-md items-center px-6 py-4 gap-6 hover:bg-white-hover">
+ <div class="w-[36px]">
+ {item.logo && <Logo size={40} logo={item.logo} />}
+ </div>
+
+ <div class="flex flex-col justify-start items-start">
+ <div class="flex flex-row gap-2">
+ <Header size="sm" class="text-gray-800">{item.name}</Header>
+ {item.tag && <Tag>{item.tag}</Tag>}
+ </div>
+ <p class="text-sm text-gray-400 font-light">{item.description}</p>
+ </div>
+ </div>
+ </a>
+ </li>
+ ))}
+ </ul>
+ </ScrollbarOverlayContainer>
+ </div>
+ )}
+ </label>
+</li> \ No newline at end of file
diff --git a/apps/website/src/components/base/ScreenOverlay.astro b/apps/website/src/components/base/ScreenOverlay.astro
new file mode 100644
index 0000000..7be8bc5
--- /dev/null
+++ b/apps/website/src/components/base/ScreenOverlay.astro
@@ -0,0 +1,16 @@
+---
+import type { HTMLAttributes } from "astro/types";
+
+interface Props extends HTMLAttributes<"div"> {
+ zIndex?: number;
+}
+
+const {
+ zIndex = 0,
+ ...rest
+} = Astro.props;
+---
+
+<div class="pointer-events-none absolute left-0 top-0">
+ <div class={`transition-opacity fixed opacity-0 w-screen h-screen z-[${zIndex}] bg-black/30 ${rest.class}`} {...rest}></div>
+</div> \ No newline at end of file
diff --git a/apps/website/src/components/base/ScrollbarOverlayContainer.astro b/apps/website/src/components/base/ScrollbarOverlayContainer.astro
new file mode 100644
index 0000000..d8d315d
--- /dev/null
+++ b/apps/website/src/components/base/ScrollbarOverlayContainer.astro
@@ -0,0 +1,51 @@
+---
+import type { HTMLAttributes } from "astro/types";
+
+interface Props extends HTMLAttributes<"div"> {
+
+}
+
+const { ...attr } = Astro.props;
+---
+
+<div {...attr}>
+ <slot></slot>
+</div>
+
+<style>
+@media (hover: hover) {
+ div {
+
+ }
+
+ div::-webkit-scrollbar {
+ display: block;
+ width: 5px;
+ }
+
+ div::-webkit-scrollbar:hover {
+ opacity: 1;
+ }
+
+ div::-webkit-scrollbar-button {
+ display: none;
+ }
+
+ div::-webkit-scrollbar-track {
+ background-color: #00000000;
+ }
+
+ div::-webkit-scrollbar-track-piece {
+ background-color: #00000000;
+ }
+
+ div::-webkit-scrollbar-thumb {
+ background-color: #00000000;
+ border-radius: 24px;
+ }
+
+ div::-webkit-scrollbar-thumb:hover {
+ background-color: #00000040;
+ }
+}
+</style> \ No newline at end of file
diff --git a/apps/website/src/components/base/Tag.astro b/apps/website/src/components/base/Tag.astro
new file mode 100644
index 0000000..e6fd34f
--- /dev/null
+++ b/apps/website/src/components/base/Tag.astro
@@ -0,0 +1,14 @@
+---
+import type { HTMLAttributes } from "astro/types";
+
+interface Props extends HTMLAttributes<"span"> {}
+
+const { ...attr } = Astro.props;
+---
+
+<div class="transition-colors text-blue-500 hover:bg-blue-500/20 text-xs font-medium bg-blue-500/10 rounded-md flex flex-col justify-center items-center px-2 py-0.5">
+ <span {...attr}>
+ <slot></slot>
+ </span>
+</div>
+
diff --git a/apps/website/src/components/icons/ChevronDown.astro b/apps/website/src/components/icons/ChevronDown.astro
new file mode 100644
index 0000000..5cb98e4
--- /dev/null
+++ b/apps/website/src/components/icons/ChevronDown.astro
@@ -0,0 +1,16 @@
+---
+import type { HTMLAttributes } from 'astro/types';
+
+interface Props extends HTMLAttributes<"svg"> {
+ size?: number;
+}
+
+const {
+ size = 16,
+ ...attr
+} = Astro.props;
+---
+
+<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16" fill="none" {...attr}>
+ <path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
+</svg> \ No newline at end of file
diff --git a/apps/website/src/components/logos/Logo.astro b/apps/website/src/components/logos/Logo.astro
new file mode 100644
index 0000000..0532396
--- /dev/null
+++ b/apps/website/src/components/logos/Logo.astro
@@ -0,0 +1,52 @@
+---
+import type { LogoType } from "@webtypes/Config";
+import { dirname } from "path";
+import { fileURLToPath } from "url";
+import type { HTMLAttributes } from "astro/types";
+
+export interface Props extends HTMLAttributes<"svg"> {
+ logo: LogoType,
+ size?: number | [number, number],
+ silent?: boolean,
+}
+
+const {
+ logo,
+ silent = false,
+ size = undefined,
+ ...attr
+} = Astro.props;
+let svg: string | undefined;
+
+try {
+ if (logo == undefined) return;
+ const dir = dirname(fileURLToPath(import.meta.url)) + "/../../../public/media";
+ svg = (await import(`${dir}/${logo.replaceAll(".", "/")}.svg?raw` /* @vite-ignore */)).default;
+
+ if (svg == undefined) return;
+
+ if (typeof size == "number" || Array.isArray(size)) {
+ // SVG main element regex
+ const svgElementRegex = /<svg[^>]*>/;
+
+ svg = svg.replace(svgElementRegex, (match) => {
+ let newMatch = match;
+ if (typeof size == "number") {
+ newMatch = newMatch.replace(/width="[^"]*"/, `width="${size}"`);
+ newMatch = newMatch.replace(/height="[^"]*"/, `height="${size}"`);
+ } else if (Array.isArray(size)) {
+ newMatch = newMatch.replace(/width="[^"]*"/, `width="${size[0]}"`);
+ newMatch = newMatch.replace(/height="[^"]*"/, `height="${size[1]}"`);
+ }
+ return newMatch;
+ });
+ }
+
+ svg = svg.replace(/<svg/, `<svg ${Object.entries(attr).map(([key, value]) => `${key}="${value}"`).join(" ")}`);
+} catch (err) {
+ if (typeof silent != "boolean" || silent == false) console.error(err);
+}
+
+---
+
+<Fragment set:html={svg} />
diff --git a/apps/website/src/layouts/Layout.astro b/apps/website/src/layouts/Layout.astro
new file mode 100644
index 0000000..a648f08
--- /dev/null
+++ b/apps/website/src/layouts/Layout.astro
@@ -0,0 +1,38 @@
+---
+import "../styles/global.css";
+import Navbar from "../components/base/Navbar.astro";
+import Favicon from "/media/polyfrost/minimal_bg.svg?url";
+
+interface Props {
+ title?: string;
+ favicon?: string;
+}
+
+const {
+ title = 'Polyfrost',
+ favicon = Favicon
+} = Astro.props;
+---
+
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="description" content="Official website for Polyfrost." />
+ <meta name="viewport" content="width=device-width" />
+ <link rel="icon" type="image/svg+xml" href={favicon} />
+ <meta name="generator" content={Astro.generator} />
+
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
+
+ <title>{title}</title>
+ </head>
+
+ <body class="bg-white">
+ <Navbar />
+ <slot />
+
+ </body>
+</html>
diff --git a/apps/website/src/pages/index.astro b/apps/website/src/pages/index.astro
new file mode 100644
index 0000000..a484172
--- /dev/null
+++ b/apps/website/src/pages/index.astro
@@ -0,0 +1,10 @@
+---
+import Header from "@components/base/Header.astro";
+import Layout from "../layouts/Layout.astro";
+import Logo from "@components/logos/Logo.astro";
+---
+
+<Layout>
+ <Header size="xl">test</Header>
+ <Header size="md">Test</Header>
+</Layout>
diff --git a/apps/website/src/styles/global.css b/apps/website/src/styles/global.css
new file mode 100644
index 0000000..51f3c19
--- /dev/null
+++ b/apps/website/src/styles/global.css
@@ -0,0 +1,11 @@
+@tailwind base;
+
+* {
+ font-family: 'Poppins', sans-serif;
+}
+
+@layer base {
+ :focus-visible {
+ @apply outline-none ring ring-blue-500;
+ }
+} \ No newline at end of file
diff --git a/apps/website/src/types/Config.d.ts b/apps/website/src/types/Config.d.ts
new file mode 100644
index 0000000..82eb4d7
--- /dev/null
+++ b/apps/website/src/types/Config.d.ts
@@ -0,0 +1,34 @@
+import { type configConst } from "config";
+
+export type LogoType = typeof configConst.logos[number];
+
+export interface Project {
+ name: string,
+ description: string,
+ logo?: LogoType,
+ tag?: string,
+}
+
+export type NavbarDropdown = {
+ name: string,
+ description: string,
+ path: string,
+ logo?: LogoType,
+ tag?: string
+}
+
+export type NavbarElement = {
+ text?: string,
+ logo?: [string, number],
+ path?: string,
+ dropdown?: NavbarDropdown[],
+}
+
+export interface Config {
+ projects: Project[],
+ logos: string[],
+ navbar: {
+ left: NavbarElement[],
+ right: NavbarElement[],
+ },
+} \ No newline at end of file