Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Layout Components #56

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@
],
"prettier": {
"printWidth": 120,
"semi": false
"semi": false,
"plugins": [
"prettier-plugin-astro"
],
"overrides": [
{
"files": "*.astro",
"options": {
"parser": "astro"
}
}
]
}
}
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/components/layout/Box.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="bg-gray-900/70 border border-gray-800/50 rounded-none md:rounded-xl min-h-52 -mx-4 md:mx-0">
<slot />
</div>
5 changes: 5 additions & 0 deletions src/components/layout/Header.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div
class="relative -mt-20 border-b border-white/5 bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 pt-20 [--tw-gradient-via-position:40%] md:-mt-16 md:pt-16"
>
<slot />
</div>
18 changes: 18 additions & 0 deletions src/components/layout/HeaderContent.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
import { styles } from "../../lib/theme"

interface Props {
section?: string
title?: string
}

const { title, section } = Astro.props
---

<div class:list={[styles.layout.container, styles.layout.containerPadding]}>
<div class="py-12">
{section && <p class="mb-2 text-base font-bold text-white/60">{section}</p>}
{title && <h1 class="text-xl font-black text-white/90 md:text-3xl">{title}</h1>}
<slot />
</div>
</div>
38 changes: 38 additions & 0 deletions src/components/layout/HeaderMeta.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
import { styles } from "../../lib/theme"

type MetaItem = { label: string; icon?: Promise<typeof import("*.svg?raw")> }
interface Props {
items?: MetaItem[]
}

const items = await Promise.all(
Astro.props.items
? Astro.props.items.map(async (item) => {
return {
...item,
icon: item.icon ? (await item.icon)?.default : undefined,
}
})
: []
)
---

<div class="bg-black/20">
<div
class:list={[
styles.layout.container,
styles.layout.containerPadding,
"flex flex-wrap items-center gap-y-4 gap-4 md:gap-8 py-4",
]}
>
{
items?.map(({ label, icon }) => (
<div class="flex items-center gap-2">
{icon && <span class="text-white opacity-20 *:h-4 *:w-4 md:*:h-5 md:*:w-5" set:html={icon} />}
<span class="text-xs font-bold text-white/30 md:text-sm">{label}</span>
</div>
))
}
</div>
</div>
53 changes: 53 additions & 0 deletions src/components/layout/HeaderNav.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
import { styles } from "../../lib/theme"
const currentRoute = new URL(Astro.request.url).pathname
type Link = {
label: string
href?: string
}

interface Props {
/** The breadcrumb up to but excluding current page */
breadcrumb?: Link[]
/** The current page or current and sibling pages/tabs */
current: Link | Link[]
}
const { breadcrumb, current } = Astro.props
const tabs = Array.isArray(current) ? current : [current]
---

<div class="scrollbar-hide overflow-x-auto border-b border-white/7 bg-white/3">
<div
class:list={[
styles.layout.container,
styles.layout.containerPadding,
"flex items-center gap-y-4 gap-4 sm:gap-8 py-2 font-extrabold text-xs md:text-sm whitespace-nowrap",
]}
>
{
breadcrumb?.map(({ label, href }) => (
<>
<a href={href} class:list={["text-white/50", tabs.length > 1 && "hidden sm:inline"]}>
{label}
</a>
<span class:list={["text-white/35 w-2 -mx-2 text-center", tabs.length > 1 && "hidden sm:inline"]}>/</span>
</>
))
}
{
tabs.map(({ label, href }) => (
<>
<a
href={href}
class:list={[
"text-xs md:text-sm font-bold",
href == currentRoute ? "text-white/90" : "text-white/50 hover:text-white/100",
]}
>
{label}
</a>
</>
))
}
</div>
</div>
7 changes: 7 additions & 0 deletions src/components/layout/Main.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
import { styles } from "../../lib/theme"
---

<div class:list={["basis-2/3 flex flex-col", styles.layout.gap]}>
<slot />
</div>
58 changes: 58 additions & 0 deletions src/components/layout/MainNav.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
import { styles } from "../../lib/theme"
const currentRoute = new URL(Astro.request.url).pathname
const navLinks = [
{ href: "/dev/example", text: "Home" },
{ href: "/leaderboards/ranked_1v1", text: "Leaderboard" },
{ href: "/stats", text: "Stats" },
{ href: "/social", text: "Content" },
{ href: "/api", text: "API" },
{ href: "/tools", text: "Tools" },
// { href: "/creators", text: "Creators" },
]
---

<div
class="to-black-20 relative z-10 h-20 w-full border-b border-white/10 bg-gradient-to-r from-black/20 via-black/5 mix-blend-screen md:h-16"
>
<nav
class:list={[
styles.layout.container,
"flex flex-wrap md:flex-nowrap items-center gap-y-2 py-2 md:min-h-16 md:py-4",
]}
>
<a
href="/"
class:list={[
styles.layout.containerPadding,
"basis-full whitespace-nowrap md:pr-2 text-xl font-extrabold text-white/90 md:basis-auto ",
]}
>
Stormgate World
</a>

<div
class:list={[
styles.layout.containerPadding,
"scrollbar-hide -ml-2 flex max-w-full flex-auto gap-1 gap-y-2 overflow-x-auto md:ml-0 md:gap-4 md:pr-7",
]}
>
{
navLinks.map(({ href, text }) => (
<a
href={href}
class:list={[
"font-extrabold rounded px-2 text-sm md:text-base md:px-3 py-1 md:py-1.5",
currentRoute === href ? "bg-white/5 text-white/80" : "hover:bg-white/5 text-white/60 ",
]}
>
{text}
</a>
))
}

<div class="flex-auto"></div>
<div>{/*search etc */}</div>
</div>
</nav>
</div>
30 changes: 30 additions & 0 deletions src/components/layout/Section.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
import { styles } from "../../lib/theme"

interface Props {
title?: string
description?: string
}
const { title, description } = Astro.props
const hasHeader = title || description || Astro.slots.header || Astro.slots.controls
---

<div class:list={[styles.layout.container, styles.layout.containerPadding, "pt-4 md:pt-6"]}>
{
hasHeader && (
<div class="flex justify-between my-4 md:my-6 gap-4">
<div class="flex-auto">
{title && <h2 class="text-2xl font-bold text-white">{title}</h2>}
{description && <p class="text-gray-400">{description}</p>}
<slot name="header" />
</div>
<div class="flex-none">
<slot name="controls" />
</div>
</div>
)
}
<div class:list={["flex flex-col lg:flex-row", styles.layout.gap]}>
<slot />
</div>
</div>
9 changes: 9 additions & 0 deletions src/components/layout/Sidebar.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
import { styles } from "../../lib/theme"
---

<div
class:list={["flex md:grid grid-cols-2 only:*:[grid-column:span_2] basis-1/3 lg:flex flex-col", styles.layout.gap]}
>
<slot />
</div>
15 changes: 15 additions & 0 deletions src/layouts/New.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
import Root from "./Root.astro"
import MainNav from "../components/layout/MainNav.astro"
export interface Props {
title: string
}

const { title } = Astro.props
---

<Root title={title}>
<MainNav />
<slot />
<div class="py-32 text-center border-t mt-4 md:mt-8 border-gray-900">Footer</div>
</Root>
6 changes: 6 additions & 0 deletions src/layouts/Root.astro
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@ const { title } = Astro.props
</head>
<body class="bg-body text-body font-body scroll-pt-24 bg-gray-950 text-white antialiased">
<slot />
<style is:global>
.scrollbar-hide {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
</style>
</body>
</html>
5 changes: 5 additions & 0 deletions src/lib/theme.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export const styles = {
layout: {
containerPadding: `px-4 md:px-8`,
container: `mx-auto max-w-screen-xl`,
gap: `gap-4 md:gap-6`,
},
button: {
base: `inline-flex items-center justify-center rounded-sm
bg-gray-800/85 border border-gray-700 backdrop-blur-sm
Expand Down
65 changes: 65 additions & 0 deletions src/pages/dev/example.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
import Layout from "../../layouts/New.astro"
import Header from "../../components/layout/Header.astro"
import HeaderContent from "../../components/layout/HeaderContent.astro"
import HeaderMeta from "../../components/layout/HeaderMeta.astro"
import HeaderNav from "../../components/layout/HeaderNav.astro"
import Section from "../../components/layout/Section.astro"
import Main from "../../components/layout/Main.astro"
import Sidebar from "../../components/layout/Sidebar.astro"
import Box from "../../components/layout/Box.astro"
---

<Layout title="Test">
{
/* The Main Navigation is contained within Layout, the main nav is semi-transparent overlayed on top of the header.
Ideally all pages have an header */
}
<Header>
{/* The Header contains the main gradient/color used for tinting */}
<HeaderNav
breadcrumb={[
{ href: "#", label: "Development" },
{ href: "#", label: "Layout" },
]}
current={[
{ href: "/dev/example", label: "Example Page" },
{ href: "#", label: "An other tab" },
{ href: "#", label: "Example 3" },
]}
/>
{/* Optional, for including breadcrumbs as well as a list of subpages/tabs that are available */}

<HeaderContent title={"Example Page"} section="Development">
{/* Very simple header, always. At most some visual and text and not too much UI */}
{/* Slot content can be used in plage of standard title */}
</HeaderContent>
<HeaderMeta
items={[
{ icon: import("lucide-static/icons/activity.svg?raw"), label: "Last active 3 hours ago" },
{ icon: import("lucide-static/icons/calendar.svg?raw"), label: "March 12, 2024" },
{ icon: import("lucide-static/icons/hash.svg?raw"), label: "s83akdy" },
]}
>
{/* Optional for 'stats' like last updated, last game data, user id, etc */}
</HeaderMeta>
</Header>
<Section>
<Main>
<Box />
<Box />
</Main>
<Sidebar>
<Box />
<Box />
</Sidebar>
</Section>
<Section title="Subsection" description="More info here">
<Main>
<Box />
</Main>
<Sidebar>
<Box />
</Sidebar>
</Section>
</Layout>
8 changes: 4 additions & 4 deletions src/pages/players/[id]-[username].astro
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ const highestLeague = player?.leaderboard_entries?.reduce(

<Layout title={player?.nickname}>
<div class="w-full border-b border-gray-700/50 bg-gray-800/50 backdrop-blur-lg">
<div class="mx-auto flex max-w-screen-lg flex-wrap items-center gap-4 px-4 md:px-8 py-4">
<div class="flex-auto flex items-center gap-3">
{player.avatar_url ? <img src={player.avatar_url} alt={player.nickname} class="rounded-sm w-6 md:w-8" /> : <></>}
<h1 class="flex-auto text-lg md:text-2xl font-bold text-gray-50">{player.nickname}</h1>
<div class="mx-auto flex max-w-screen-lg flex-wrap items-center gap-4 px-4 py-4 md:px-8">
<div class="flex flex-auto items-center gap-3">
{player.avatar_url && <img src={player.avatar_url} alt={player.nickname} class="w-6 rounded-sm md:w-8" />}
<h1 class="flex-auto text-lg font-bold text-gray-50 md:text-2xl">{player.nickname}</h1>
</div>
<RankedBadge entry={highestLeague} class="w-16 md:w-20" client:load />
</div>
Expand Down
Loading
Loading