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

feat: add compound layout component #1363

Merged
merged 12 commits into from
Jul 11, 2024
6 changes: 3 additions & 3 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { StorybookConfig } from "@storybook/nextjs"
import type { StorybookConfig } from "@storybook/nextjs";

const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
Expand All @@ -20,5 +20,5 @@ const config: StorybookConfig = {
disable: true,
},
},
}
export default config
};
export default config;
7 changes: 6 additions & 1 deletion src/v2/components/GuildAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ interface Props extends React.HTMLAttributes<HTMLDivElement> {
}

const GuildAvatar = memo(({ address, className }: Props) => {
const addressEnding = address
?.toLowerCase()
?.slice(-2) as keyof typeof addressAvatarPairs

const Avatar = dynamic(
() =>
// webpack can't resolve the dynamic import path when running storybook, so we just pass the first svg manually there
import(
`static/avatars/${addressAvatarPairs[address?.toLowerCase()?.slice(-2)]}.svg`
`static/avatars/${process.env.STORYBOOK ? 1 : addressAvatarPairs[addressEnding]}.svg`
)
)

Expand Down
22 changes: 22 additions & 0 deletions src/v2/components/Layout/Layout.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Meta, StoryFn } from "@storybook/react"
import { Layout } from "."

const meta: Meta = {
title: "Design system/Layout",
parameters: {
layout: "fullscreen",
},
}

export default meta

export const Static: StoryFn = () => (
<Layout.Root>
<Layout.Hero>
<Layout.Banner />
<Layout.Headline title="Layout title" />
</Layout.Hero>
<Layout.Main>Page contents</Layout.Main>
<Layout.Footer />
</Layout.Root>
)
108 changes: 108 additions & 0 deletions src/v2/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { cn } from "@/lib/utils"
import { Slot } from "@radix-ui/react-slot"
import clsx from "clsx"
import { PropsWithChildren, ReactNode, forwardRef } from "react"

/* -------------------------------------------------------------------------------------------------
* Root
* -----------------------------------------------------------------------------------------------*/

const Root = ({ children }: PropsWithChildren) => (
<div className="flex min-h-screen flex-col">{children}</div>
)

/* -------------------------------------------------------------------------------------------------
* PageContainer
* -----------------------------------------------------------------------------------------------*/

export interface PageContainerProps extends React.HTMLAttributes<HTMLDivElement> {
asChild?: boolean
}

const PageContainer = forwardRef<HTMLDivElement, PageContainerProps>(
({ children, className, asChild = false }, ref) => {
const Comp = asChild ? Slot : "div"
return (
<Comp
className={clsx("mx-auto max-w-screen-lg px-4 sm:px-8 md:px-10", className)}
ref={ref}
>
{children}
</Comp>
)
}
)

/* -------------------------------------------------------------------------------------------------
* Hero
* -----------------------------------------------------------------------------------------------*/

const Hero = ({ children }: PropsWithChildren) => (
<div className="relative">{children}</div>
)

/* -------------------------------------------------------------------------------------------------
* Headline
* -----------------------------------------------------------------------------------------------*/

interface HeadlineProps {
title: ReactNode
}

const Headline = ({ title }: HeadlineProps) => (
<PageContainer>
<h1 className="pt-9 pb-14 font-bold font-display text-4xl text-white tracking-tight sm:text-5xl">
{title}
</h1>
</PageContainer>
)

/* -------------------------------------------------------------------------------------------------
* Banner
* -----------------------------------------------------------------------------------------------*/

interface BannerProps extends PropsWithChildren {
offset?: number
className?: string
}

const Banner = ({ children, offset = 112, className }: BannerProps) => (
<div
className={cn(
"-z-10 absolute inset-0 overflow-hidden",
`-bottom-[${Math.abs(offset)}px]`
)}
>
<div
className={cn(
"absolute inset-0 bg-[hsl(240_4%_16%)] data-[theme='dark']:bg-[hsl(240_3%_22%)]",
className
)}
/>
{children}
</div>
)

/* -------------------------------------------------------------------------------------------------
* Main
* -----------------------------------------------------------------------------------------------*/

const Main = ({ children }: PropsWithChildren) => (
<main>
<PageContainer>{children}</PageContainer>
</main>
)

/* -------------------------------------------------------------------------------------------------
* Footer
* -----------------------------------------------------------------------------------------------*/

const Footer = ({ children }: PropsWithChildren) => (
<footer className="mt-auto">
<PageContainer>{children}</PageContainer>
</footer>
)

/* -----------------------------------------------------------------------------------------------*/

export { Banner, Footer, Headline, Hero, Main, PageContainer, Root }
4 changes: 4 additions & 0 deletions src/v2/components/Layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Header } from "@/components/Header"
import { Banner, Footer, Headline, Hero, Main, Root } from "./Layout"

export const Layout = { Root, Headline, Banner, Hero, Footer, Main, Header }
Loading