diff options
Diffstat (limited to 'apps/website/src/components/base')
17 files changed, 430 insertions, 245 deletions
diff --git a/apps/website/src/components/base/Button.astro b/apps/website/src/components/base/Button.astro index adbc656..e529dc5 100644 --- a/apps/website/src/components/base/Button.astro +++ b/apps/website/src/components/base/Button.astro @@ -1,26 +1,28 @@ --- -import type { Icons } from "@components/icons/Icon.astro"; -import Icon from "@components/icons/Icon.astro"; -import type { HTMLAttributes } from "astro/types"; +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-200 active:bg-blue-300 disabled:bg-blue-50 disabled:text-blue-200", -} + // TODO: adjust active / disabled colors + 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-20 text-blue-60 border-[1px] border-blue-30 hover:bg-blue-200 active:bg-blue-300 disabled:bg-blue-50 disabled:text-blue-200', + ghost: 'bg-transparent text-blue-500 hover:bg-blue-20 active:bg-blue-30 disabled:bg-transparent disabled:text-blue-200', +}; const sizes = { - sm: "px-4 py-2 text-sm", - md: "px-5 py-3 text-md", - lg: "px-6 py-3 text-lg rounded-2xl" -} + sm: 'px-4 py-2 text-sm', + md: 'px-5 py-3 text-md', + lg: 'px-6 py-3 text-lg rounded-2xl', +}; const iconSize = { - sm: 15, - md: 18, - lg: 24 -} + sm: 17, + md: 20, + lg: 24, +}; -interface Props extends HTMLAttributes<"button"> { +interface Props extends HTMLAttributes<'button'> { style?: keyof typeof styles size?: keyof typeof sizes text?: string @@ -30,28 +32,28 @@ interface Props extends HTMLAttributes<"button"> { } const { - style = "primary", - size = "md", - text = "", - iconLeft = "", - iconRight = "", + 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", + '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(" "); + 'transition-colors', + rest.class, +].join(' '); -const Element = rest.href ? "a" : "button" as any; +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> + <Element {...rest} class={className}> + {iconLeft && <span class="mr-2"><Icon icon={iconLeft} size={iconSize[size]}></Icon></span>} + {text || <slot/>} + {iconRight && <span class="ml-2"><Icon icon={iconRight} size={iconSize[size]}></Icon></span>} + </Element> diff --git a/apps/website/src/components/base/Card.astro b/apps/website/src/components/base/Card.astro new file mode 100644 index 0000000..6438273 --- /dev/null +++ b/apps/website/src/components/base/Card.astro @@ -0,0 +1,22 @@ +--- +import type { Icons } from '@components/icons/Icon.astro'; +import Icon from '@components/icons/Icon.astro'; +import type { HTMLAttributes } from 'astro/types'; + +interface Props extends HTMLAttributes<'div'> { + icon: Icons + text?: string +} + +const { + icon, + text = 'Hiiii', + ...rest +} = Astro.props; +--- + +<!-- pt-1 added temporarily cause for some reason the icon's padding doesn't apply unless I add this. the wonders of CSS. --> +<div {...rest} class="rounded-xl bg-primary-100 w-[256px] shrink-0"> + <Icon icon={icon} size={48} class="my-[28px] mx-auto text-white"></Icon> + <p class="text-white mx-auto bg-primary-200 rounded-b-xl text-[14px] py-[7px] pl-[12px] pr-[32px]">{text}</p> +</div> diff --git a/apps/website/src/components/base/CodeBlock.astro b/apps/website/src/components/base/CodeBlock.astro deleted file mode 100644 index 5991428..0000000 --- a/apps/website/src/components/base/CodeBlock.astro +++ /dev/null @@ -1,21 +0,0 @@ ---- - ---- - -<pre class="flex flex-col"> - <code class="whitespace-pre bg-white-light border border-gray-50 rounded-2xl text-sm">{`public class MyConfig { - - @Switch(name = "Sub Switch", type = OptionType.SWITCH) - public static boolean subSwitch = false; - - public MyConfig() { - super(new Mod("My Mod", ModType.UTIL_QOL), "config.json"); - - addDependency("subSwitch", () -> { - // TODO: Make codeblocks better lmao - }); - } - -}`}</code> -</pre> - diff --git a/apps/website/src/components/base/Footer.astro b/apps/website/src/components/base/Footer.astro index b24db5f..7a9071a 100644 --- a/apps/website/src/components/base/Footer.astro +++ b/apps/website/src/components/base/Footer.astro @@ -1,7 +1,47 @@ --- +import Icon from '@components/icons/Icon.astro'; +import Logo from '@components/logos/Logo.astro'; +import configConst from '@config'; +import type { HTMLAttributes } from 'astro/types'; +import Link from './Link.astro'; +interface Props extends HTMLAttributes<'footer'> {} + +const props = Astro.props; --- -<footer class="flex min-h-[400px] bg-blue-100 mt-4"> +<footer {...props} class="section flex justify-center items-center bg-blue-100 -mt-40 pt-20 pb-8 px-20"> + <div class="max-w-[1024px] w-full flex flex-col gap-y-24"> + <div class="flex flex-col gap-y-20 justify-center items-start md:flex-row md:items-start md:justify-between"> + <div class="flex-1 flex flex-col gap-y-3 text-blue-gray"> + <Logo logo="polyfrost.full" /> + <p>English, USA</p> {/* hardcoded for now, todo i18n */} + <div class="flex flex-row gap-3"> + <a href={configConst.socials.discord} target="_blank" class="hover:text-[#5865F2]"><Icon icon="discord" /></a> + <a href={configConst.socials.youtube} target="_blank" class="hover:text-[#ff0000]"><Icon icon="youtube" /></a> + <a href={configConst.socials.github} target="_blank" class="hover:text-[#000000]"><Icon icon="github" /></a> + </div> + </div> + + <div class="flex-1 flex flex-col md:flex-row justify-end gap-8"> + {configConst.footer.map(column => ( + <div class="flex flex-col gap-y-3"> + <h3 class="text-gray-700 text-md">{column.header}</h3> + <ul class="flex flex-col gap-y-1"> + {column.links.map(link => ( + <li> + <Link href={link.url} class="text-blue-gray text-sm text-nowrap">{link.text}</Link> + </li> + ))} + </ul> + </div> + ))} + </div> + </div> + <div class="flex flex-col items-center md:flex-row md:items-start md:justify-between"> + <p class="text-blue-gray text-sm">© {new Date().getFullYear()} Polyfrost. All rights reserved.</p> + <p class="text-blue-gray text-sm">Not an official Minecraft product. Not approved by or affiliated with Mojang Studios.</p> + </div> + </div> </footer> diff --git a/apps/website/src/components/base/FormattedDate.astro b/apps/website/src/components/base/FormattedDate.astro new file mode 100644 index 0000000..af538b9 --- /dev/null +++ b/apps/website/src/components/base/FormattedDate.astro @@ -0,0 +1,17 @@ +--- +interface Props { + date: Date +} + +const { date } = Astro.props; +--- + + <time datetime={date.toISOString()}> + { + date.toLocaleDateString('en-us', { + year: 'numeric', + month: 'short', + day: 'numeric', + }) + } + </time> diff --git a/apps/website/src/components/base/Header.astro b/apps/website/src/components/base/Header.astro index d35ad9f..962b2d4 100644 --- a/apps/website/src/components/base/Header.astro +++ b/apps/website/src/components/base/Header.astro @@ -1,41 +1,54 @@ --- -import type { HTMLAttributes } from "astro/types" +import type { HTMLAttributes } from 'astro/types'; const sizes = { - "xxl": "h1", - "xl": "h2", - "lg": "h2", - "md": "h3", - "sm": "h4", - "xs": "h5", - "xxs": "h6" + xxl: 'h1', + xl: 'h2', + lg: 'h2', + md: 'h3', + sm: 'h4', + xs: 'h5', + xxs: 'h6', }; -type Headers = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; +type Headers = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; interface Props extends HTMLAttributes<Headers> { - size?: keyof typeof sizes; - align?: "left" | "center" | "right" | "inherit"; + size?: keyof typeof sizes + align?: 'left' | 'center' | 'right' | 'inherit' + inheritSize?: boolean } const { - size = "lg", - align = "inherit", + size = 'lg', + align = 'inherit', + inheritSize = false, ...attr } = Astro.props; const Element = sizes[size] as any; // Unfortunately gotta do this -const className = (align == "inherit" ? "" : `text-${align} `) - + (size == "xxl" ? " page-header" : "") - + (attr.class ? ` ${attr.class}` : ""); +let className: string | string[] = []; +if (!inheritSize) + className.push('header'); + +if (align !== 'inherit') + className.push(`text-${align}`); + +if (size === 'xxl' || size === 'xl') + className.push('page-header'); + +if (attr.class) + className.push(attr.class); + +className = className.join(' '); --- <Element {...attr} class={className}> - <slot /> + <slot/> </Element> <style> - h1 { + h1.header { font-size: theme("fontSize.header-lg"); &.page-header { font-size: theme("fontSize.header-page"); @@ -43,27 +56,30 @@ const className = (align == "inherit" ? "" : `text-${align} `) font-weight: 600; } - h2 { + h2.header { font-size: theme("fontSize.header"); + &.page-header { + font-size: theme("fontSize.header-page"); + } font-weight: 600; } - h3 { + h3.header { font-size: theme("fontSize.header-sm"); font-weight: 600; } - h4 { + h4.header { font-size: theme("fontSize.body-lg"); font-weight: 500; } - h5 { + h5.header { font-size: theme("fontSize.body"); font-weight: 500; } - h6 { + h6.header { font-size: theme("fontSize.body-sm"); font-weight: 500; } diff --git a/apps/website/src/components/base/Link.astro b/apps/website/src/components/base/Link.astro new file mode 100644 index 0000000..dfb6425 --- /dev/null +++ b/apps/website/src/components/base/Link.astro @@ -0,0 +1,17 @@ +--- +import type { HTMLAttributes } from 'astro/types'; + +interface Props extends HTMLAttributes<'a'> { + +} + +const props = Astro.props; +const className = [ + 'text-current hover:text-blue-500 underline decoration-[transparent] hover:decoration-blue-500 transition-colors', + props.class, +].join(' '); +--- + +<a class={className} {...props}> + <slot /> +</a> diff --git a/apps/website/src/components/base/Navbar.astro b/apps/website/src/components/base/Navbar.astro deleted file mode 100644 index a3a82fe..0000000 --- a/apps/website/src/components/base/Navbar.astro +++ /dev/null @@ -1,21 +0,0 @@ ---- -import config from "config"; -import type { Config } from "@webtypes/Config"; -import NavbarElement from "./NavbarElement.astro"; - ---- - -<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) => ( - <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> diff --git a/apps/website/src/components/base/NavbarElement.astro b/apps/website/src/components/base/NavbarElement.astro deleted file mode 100644 index b0f1282..0000000 --- a/apps/website/src/components/base/NavbarElement.astro +++ /dev/null @@ -1,89 +0,0 @@ ---- -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; - 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 && <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 && <Icon icon="chevron-down" />} - </p> - )} - - {element.dropdown && ( - <ScreenOverlay class="max-sm:group-focus-within:opacity-100" /> - <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 - - 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 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 - max-h-full md:max-h-96 overflow-y-auto - md:shadow-lg - `}> - <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-blue-50"> - <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> diff --git a/apps/website/src/components/base/Paragraph.astro b/apps/website/src/components/base/Paragraph.astro index 08fbbdd..db0bff6 100644 --- a/apps/website/src/components/base/Paragraph.astro +++ b/apps/website/src/components/base/Paragraph.astro @@ -1,31 +1,31 @@ --- -import type { HTMLAttributes } from "astro/types"; +import type { HTMLAttributes } from 'astro/types'; const sizes = { - xs: "text-xs", - sm: "text-sm", - md: "text-md", - lg: "text-lg", - xl: "text-xl" -} + xs: 'text-xs', + sm: 'text-sm', + md: 'text-inherit', + lg: 'text-lg', + xl: 'text-xl', +}; -interface Props extends HTMLAttributes<"p"> { - text?: string, +interface Props extends HTMLAttributes<'p'> { + text?: string size?: keyof typeof sizes } const { - text = "", - size = "md", + text = '', + size = 'md', ...props } = Astro.props; const className = [ sizes[size], - props.class -].join(" "); + props.class, +].join(' '); --- <p class={className} {...props}> - {text ? text : <slot />} + {text || <slot/>} </p> diff --git a/apps/website/src/components/base/ScreenOverlay.astro b/apps/website/src/components/base/ScreenOverlay.astro index 7be8bc5..1b97152 100644 --- a/apps/website/src/components/base/ScreenOverlay.astro +++ b/apps/website/src/components/base/ScreenOverlay.astro @@ -1,16 +1,16 @@ --- -import type { HTMLAttributes } from "astro/types"; +import type { HTMLAttributes } from 'astro/types'; -interface Props extends HTMLAttributes<"div"> { - zIndex?: number; +interface Props extends HTMLAttributes<'div'> { + zIndex?: number } const { - zIndex = 0, - ...rest + 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 + <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> diff --git a/apps/website/src/components/base/ScrollbarOverlayContainer.astro b/apps/website/src/components/base/ScrollbarOverlayContainer.astro index d8d315d..235dbc7 100644 --- a/apps/website/src/components/base/ScrollbarOverlayContainer.astro +++ b/apps/website/src/components/base/ScrollbarOverlayContainer.astro @@ -1,21 +1,21 @@ --- -import type { HTMLAttributes } from "astro/types"; +import type { HTMLAttributes } from 'astro/types'; -interface Props extends HTMLAttributes<"div"> { +interface Props extends HTMLAttributes<'div'> { } const { ...attr } = Astro.props; --- -<div {...attr}> - <slot></slot> -</div> + <div {...attr}> + <slot></slot> + </div> -<style> + <style> @media (hover: hover) { div { - + } div::-webkit-scrollbar { @@ -48,4 +48,4 @@ const { ...attr } = Astro.props; background-color: #00000040; } } -</style>
\ No newline at end of file + </style> diff --git a/apps/website/src/components/base/Section.astro b/apps/website/src/components/base/Section.astro index 0d177ef..6ea3075 100644 --- a/apps/website/src/components/base/Section.astro +++ b/apps/website/src/components/base/Section.astro @@ -1,38 +1,45 @@ --- -import type { HTMLAttributes } from "astro/types"; +import type { HTMLAttributes } from 'astro/types'; -interface Props extends HTMLAttributes<"section"> { - maxWidth?: "none" | String; - colReverse?: boolean; - wrapperClass?: string; +interface Props extends HTMLAttributes<'section'> { + maxWidth?: 'none' | String + colReverse?: boolean + wrapperClass?: string + wFull?: boolean + hFull?: boolean } const { - maxWidth = "1080px", + maxWidth = '1024px', colReverse = true, - wrapperClass = "", + wrapperClass = '', + wFull = true, + hFull = false, ...props } = Astro.props; -const twoColumn = Astro.slots.has("left") || Astro.slots.has("right"); +const twoColumn = Astro.slots.has('left') || Astro.slots.has('right'); -const className = `max-w-[${maxWidth}] w-full px-5 md:p-0 flex gap-4` - + (twoColumn ? ` ${maxWidth == "none" ? "justify-center" : "justify-between md:justify-evenly lg:justify-between"} ${colReverse ? "flex-col-reverse" : "flex-col"} md:flex-row md:items-center md:flex-row` : "") - + (props.class ? ` ${props.class}` : ""); +const twoColumnClasses = ` ${maxWidth === 'none' ? 'justify-center' : 'justify-center lg:justify-between'} + ${colReverse ? 'flex-col-reverse' : 'flex-col'} lg:flex-row items-center`; + +const className = `max-w-[${maxWidth}] ${hFull ? 'min-h-screen' : 'h-auto'} ${wFull ? 'w-full' : `w-[${maxWidth}]`} px-5 xl:px-0 flex gap-x-20 gap-y-4${twoColumn ? twoColumnClasses : ''}${props.class ? ` ${props.class}` : ''}`; --- -<section class={`w-full flex justify-center${wrapperClass ? ` ${wrapperClass}` : ""}`}> +<section class={`w-full outline-none flex justify-center ${wrapperClass ?? ''}`}> <div class={className} {...props}> - {twoColumn ? ( - <div class="flex flex-col items-start text-left relative"> - <slot name="left"></slot> - </div> + {twoColumn + ? ( + <div class="flex flex-col items-center text-center w-full md:w-auto md:items-start md:text-left relative"> + <slot name="left"></slot> + </div> - <div class="flex flex-col items-start text-left relative"> - <slot name="right"></slot> - </div> - ) : ( - <slot></slot> - )} + <div class="flex flex-col items-center text-center w-full md:w-auto md:items-start md:text-left relative"> + <slot name="right"></slot> + </div> + ) + : ( + <slot></slot> + )} </div> </section> diff --git a/apps/website/src/components/base/Slider.astro b/apps/website/src/components/base/Slider.astro new file mode 100644 index 0000000..1afd680 --- /dev/null +++ b/apps/website/src/components/base/Slider.astro @@ -0,0 +1,73 @@ +--- +import type { HTMLAttributes } from 'astro/types'; + +interface Props extends HTMLAttributes<'div'> { + dir?: string + wrapperClass?: string + childrenNum: number + childrenSize?: string + speed?: string +} + +const { + dir = 'left', + wrapperClass = '', + childrenNum, + childrenSize = '256px', + speed = '25s', +} = Astro.props; + +--- + +<div class={ + `w-full slider + ${dir === 'right' ? 'reverse' : ''} + ${wrapperClass}` +}> + <div class="wrapper flex flex-row gap-2.5"> + <slot class="content" /> + <slot class="content" /> + </div> +</div> + +<!-- + credit to modrinth's implementation! here is their CSS code: + https://github.com/modrinth/knossos/blob/d6ba3f3adfd8f52b85f83e53660d3d87cd0bc9ea/pages/index.vue#L620-L675 + oh and since theirs is in AGPL, please note that this codeblock is also AGPL +--> +<style lang="scss" define:vars={{ childrenNum, childrenSize, speed }}> + .slider { + .wrapper { + animation: var(--speed) linear infinite slide; + @media (prefers-reduced-motion) { + animation: none; + } + @keyframes slide { + from { + transform: translateX(0); + } + to { + transform: translateX(calc((var(--childrenSize) + 10px) * -1 * var(--childrenNum))); + } + } + } + + /** + &:hover > .wrapper, &.reverse:hover > .wrapper { + animation-play-state: paused; + } + */ + + &.reverse > .wrapper { + animation: var(--speed) linear infinite slide-reverse; + @keyframes slide-reverse { + from { + transform: translateX(calc((var(--childrenSize) + 10px) * -1 * var(--childrenNum))); + } + to { + transform: translateX(0); + } + } + } + } +</style> diff --git a/apps/website/src/components/base/Tag.astro b/apps/website/src/components/base/Tag.astro index e6fd34f..2eb5778 100644 --- a/apps/website/src/components/base/Tag.astro +++ b/apps/website/src/components/base/Tag.astro @@ -1,14 +1,13 @@ --- -import type { HTMLAttributes } from "astro/types"; +import type { HTMLAttributes } from 'astro/types'; -interface Props extends HTMLAttributes<"span"> {} +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 class="leading-none 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/base/navbar/Navbar.astro b/apps/website/src/components/base/navbar/Navbar.astro new file mode 100644 index 0000000..8903b7e --- /dev/null +++ b/apps/website/src/components/base/navbar/Navbar.astro @@ -0,0 +1,23 @@ +--- +import type { Config } from '@webtypes/Config'; +import type { HTMLAttributes } from 'astro/types'; +import config from 'config'; +import NavbarElement from '../navbar/NavbarElement.astro'; + +interface Props extends HTMLAttributes<'div'> {} +const props = Astro.props; +--- +<div {...props} class="absolute w-full flex flex-row justify-center h-screen max-h-[110px] px-3 z-navbar text-[16px]"> + <nav class="w-full max-w-[1024px] flex flex-col md:flex-row justify-between items-center"> + <ul class="flex flex-row justify-start gap-4 max-md:mt-4"> + {(config as Config).navbar.left.map((element, index) => ( + <NavbarElement {element} {index}/> + ))} + </ul> + <ul class="flex flex-row justify-center md:justify-end gap-4 flex-wrap"> + {(config as Config).navbar.right.map((element, index) => ( + <NavbarElement {element} {index}/> + ))} + </ul> + </nav> +</div> diff --git a/apps/website/src/components/base/navbar/NavbarElement.astro b/apps/website/src/components/base/navbar/NavbarElement.astro new file mode 100644 index 0000000..5e37253 --- /dev/null +++ b/apps/website/src/components/base/navbar/NavbarElement.astro @@ -0,0 +1,100 @@ +--- +import Icon from '@components/icons/Icon.astro'; +import Logo from '@components/logos/Logo.astro'; +import type { LogoType, NavbarElement } from '@webtypes/Config'; +import Header from '../Header.astro'; +import ScreenOverlay from '../ScreenOverlay.astro'; +import ScrollbarOverlayContainer from '../ScrollbarOverlayContainer.astro'; +import Tag from '../Tag.astro'; + +interface Props { + element: NavbarElement + index: number +} + +const { + element, + index, +} = Astro.props; + +function isCurrentPage(url: string): boolean { + return Astro.url.pathname === url; +} + +--- + + <li class="sm:relative max-sm:overflow-hidden flex flex-row justify-center items-center text-center"> + {element.path +? ( + <a href={element.path} class={`p-2 flex flex-row justify-center items-center hover:text-blue-500 ${isCurrentPage(element.path) ? 'text-blue-400' : 'text-gray-700'}`}> + {element.text && element.text} + {element.logo && <Logo class="active:scale-95 transition-transform" size={element.logo[1] < 0 ? undefined : element.logo[1]} logo={element.logo[0] as LogoType}/>} + {element.dropdown && <Icon icon="chevron-down"/>} + </a> + ) +: ( + <label for={`navbar-input-${index}`} class="group"> + {element.dropdown && ( + <p class={`p-2 flex flex-row justify-center items-center hover:text-blue-500 cursor-default ${isCurrentPage(element.dropdown[0].path ?? '') ? 'text-blue-400' : 'text-gray-700'}`}> + {element.text && element.text} + {element.logo && <Logo size={element.logo[1] < 0 ? undefined : element.logo[1]} logo={element.logo[0] as LogoType}/>} + {element.dropdown && <Icon icon="chevron-down"/>} + </p> + + <ScreenOverlay class="max-sm:group-focus-within:opacity-100 z-navbar-backdrop"/> + <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 + z-navbar + + md:top-full md:right-0 + + group-focus-within:pointer-events-auto group-focus-within:opacity-100 + md:group-hover:pointer-events-auto md:group-hover:opacity-100 + focus-within:pointer-events-auto focus-within:opacity-100 + md:hover:pointer-events-auto md:hover:opacity-100 + `}> + <ScrollbarOverlayContainer + tabindex="-1" + class={` + bg-gray-50 + border border-gray-100 + 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 min-h-full + md:shadow-lg + `}> + <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-[color,background-color,filter] text-left w-full flex flex-row justify-start rounded-md items-center px-6 py-4 gap-6 ${item.path ? 'hover:bg-blue-50 active:bg-blue-100' : 'hover:grayscale hover:brightness-75'}`}> + <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 inheritSize size="md" class="text-gray-800 text-md md:text-sm font-medium">{item.name}</Header> + {item.tag && <Tag class="text-sm md:text-xxs">{item.tag}</Tag>} + </div> + <p class="text-md md:text-sm text-gray-400 font-light">{item.description}</p> + </div> + </div> + </a> + </li> + ))} + </ul> + </ScrollbarOverlayContainer> + </div> + )} + </label> +)} + </li> +{/* WHY IS ESLINT DOING THIS */} |