aboutsummaryrefslogtreecommitdiff
path: root/apps/website/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'apps/website/src/components')
-rw-r--r--apps/website/src/components/base/Button.astro57
-rw-r--r--apps/website/src/components/base/Header.astro13
-rw-r--r--apps/website/src/components/base/Navbar.astro4
-rw-r--r--apps/website/src/components/base/NavbarElement.astro32
-rw-r--r--apps/website/src/components/base/Section.astro17
-rw-r--r--apps/website/src/components/icons/ChevronDown.astro16
-rw-r--r--apps/website/src/components/icons/Icon.astro77
-rw-r--r--apps/website/src/components/icons/impl/book-open.svg3
-rw-r--r--apps/website/src/components/icons/impl/chevron-down.svg3
-rw-r--r--apps/website/src/components/icons/impl/download.svg3
-rw-r--r--apps/website/src/components/logos/Logo.astro4
11 files changed, 191 insertions, 38 deletions
diff --git a/apps/website/src/components/base/Button.astro b/apps/website/src/components/base/Button.astro
new file mode 100644
index 0000000..e0787c2
--- /dev/null
+++ b/apps/website/src/components/base/Button.astro
@@ -0,0 +1,57 @@
+---
+import type { Icons } from "@components/icons/Icon.astro";
+import Icon from "@components/icons/Icon.astro";
+import type { HTMLAttributes } from "astro/types";
+
+const styles = {
+ primary: "bg-blue-500 text-white hover:bg-blue-400 active:bg-blue-600 disabled:bg-blue-800 disabled:text-white-1/4",
+ secondary: "bg-blue-100 text-blue-500 hover:bg-blue-50 active:bg-blue-200 disabled:bg-blue-50 disabled:text-blue-200",
+}
+
+const sizes = {
+ sm: "px-4 py-2 text-sm",
+ md: "px-5 py-2 text-md",
+ lg: "px-6 py-3 text-lg rounded-2xl"
+}
+
+const iconSize = {
+ sm: 15,
+ md: 16,
+ lg: 24
+}
+
+interface Props extends HTMLAttributes<"button"> {
+ style?: keyof typeof styles
+ size?: keyof typeof sizes
+ text?: string
+ iconLeft?: Icons
+ iconRight?: Icons
+ href?: string
+}
+
+const {
+ style = "primary",
+ size = "md",
+ text = "",
+ iconLeft = "",
+ iconRight = "",
+ ...rest
+} = Astro.props;
+
+const className = [
+ "flex flex-row justify-center items-center text-center focus-visible:ring-offset-4 focus-visible:outline-offset-4",
+ "rounded-xl font-medium",
+ styles[style],
+ sizes[size],
+ "transition-colors",
+ rest.class
+].join(" ");
+
+const Element = rest.href ? "a" : "button" as any;
+---
+
+<Element {...rest} class={className}>
+ {iconLeft && <span class="mr-2"><Icon icon={iconLeft} size={iconSize[size]}></Icon></span>}
+ {text ? text : <slot />}
+ {iconRight && <span class="ml-2"><Icon icon={iconRight} size={iconSize[size]}></Icon></span>}
+</Element>
diff --git a/apps/website/src/components/base/Header.astro b/apps/website/src/components/base/Header.astro
index 1201798..aea04af 100644
--- a/apps/website/src/components/base/Header.astro
+++ b/apps/website/src/components/base/Header.astro
@@ -13,14 +13,21 @@ const sizes = {
type Headers = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
interface Props extends HTMLAttributes<Headers> {
- size: keyof typeof sizes;
+ size?: keyof typeof sizes;
+ align?: "left" | "center" | "right";
}
-const { size, ...attr } = Astro.props;
+const {
+ size = "lg",
+ align = "left",
+ ...attr
+} = Astro.props;
const Element = sizes[size] as any; // Unfortunately gotta do this
+
+const className = `text-${align}` + (attr.class ? ` ${attr.class}` : "");
---
-<Element {...attr}>
+<Element {...attr} class={className}>
<slot />
</Element>
diff --git a/apps/website/src/components/base/Navbar.astro b/apps/website/src/components/base/Navbar.astro
index f4f2f49..a3a82fe 100644
--- a/apps/website/src/components/base/Navbar.astro
+++ b/apps/website/src/components/base/Navbar.astro
@@ -5,7 +5,7 @@ import NavbarElement from "./NavbarElement.astro";
---
-<div class="w-full flex flex-row justify-center h-screen max-h-[110px] px-3">
+<div class="absolute 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) => (
@@ -18,4 +18,4 @@ import NavbarElement from "./NavbarElement.astro";
))}
</ul>
</nav>
-</div> \ No newline at end of file
+</div>
diff --git a/apps/website/src/components/base/NavbarElement.astro b/apps/website/src/components/base/NavbarElement.astro
index 4f82e8b..a7a0768 100644
--- a/apps/website/src/components/base/NavbarElement.astro
+++ b/apps/website/src/components/base/NavbarElement.astro
@@ -1,11 +1,12 @@
---
-import ChevronDown from "@components/icons/ChevronDown.astro";
+import ChevronDown from "@components/icons/ChevronDown.svg";
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";
+import Icon from "@components/icons/Icon.astro";
interface Props {
element: NavbarElement;
@@ -25,23 +26,24 @@ const {
<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 />}
+ {element.dropdown && <Icon icon="chevron-down" />}
</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 />}
+ {element.dropdown && <Icon icon="chevron-down" />}
</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
+ <input tabindex="-1" type="checkbox" id={`navbar-input-${index}`} class="peer appearance-none absolute">
+ <div class={`
+ transition-opacity
+ fixed md: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
@@ -50,9 +52,9 @@ const {
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
+ <ScrollbarOverlayContainer tabindex="-1" 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
@@ -62,9 +64,9 @@ const {
{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="transition-colors text-left w-full flex flex-row justify-start rounded-md items-center px-6 py-4 gap-6 hover:bg-blue-50">
<div class="w-[36px]">
- {item.logo && <Logo size={40} logo={item.logo} />}
+ {item.logo && <Logo size={40} logo={item.logo} />}
</div>
<div class="flex flex-col justify-start items-start">
@@ -74,7 +76,7 @@ const {
</div>
<p class="text-sm text-gray-400 font-light">{item.description}</p>
</div>
- </div>
+ </div>
</a>
</li>
))}
@@ -83,4 +85,4 @@ const {
</div>
)}
</label>
-</li> \ No newline at end of file
+</li>
diff --git a/apps/website/src/components/base/Section.astro b/apps/website/src/components/base/Section.astro
new file mode 100644
index 0000000..318056b
--- /dev/null
+++ b/apps/website/src/components/base/Section.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types";
+
+interface Props extends HTMLAttributes<"section"> {
+ maxWidth?: number;
+}
+
+const {
+ maxWidth = 800,
+ ...rest
+} = Astro.props;
+const className = `max-w-[${maxWidth}px] px-3 md:p-0 flex flex-col justify-center items-center h-screen md:h-4/5 md:min-h-[600px] gap-4` + (rest.class ? ` ${rest.class}` : "");
+---
+
+<section {...rest} class={className}>
+ <slot></slot>
+</section>
diff --git a/apps/website/src/components/icons/ChevronDown.astro b/apps/website/src/components/icons/ChevronDown.astro
deleted file mode 100644
index 5cb98e4..0000000
--- a/apps/website/src/components/icons/ChevronDown.astro
+++ /dev/null
@@ -1,16 +0,0 @@
----
-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/icons/Icon.astro b/apps/website/src/components/icons/Icon.astro
new file mode 100644
index 0000000..bf2b362
--- /dev/null
+++ b/apps/website/src/components/icons/Icon.astro
@@ -0,0 +1,77 @@
+---
+export type Icons = "chevron-down" | "download" | "book-open";
+
+import { parse } from 'node-html-parser';
+import type { HTMLAttributes } from "astro/types";
+
+interface Props extends HTMLAttributes<"svg"> {
+ icon: Icons;
+ size?: number | [number, number];
+}
+
+async function getSVG(name: string) {
+ const file = await import(`./impl/${name}.svg?raw` /* @vite-ignore */);
+
+ if (!file) {
+ throw new Error(`${name} not found`);
+ }
+
+ const content = parse(file.default);
+
+ const svg = content.querySelector('svg');
+
+ if (!svg) {
+ throw new Error(`${name} is not a valid SVG`);
+ }
+
+ const { attributes, innerHTML } = svg;
+
+ return {
+ attributes,
+ innerHTML,
+ };
+}
+
+const {
+ icon,
+ size,
+ ...attributes
+} = Astro.props as Props;
+
+let svgAttributes = {};
+let html = "";
+
+try {
+ const sizeAttributes = () => {
+ if (!size) {
+ return {};
+ }
+
+ if (Array.isArray(size)) {
+ return {
+ width: size[0],
+ height: size[1],
+ };
+ }
+
+ return {
+ width: size,
+ height: size,
+ };
+ }
+
+ const { attributes: baseAttributes, innerHTML } = await getSVG(icon);
+ svgAttributes = {
+ ...baseAttributes,
+ ...attributes,
+ ...sizeAttributes(),
+ };
+
+ const colorRegex = /(fill|stroke)=\"([^"]*)\"/g;
+ html = innerHTML.replaceAll(colorRegex, '$1="currentColor"');
+} catch (err) {
+
+}
+---
+
+<svg {...svgAttributes} set:html={html}></svg>
diff --git a/apps/website/src/components/icons/impl/book-open.svg b/apps/website/src/components/icons/impl/book-open.svg
new file mode 100644
index 0000000..37cf696
--- /dev/null
+++ b/apps/website/src/components/icons/impl/book-open.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 20H5.2C4.07989 20 3.51984 20 3.09202 19.782C2.71569 19.5903 2.40973 19.2843 2.21799 18.908C2 18.4802 2 17.9201 2 16.8V7.2C2 6.07989 2 5.51984 2.21799 5.09202C2.40973 4.71569 2.71569 4.40973 3.09202 4.21799C3.51984 4 4.07989 4 5.2 4H5.6C7.84021 4 8.96031 4 9.81596 4.43597C10.5686 4.81947 11.1805 5.43139 11.564 6.18404C12 7.03968 12 8.15979 12 10.4M12 20V10.4M12 20H18.8C19.9201 20 20.4802 20 20.908 19.782C21.2843 19.5903 21.5903 19.2843 21.782 18.908C22 18.4802 22 17.9201 22 16.8V7.2C22 6.07989 22 5.51984 21.782 5.09202C21.5903 4.71569 21.2843 4.40973 20.908 4.21799C20.4802 4 19.9201 4 18.8 4H18.4C16.1598 4 15.0397 4 14.184 4.43597C13.4314 4.81947 12.8195 5.43139 12.436 6.18404C12 7.03968 12 8.15979 12 10.4" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/apps/website/src/components/icons/impl/chevron-down.svg b/apps/website/src/components/icons/impl/chevron-down.svg
new file mode 100644
index 0000000..910a0b5
--- /dev/null
+++ b/apps/website/src/components/icons/impl/chevron-down.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
+ <path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/apps/website/src/components/icons/impl/download.svg b/apps/website/src/components/icons/impl/download.svg
new file mode 100644
index 0000000..cd8a6cb
--- /dev/null
+++ b/apps/website/src/components/icons/impl/download.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M21 15V16.2C21 17.8802 21 18.7202 20.673 19.362C20.3854 19.9265 19.9265 20.3854 19.362 20.673C18.7202 21 17.8802 21 16.2 21H7.8C6.11984 21 5.27976 21 4.63803 20.673C4.07354 20.3854 3.6146 19.9265 3.32698 19.362C3 18.7202 3 17.8802 3 16.2V15M17 10L12 15M12 15L7 10M12 15V3" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/apps/website/src/components/logos/Logo.astro b/apps/website/src/components/logos/Logo.astro
index 0532396..2fd6bea 100644
--- a/apps/website/src/components/logos/Logo.astro
+++ b/apps/website/src/components/logos/Logo.astro
@@ -10,7 +10,7 @@ export interface Props extends HTMLAttributes<"svg"> {
silent?: boolean,
}
-const {
+const {
logo,
silent = false,
size = undefined,
@@ -44,7 +44,7 @@ try {
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);
+
}
---